1 /* 2 * Copyright (c) 2010 Broadcom Corporation 3 * 4 * Permission to use, copy, modify, and/or distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 11 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 13 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 14 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 #include <linux/kernel.h> 17 #include <linux/delay.h> 18 #include <linux/bitops.h> 19 20 #include <brcm_hw_ids.h> 21 #include <chipcommon.h> 22 #include <aiutils.h> 23 #include <d11.h> 24 #include <phy_shim.h> 25 #include "phy_hal.h" 26 #include "phy_int.h" 27 #include "phy_radio.h" 28 #include "phy_lcn.h" 29 #include "phyreg_n.h" 30 31 #define VALID_N_RADIO(radioid) ((radioid == BCM2055_ID) || \ 32 (radioid == BCM2056_ID) || \ 33 (radioid == BCM2057_ID)) 34 35 #define VALID_LCN_RADIO(radioid) (radioid == BCM2064_ID) 36 37 #define VALID_RADIO(pi, radioid) ( \ 38 (ISNPHY(pi) ? VALID_N_RADIO(radioid) : false) || \ 39 (ISLCNPHY(pi) ? VALID_LCN_RADIO(radioid) : false)) 40 41 /* basic mux operation - can be optimized on several architectures */ 42 #define MUX(pred, true, false) ((pred) ? (true) : (false)) 43 44 /* modulo inc/dec - assumes x E [0, bound - 1] */ 45 #define MODINC(x, bound) MUX((x) == (bound) - 1, 0, (x) + 1) 46 47 /* modulo inc/dec, bound = 2^k */ 48 #define MODDEC_POW2(x, bound) (((x) - 1) & ((bound) - 1)) 49 #define MODINC_POW2(x, bound) (((x) + 1) & ((bound) - 1)) 50 51 struct chan_info_basic { 52 u16 chan; 53 u16 freq; 54 }; 55 56 static const struct chan_info_basic chan_info_all[] = { 57 {1, 2412}, 58 {2, 2417}, 59 {3, 2422}, 60 {4, 2427}, 61 {5, 2432}, 62 {6, 2437}, 63 {7, 2442}, 64 {8, 2447}, 65 {9, 2452}, 66 {10, 2457}, 67 {11, 2462}, 68 {12, 2467}, 69 {13, 2472}, 70 {14, 2484}, 71 72 {34, 5170}, 73 {38, 5190}, 74 {42, 5210}, 75 {46, 5230}, 76 77 {36, 5180}, 78 {40, 5200}, 79 {44, 5220}, 80 {48, 5240}, 81 {52, 5260}, 82 {56, 5280}, 83 {60, 5300}, 84 {64, 5320}, 85 86 {100, 5500}, 87 {104, 5520}, 88 {108, 5540}, 89 {112, 5560}, 90 {116, 5580}, 91 {120, 5600}, 92 {124, 5620}, 93 {128, 5640}, 94 {132, 5660}, 95 {136, 5680}, 96 {140, 5700}, 97 98 {149, 5745}, 99 {153, 5765}, 100 {157, 5785}, 101 {161, 5805}, 102 {165, 5825}, 103 104 {184, 4920}, 105 {188, 4940}, 106 {192, 4960}, 107 {196, 4980}, 108 {200, 5000}, 109 {204, 5020}, 110 {208, 5040}, 111 {212, 5060}, 112 {216, 5080} 113 }; 114 115 static const u8 ofdm_rate_lookup[] = { 116 117 BRCM_RATE_48M, 118 BRCM_RATE_24M, 119 BRCM_RATE_12M, 120 BRCM_RATE_6M, 121 BRCM_RATE_54M, 122 BRCM_RATE_36M, 123 BRCM_RATE_18M, 124 BRCM_RATE_9M 125 }; 126 127 #define PHY_WREG_LIMIT 24 128 129 void wlc_phyreg_enter(struct brcms_phy_pub *pih) 130 { 131 struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro); 132 wlapi_bmac_ucode_wake_override_phyreg_set(pi->sh->physhim); 133 } 134 135 void wlc_phyreg_exit(struct brcms_phy_pub *pih) 136 { 137 struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro); 138 wlapi_bmac_ucode_wake_override_phyreg_clear(pi->sh->physhim); 139 } 140 141 void wlc_radioreg_enter(struct brcms_phy_pub *pih) 142 { 143 struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro); 144 wlapi_bmac_mctrl(pi->sh->physhim, MCTL_LOCK_RADIO, MCTL_LOCK_RADIO); 145 146 udelay(10); 147 } 148 149 void wlc_radioreg_exit(struct brcms_phy_pub *pih) 150 { 151 struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro); 152 153 (void)bcma_read16(pi->d11core, D11REGOFFS(phyversion)); 154 pi->phy_wreg = 0; 155 wlapi_bmac_mctrl(pi->sh->physhim, MCTL_LOCK_RADIO, 0); 156 } 157 158 u16 read_radio_reg(struct brcms_phy *pi, u16 addr) 159 { 160 u16 data; 161 162 if ((addr == RADIO_IDCODE)) 163 return 0xffff; 164 165 switch (pi->pubpi.phy_type) { 166 case PHY_TYPE_N: 167 if (!CONF_HAS(PHYTYPE, PHY_TYPE_N)) 168 break; 169 if (NREV_GE(pi->pubpi.phy_rev, 7)) 170 addr |= RADIO_2057_READ_OFF; 171 else 172 addr |= RADIO_2055_READ_OFF; 173 break; 174 175 case PHY_TYPE_LCN: 176 if (!CONF_HAS(PHYTYPE, PHY_TYPE_LCN)) 177 break; 178 addr |= RADIO_2064_READ_OFF; 179 break; 180 181 default: 182 break; 183 } 184 185 if ((D11REV_GE(pi->sh->corerev, 24)) || 186 (D11REV_IS(pi->sh->corerev, 22) 187 && (pi->pubpi.phy_type != PHY_TYPE_SSN))) { 188 bcma_wflush16(pi->d11core, D11REGOFFS(radioregaddr), addr); 189 data = bcma_read16(pi->d11core, D11REGOFFS(radioregdata)); 190 } else { 191 bcma_wflush16(pi->d11core, D11REGOFFS(phy4waddr), addr); 192 data = bcma_read16(pi->d11core, D11REGOFFS(phy4wdatalo)); 193 } 194 pi->phy_wreg = 0; 195 196 return data; 197 } 198 199 void write_radio_reg(struct brcms_phy *pi, u16 addr, u16 val) 200 { 201 if ((D11REV_GE(pi->sh->corerev, 24)) || 202 (D11REV_IS(pi->sh->corerev, 22) 203 && (pi->pubpi.phy_type != PHY_TYPE_SSN))) { 204 205 bcma_wflush16(pi->d11core, D11REGOFFS(radioregaddr), addr); 206 bcma_write16(pi->d11core, D11REGOFFS(radioregdata), val); 207 } else { 208 bcma_wflush16(pi->d11core, D11REGOFFS(phy4waddr), addr); 209 bcma_write16(pi->d11core, D11REGOFFS(phy4wdatalo), val); 210 } 211 212 if ((pi->d11core->bus->hosttype == BCMA_HOSTTYPE_PCI) && 213 (++pi->phy_wreg >= pi->phy_wreg_limit)) { 214 (void)bcma_read32(pi->d11core, D11REGOFFS(maccontrol)); 215 pi->phy_wreg = 0; 216 } 217 } 218 219 static u32 read_radio_id(struct brcms_phy *pi) 220 { 221 u32 id; 222 223 if (D11REV_GE(pi->sh->corerev, 24)) { 224 u32 b0, b1, b2; 225 226 bcma_wflush16(pi->d11core, D11REGOFFS(radioregaddr), 0); 227 b0 = (u32) bcma_read16(pi->d11core, D11REGOFFS(radioregdata)); 228 bcma_wflush16(pi->d11core, D11REGOFFS(radioregaddr), 1); 229 b1 = (u32) bcma_read16(pi->d11core, D11REGOFFS(radioregdata)); 230 bcma_wflush16(pi->d11core, D11REGOFFS(radioregaddr), 2); 231 b2 = (u32) bcma_read16(pi->d11core, D11REGOFFS(radioregdata)); 232 233 id = ((b0 & 0xf) << 28) | (((b2 << 8) | b1) << 12) | ((b0 >> 4) 234 & 0xf); 235 } else { 236 bcma_wflush16(pi->d11core, D11REGOFFS(phy4waddr), RADIO_IDCODE); 237 id = (u32) bcma_read16(pi->d11core, D11REGOFFS(phy4wdatalo)); 238 id |= (u32) bcma_read16(pi->d11core, 239 D11REGOFFS(phy4wdatahi)) << 16; 240 } 241 pi->phy_wreg = 0; 242 return id; 243 } 244 245 void and_radio_reg(struct brcms_phy *pi, u16 addr, u16 val) 246 { 247 u16 rval; 248 249 rval = read_radio_reg(pi, addr); 250 write_radio_reg(pi, addr, (rval & val)); 251 } 252 253 void or_radio_reg(struct brcms_phy *pi, u16 addr, u16 val) 254 { 255 u16 rval; 256 257 rval = read_radio_reg(pi, addr); 258 write_radio_reg(pi, addr, (rval | val)); 259 } 260 261 void xor_radio_reg(struct brcms_phy *pi, u16 addr, u16 mask) 262 { 263 u16 rval; 264 265 rval = read_radio_reg(pi, addr); 266 write_radio_reg(pi, addr, (rval ^ mask)); 267 } 268 269 void mod_radio_reg(struct brcms_phy *pi, u16 addr, u16 mask, u16 val) 270 { 271 u16 rval; 272 273 rval = read_radio_reg(pi, addr); 274 write_radio_reg(pi, addr, (rval & ~mask) | (val & mask)); 275 } 276 277 void write_phy_channel_reg(struct brcms_phy *pi, uint val) 278 { 279 bcma_write16(pi->d11core, D11REGOFFS(phychannel), val); 280 } 281 282 u16 read_phy_reg(struct brcms_phy *pi, u16 addr) 283 { 284 bcma_wflush16(pi->d11core, D11REGOFFS(phyregaddr), addr); 285 286 pi->phy_wreg = 0; 287 return bcma_read16(pi->d11core, D11REGOFFS(phyregdata)); 288 } 289 290 void write_phy_reg(struct brcms_phy *pi, u16 addr, u16 val) 291 { 292 #ifdef CONFIG_BCM47XX 293 bcma_wflush16(pi->d11core, D11REGOFFS(phyregaddr), addr); 294 bcma_write16(pi->d11core, D11REGOFFS(phyregdata), val); 295 if (addr == 0x72) 296 (void)bcma_read16(pi->d11core, D11REGOFFS(phyregdata)); 297 #else 298 bcma_write32(pi->d11core, D11REGOFFS(phyregaddr), addr | (val << 16)); 299 if ((pi->d11core->bus->hosttype == BCMA_HOSTTYPE_PCI) && 300 (++pi->phy_wreg >= pi->phy_wreg_limit)) { 301 pi->phy_wreg = 0; 302 (void)bcma_read16(pi->d11core, D11REGOFFS(phyversion)); 303 } 304 #endif 305 } 306 307 void and_phy_reg(struct brcms_phy *pi, u16 addr, u16 val) 308 { 309 bcma_wflush16(pi->d11core, D11REGOFFS(phyregaddr), addr); 310 bcma_mask16(pi->d11core, D11REGOFFS(phyregdata), val); 311 pi->phy_wreg = 0; 312 } 313 314 void or_phy_reg(struct brcms_phy *pi, u16 addr, u16 val) 315 { 316 bcma_wflush16(pi->d11core, D11REGOFFS(phyregaddr), addr); 317 bcma_set16(pi->d11core, D11REGOFFS(phyregdata), val); 318 pi->phy_wreg = 0; 319 } 320 321 void mod_phy_reg(struct brcms_phy *pi, u16 addr, u16 mask, u16 val) 322 { 323 val &= mask; 324 bcma_wflush16(pi->d11core, D11REGOFFS(phyregaddr), addr); 325 bcma_maskset16(pi->d11core, D11REGOFFS(phyregdata), ~mask, val); 326 pi->phy_wreg = 0; 327 } 328 329 static void wlc_set_phy_uninitted(struct brcms_phy *pi) 330 { 331 int i, j; 332 333 pi->initialized = false; 334 335 pi->tx_vos = 0xffff; 336 pi->nrssi_table_delta = 0x7fffffff; 337 pi->rc_cal = 0xffff; 338 pi->mintxbias = 0xffff; 339 pi->txpwridx = -1; 340 if (ISNPHY(pi)) { 341 pi->phy_spuravoid = SPURAVOID_DISABLE; 342 343 if (NREV_GE(pi->pubpi.phy_rev, 3) 344 && NREV_LT(pi->pubpi.phy_rev, 7)) 345 pi->phy_spuravoid = SPURAVOID_AUTO; 346 347 pi->nphy_papd_skip = 0; 348 pi->nphy_papd_epsilon_offset[0] = 0xf588; 349 pi->nphy_papd_epsilon_offset[1] = 0xf588; 350 pi->nphy_txpwr_idx[0] = 128; 351 pi->nphy_txpwr_idx[1] = 128; 352 pi->nphy_txpwrindex[0].index_internal = 40; 353 pi->nphy_txpwrindex[1].index_internal = 40; 354 pi->phy_pabias = 0; 355 } else { 356 pi->phy_spuravoid = SPURAVOID_AUTO; 357 } 358 pi->radiopwr = 0xffff; 359 for (i = 0; i < STATIC_NUM_RF; i++) { 360 for (j = 0; j < STATIC_NUM_BB; j++) 361 pi->stats_11b_txpower[i][j] = -1; 362 } 363 } 364 365 struct shared_phy *wlc_phy_shared_attach(struct shared_phy_params *shp) 366 { 367 struct shared_phy *sh; 368 369 sh = kzalloc(sizeof(struct shared_phy), GFP_ATOMIC); 370 if (sh == NULL) 371 return NULL; 372 373 sh->physhim = shp->physhim; 374 sh->unit = shp->unit; 375 sh->corerev = shp->corerev; 376 377 sh->vid = shp->vid; 378 sh->did = shp->did; 379 sh->chip = shp->chip; 380 sh->chiprev = shp->chiprev; 381 sh->chippkg = shp->chippkg; 382 sh->sromrev = shp->sromrev; 383 sh->boardtype = shp->boardtype; 384 sh->boardrev = shp->boardrev; 385 sh->boardflags = shp->boardflags; 386 sh->boardflags2 = shp->boardflags2; 387 388 sh->fast_timer = PHY_SW_TIMER_FAST; 389 sh->slow_timer = PHY_SW_TIMER_SLOW; 390 sh->glacial_timer = PHY_SW_TIMER_GLACIAL; 391 392 sh->rssi_mode = RSSI_ANT_MERGE_MAX; 393 394 return sh; 395 } 396 397 static void wlc_phy_timercb_phycal(struct brcms_phy *pi) 398 { 399 uint delay = 5; 400 401 if (PHY_PERICAL_MPHASE_PENDING(pi)) { 402 if (!pi->sh->up) { 403 wlc_phy_cal_perical_mphase_reset(pi); 404 return; 405 } 406 407 if (SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi)) { 408 409 delay = 1000; 410 wlc_phy_cal_perical_mphase_restart(pi); 411 } else 412 wlc_phy_cal_perical_nphy_run(pi, PHY_PERICAL_AUTO); 413 wlapi_add_timer(pi->phycal_timer, delay, 0); 414 return; 415 } 416 417 } 418 419 static u32 wlc_phy_get_radio_ver(struct brcms_phy *pi) 420 { 421 u32 ver; 422 423 ver = read_radio_id(pi); 424 425 return ver; 426 } 427 428 struct brcms_phy_pub * 429 wlc_phy_attach(struct shared_phy *sh, struct bcma_device *d11core, 430 int bandtype, struct wiphy *wiphy) 431 { 432 struct brcms_phy *pi; 433 u32 sflags = 0; 434 uint phyversion; 435 u32 idcode; 436 int i; 437 438 if (D11REV_IS(sh->corerev, 4)) 439 sflags = SISF_2G_PHY | SISF_5G_PHY; 440 else 441 sflags = bcma_aread32(d11core, BCMA_IOST); 442 443 if (bandtype == BRCM_BAND_5G) { 444 if ((sflags & (SISF_5G_PHY | SISF_DB_PHY)) == 0) 445 return NULL; 446 } 447 448 pi = sh->phy_head; 449 if ((sflags & SISF_DB_PHY) && pi) { 450 wlapi_bmac_corereset(pi->sh->physhim, pi->pubpi.coreflags); 451 pi->refcnt++; 452 return &pi->pubpi_ro; 453 } 454 455 pi = kzalloc(sizeof(struct brcms_phy), GFP_ATOMIC); 456 if (pi == NULL) 457 return NULL; 458 pi->wiphy = wiphy; 459 pi->d11core = d11core; 460 pi->sh = sh; 461 pi->phy_init_por = true; 462 pi->phy_wreg_limit = PHY_WREG_LIMIT; 463 464 pi->txpwr_percent = 100; 465 466 pi->do_initcal = true; 467 468 pi->phycal_tempdelta = 0; 469 470 if (bandtype == BRCM_BAND_2G && (sflags & SISF_2G_PHY)) 471 pi->pubpi.coreflags = SICF_GMODE; 472 473 wlapi_bmac_corereset(pi->sh->physhim, pi->pubpi.coreflags); 474 phyversion = bcma_read16(pi->d11core, D11REGOFFS(phyversion)); 475 476 pi->pubpi.phy_type = PHY_TYPE(phyversion); 477 pi->pubpi.phy_rev = phyversion & PV_PV_MASK; 478 479 if (pi->pubpi.phy_type == PHY_TYPE_LCNXN) { 480 pi->pubpi.phy_type = PHY_TYPE_N; 481 pi->pubpi.phy_rev += LCNXN_BASEREV; 482 } 483 pi->pubpi.phy_corenum = PHY_CORE_NUM_2; 484 pi->pubpi.ana_rev = (phyversion & PV_AV_MASK) >> PV_AV_SHIFT; 485 486 if (pi->pubpi.phy_type != PHY_TYPE_N && 487 pi->pubpi.phy_type != PHY_TYPE_LCN) 488 goto err; 489 490 if (bandtype == BRCM_BAND_5G) { 491 if (!ISNPHY(pi)) 492 goto err; 493 } else if (!ISNPHY(pi) && !ISLCNPHY(pi)) { 494 goto err; 495 } 496 497 wlc_phy_anacore((struct brcms_phy_pub *) pi, ON); 498 499 idcode = wlc_phy_get_radio_ver(pi); 500 pi->pubpi.radioid = 501 (idcode & IDCODE_ID_MASK) >> IDCODE_ID_SHIFT; 502 pi->pubpi.radiorev = 503 (idcode & IDCODE_REV_MASK) >> IDCODE_REV_SHIFT; 504 pi->pubpi.radiover = 505 (idcode & IDCODE_VER_MASK) >> IDCODE_VER_SHIFT; 506 if (!VALID_RADIO(pi, pi->pubpi.radioid)) 507 goto err; 508 509 wlc_phy_switch_radio((struct brcms_phy_pub *) pi, OFF); 510 511 wlc_set_phy_uninitted(pi); 512 513 pi->bw = WL_CHANSPEC_BW_20; 514 pi->radio_chanspec = (bandtype == BRCM_BAND_2G) ? 515 ch20mhz_chspec(1) : ch20mhz_chspec(36); 516 517 pi->rxiq_samps = PHY_NOISE_SAMPLE_LOG_NUM_NPHY; 518 pi->rxiq_antsel = ANT_RX_DIV_DEF; 519 520 pi->watchdog_override = true; 521 522 pi->cal_type_override = PHY_PERICAL_AUTO; 523 524 pi->nphy_saved_noisevars.bufcount = 0; 525 526 if (ISNPHY(pi)) 527 pi->min_txpower = PHY_TXPWR_MIN_NPHY; 528 else 529 pi->min_txpower = PHY_TXPWR_MIN; 530 531 pi->sh->phyrxchain = 0x3; 532 533 pi->rx2tx_biasentry = -1; 534 535 pi->phy_txcore_disable_temp = PHY_CHAIN_TX_DISABLE_TEMP; 536 pi->phy_txcore_enable_temp = 537 PHY_CHAIN_TX_DISABLE_TEMP - PHY_HYSTERESIS_DELTATEMP; 538 pi->phy_tempsense_offset = 0; 539 pi->phy_txcore_heatedup = false; 540 541 pi->nphy_lastcal_temp = -50; 542 543 pi->phynoise_polling = true; 544 if (ISNPHY(pi) || ISLCNPHY(pi)) 545 pi->phynoise_polling = false; 546 547 for (i = 0; i < TXP_NUM_RATES; i++) { 548 pi->txpwr_limit[i] = BRCMS_TXPWR_MAX; 549 pi->txpwr_env_limit[i] = BRCMS_TXPWR_MAX; 550 pi->tx_user_target[i] = BRCMS_TXPWR_MAX; 551 } 552 553 pi->radiopwr_override = RADIOPWR_OVERRIDE_DEF; 554 555 pi->user_txpwr_at_rfport = false; 556 557 if (ISNPHY(pi)) { 558 559 pi->phycal_timer = wlapi_init_timer(pi->sh->physhim, 560 wlc_phy_timercb_phycal, 561 pi, "phycal"); 562 if (!pi->phycal_timer) 563 goto err; 564 565 if (!wlc_phy_attach_nphy(pi)) 566 goto err; 567 568 } else if (ISLCNPHY(pi)) { 569 if (!wlc_phy_attach_lcnphy(pi)) 570 goto err; 571 572 } 573 574 pi->refcnt++; 575 pi->next = pi->sh->phy_head; 576 sh->phy_head = pi; 577 578 memcpy(&pi->pubpi_ro, &pi->pubpi, sizeof(struct brcms_phy_pub)); 579 580 return &pi->pubpi_ro; 581 582 err: 583 kfree(pi); 584 return NULL; 585 } 586 587 void wlc_phy_detach(struct brcms_phy_pub *pih) 588 { 589 struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro); 590 591 if (pih) { 592 if (--pi->refcnt) 593 return; 594 595 if (pi->phycal_timer) { 596 wlapi_free_timer(pi->phycal_timer); 597 pi->phycal_timer = NULL; 598 } 599 600 if (pi->sh->phy_head == pi) 601 pi->sh->phy_head = pi->next; 602 else if (pi->sh->phy_head->next == pi) 603 pi->sh->phy_head->next = NULL; 604 605 if (pi->pi_fptr.detach) 606 (pi->pi_fptr.detach)(pi); 607 608 kfree(pi); 609 } 610 } 611 612 bool 613 wlc_phy_get_phyversion(struct brcms_phy_pub *pih, u16 *phytype, u16 *phyrev, 614 u16 *radioid, u16 *radiover) 615 { 616 struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro); 617 *phytype = (u16) pi->pubpi.phy_type; 618 *phyrev = (u16) pi->pubpi.phy_rev; 619 *radioid = pi->pubpi.radioid; 620 *radiover = pi->pubpi.radiorev; 621 622 return true; 623 } 624 625 bool wlc_phy_get_encore(struct brcms_phy_pub *pih) 626 { 627 struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro); 628 return pi->pubpi.abgphy_encore; 629 } 630 631 u32 wlc_phy_get_coreflags(struct brcms_phy_pub *pih) 632 { 633 struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro); 634 return pi->pubpi.coreflags; 635 } 636 637 void wlc_phy_anacore(struct brcms_phy_pub *pih, bool on) 638 { 639 struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro); 640 641 if (ISNPHY(pi)) { 642 if (on) { 643 if (NREV_GE(pi->pubpi.phy_rev, 3)) { 644 write_phy_reg(pi, 0xa6, 0x0d); 645 write_phy_reg(pi, 0x8f, 0x0); 646 write_phy_reg(pi, 0xa7, 0x0d); 647 write_phy_reg(pi, 0xa5, 0x0); 648 } else { 649 write_phy_reg(pi, 0xa5, 0x0); 650 } 651 } else { 652 if (NREV_GE(pi->pubpi.phy_rev, 3)) { 653 write_phy_reg(pi, 0x8f, 0x07ff); 654 write_phy_reg(pi, 0xa6, 0x0fd); 655 write_phy_reg(pi, 0xa5, 0x07ff); 656 write_phy_reg(pi, 0xa7, 0x0fd); 657 } else { 658 write_phy_reg(pi, 0xa5, 0x7fff); 659 } 660 } 661 } else if (ISLCNPHY(pi)) { 662 if (on) { 663 and_phy_reg(pi, 0x43b, 664 ~((0x1 << 0) | (0x1 << 1) | (0x1 << 2))); 665 } else { 666 or_phy_reg(pi, 0x43c, 667 (0x1 << 0) | (0x1 << 1) | (0x1 << 2)); 668 or_phy_reg(pi, 0x43b, 669 (0x1 << 0) | (0x1 << 1) | (0x1 << 2)); 670 } 671 } 672 } 673 674 u32 wlc_phy_clk_bwbits(struct brcms_phy_pub *pih) 675 { 676 struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro); 677 678 u32 phy_bw_clkbits = 0; 679 680 if (pi && (ISNPHY(pi) || ISLCNPHY(pi))) { 681 switch (pi->bw) { 682 case WL_CHANSPEC_BW_10: 683 phy_bw_clkbits = SICF_BW10; 684 break; 685 case WL_CHANSPEC_BW_20: 686 phy_bw_clkbits = SICF_BW20; 687 break; 688 case WL_CHANSPEC_BW_40: 689 phy_bw_clkbits = SICF_BW40; 690 break; 691 default: 692 break; 693 } 694 } 695 696 return phy_bw_clkbits; 697 } 698 699 void wlc_phy_por_inform(struct brcms_phy_pub *ppi) 700 { 701 struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro); 702 703 pi->phy_init_por = true; 704 } 705 706 void wlc_phy_edcrs_lock(struct brcms_phy_pub *pih, bool lock) 707 { 708 struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro); 709 710 pi->edcrs_threshold_lock = lock; 711 712 write_phy_reg(pi, 0x22c, 0x46b); 713 write_phy_reg(pi, 0x22d, 0x46b); 714 write_phy_reg(pi, 0x22e, 0x3c0); 715 write_phy_reg(pi, 0x22f, 0x3c0); 716 } 717 718 void wlc_phy_initcal_enable(struct brcms_phy_pub *pih, bool initcal) 719 { 720 struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro); 721 722 pi->do_initcal = initcal; 723 } 724 725 void wlc_phy_hw_clk_state_upd(struct brcms_phy_pub *pih, bool newstate) 726 { 727 struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro); 728 729 if (!pi || !pi->sh) 730 return; 731 732 pi->sh->clk = newstate; 733 } 734 735 void wlc_phy_hw_state_upd(struct brcms_phy_pub *pih, bool newstate) 736 { 737 struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro); 738 739 if (!pi || !pi->sh) 740 return; 741 742 pi->sh->up = newstate; 743 } 744 745 void wlc_phy_init(struct brcms_phy_pub *pih, u16 chanspec) 746 { 747 u32 mc; 748 void (*phy_init)(struct brcms_phy *) = NULL; 749 struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro); 750 751 if (pi->init_in_progress) 752 return; 753 754 pi->init_in_progress = true; 755 756 pi->radio_chanspec = chanspec; 757 758 mc = bcma_read32(pi->d11core, D11REGOFFS(maccontrol)); 759 if (WARN(mc & MCTL_EN_MAC, "HW error MAC running on init")) 760 return; 761 762 if (!(pi->measure_hold & PHY_HOLD_FOR_SCAN)) 763 pi->measure_hold |= PHY_HOLD_FOR_NOT_ASSOC; 764 765 if (WARN(!(bcma_aread32(pi->d11core, BCMA_IOST) & SISF_FCLKA), 766 "HW error SISF_FCLKA\n")) 767 return; 768 769 phy_init = pi->pi_fptr.init; 770 771 if (phy_init == NULL) 772 return; 773 774 wlc_phy_anacore(pih, ON); 775 776 if (CHSPEC_BW(pi->radio_chanspec) != pi->bw) 777 wlapi_bmac_bw_set(pi->sh->physhim, 778 CHSPEC_BW(pi->radio_chanspec)); 779 780 pi->nphy_gain_boost = true; 781 782 wlc_phy_switch_radio((struct brcms_phy_pub *) pi, ON); 783 784 (*phy_init)(pi); 785 786 pi->phy_init_por = false; 787 788 if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12)) 789 wlc_phy_do_dummy_tx(pi, true, OFF); 790 791 if (!(ISNPHY(pi))) 792 wlc_phy_txpower_update_shm(pi); 793 794 wlc_phy_ant_rxdiv_set((struct brcms_phy_pub *) pi, pi->sh->rx_antdiv); 795 796 pi->init_in_progress = false; 797 } 798 799 void wlc_phy_cal_init(struct brcms_phy_pub *pih) 800 { 801 struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro); 802 void (*cal_init)(struct brcms_phy *) = NULL; 803 804 if (WARN((bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) & 805 MCTL_EN_MAC) != 0, "HW error: MAC enabled during phy cal\n")) 806 return; 807 808 if (!pi->initialized) { 809 cal_init = pi->pi_fptr.calinit; 810 if (cal_init) 811 (*cal_init)(pi); 812 813 pi->initialized = true; 814 } 815 } 816 817 int wlc_phy_down(struct brcms_phy_pub *pih) 818 { 819 struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro); 820 int callbacks = 0; 821 822 if (pi->phycal_timer 823 && !wlapi_del_timer(pi->phycal_timer)) 824 callbacks++; 825 826 pi->nphy_iqcal_chanspec_2G = 0; 827 pi->nphy_iqcal_chanspec_5G = 0; 828 829 return callbacks; 830 } 831 832 void 833 wlc_phy_table_addr(struct brcms_phy *pi, uint tbl_id, uint tbl_offset, 834 u16 tblAddr, u16 tblDataHi, u16 tblDataLo) 835 { 836 write_phy_reg(pi, tblAddr, (tbl_id << 10) | tbl_offset); 837 838 pi->tbl_data_hi = tblDataHi; 839 pi->tbl_data_lo = tblDataLo; 840 841 if (pi->sh->chip == BCMA_CHIP_ID_BCM43224 && 842 pi->sh->chiprev == 1) { 843 pi->tbl_addr = tblAddr; 844 pi->tbl_save_id = tbl_id; 845 pi->tbl_save_offset = tbl_offset; 846 } 847 } 848 849 void wlc_phy_table_data_write(struct brcms_phy *pi, uint width, u32 val) 850 { 851 if ((pi->sh->chip == BCMA_CHIP_ID_BCM43224) && 852 (pi->sh->chiprev == 1) && 853 (pi->tbl_save_id == NPHY_TBL_ID_ANTSWCTRLLUT)) { 854 read_phy_reg(pi, pi->tbl_data_lo); 855 856 write_phy_reg(pi, pi->tbl_addr, 857 (pi->tbl_save_id << 10) | pi->tbl_save_offset); 858 pi->tbl_save_offset++; 859 } 860 861 if (width == 32) { 862 write_phy_reg(pi, pi->tbl_data_hi, (u16) (val >> 16)); 863 write_phy_reg(pi, pi->tbl_data_lo, (u16) val); 864 } else { 865 write_phy_reg(pi, pi->tbl_data_lo, (u16) val); 866 } 867 } 868 869 void 870 wlc_phy_write_table(struct brcms_phy *pi, const struct phytbl_info *ptbl_info, 871 u16 tblAddr, u16 tblDataHi, u16 tblDataLo) 872 { 873 uint idx; 874 uint tbl_id = ptbl_info->tbl_id; 875 uint tbl_offset = ptbl_info->tbl_offset; 876 uint tbl_width = ptbl_info->tbl_width; 877 const u8 *ptbl_8b = (const u8 *)ptbl_info->tbl_ptr; 878 const u16 *ptbl_16b = (const u16 *)ptbl_info->tbl_ptr; 879 const u32 *ptbl_32b = (const u32 *)ptbl_info->tbl_ptr; 880 881 write_phy_reg(pi, tblAddr, (tbl_id << 10) | tbl_offset); 882 883 for (idx = 0; idx < ptbl_info->tbl_len; idx++) { 884 885 if ((pi->sh->chip == BCMA_CHIP_ID_BCM43224) && 886 (pi->sh->chiprev == 1) && 887 (tbl_id == NPHY_TBL_ID_ANTSWCTRLLUT)) { 888 read_phy_reg(pi, tblDataLo); 889 890 write_phy_reg(pi, tblAddr, 891 (tbl_id << 10) | (tbl_offset + idx)); 892 } 893 894 if (tbl_width == 32) { 895 write_phy_reg(pi, tblDataHi, 896 (u16) (ptbl_32b[idx] >> 16)); 897 write_phy_reg(pi, tblDataLo, (u16) ptbl_32b[idx]); 898 } else if (tbl_width == 16) { 899 write_phy_reg(pi, tblDataLo, ptbl_16b[idx]); 900 } else { 901 write_phy_reg(pi, tblDataLo, ptbl_8b[idx]); 902 } 903 } 904 } 905 906 void 907 wlc_phy_read_table(struct brcms_phy *pi, const struct phytbl_info *ptbl_info, 908 u16 tblAddr, u16 tblDataHi, u16 tblDataLo) 909 { 910 uint idx; 911 uint tbl_id = ptbl_info->tbl_id; 912 uint tbl_offset = ptbl_info->tbl_offset; 913 uint tbl_width = ptbl_info->tbl_width; 914 u8 *ptbl_8b = (u8 *)ptbl_info->tbl_ptr; 915 u16 *ptbl_16b = (u16 *)ptbl_info->tbl_ptr; 916 u32 *ptbl_32b = (u32 *)ptbl_info->tbl_ptr; 917 918 write_phy_reg(pi, tblAddr, (tbl_id << 10) | tbl_offset); 919 920 for (idx = 0; idx < ptbl_info->tbl_len; idx++) { 921 922 if ((pi->sh->chip == BCMA_CHIP_ID_BCM43224) && 923 (pi->sh->chiprev == 1)) { 924 (void)read_phy_reg(pi, tblDataLo); 925 926 write_phy_reg(pi, tblAddr, 927 (tbl_id << 10) | (tbl_offset + idx)); 928 } 929 930 if (tbl_width == 32) { 931 ptbl_32b[idx] = read_phy_reg(pi, tblDataLo); 932 ptbl_32b[idx] |= (read_phy_reg(pi, tblDataHi) << 16); 933 } else if (tbl_width == 16) { 934 ptbl_16b[idx] = read_phy_reg(pi, tblDataLo); 935 } else { 936 ptbl_8b[idx] = (u8) read_phy_reg(pi, tblDataLo); 937 } 938 } 939 } 940 941 uint 942 wlc_phy_init_radio_regs_allbands(struct brcms_phy *pi, 943 struct radio_20xx_regs *radioregs) 944 { 945 uint i = 0; 946 947 do { 948 if (radioregs[i].do_init) 949 write_radio_reg(pi, radioregs[i].address, 950 (u16) radioregs[i].init); 951 952 i++; 953 } while (radioregs[i].address != 0xffff); 954 955 return i; 956 } 957 958 uint 959 wlc_phy_init_radio_regs(struct brcms_phy *pi, 960 const struct radio_regs *radioregs, 961 u16 core_offset) 962 { 963 uint i = 0; 964 uint count = 0; 965 966 do { 967 if (CHSPEC_IS5G(pi->radio_chanspec)) { 968 if (radioregs[i].do_init_a) { 969 write_radio_reg(pi, 970 radioregs[i]. 971 address | core_offset, 972 (u16) radioregs[i].init_a); 973 if (ISNPHY(pi) && (++count % 4 == 0)) 974 BRCMS_PHY_WAR_PR51571(pi); 975 } 976 } else { 977 if (radioregs[i].do_init_g) { 978 write_radio_reg(pi, 979 radioregs[i]. 980 address | core_offset, 981 (u16) radioregs[i].init_g); 982 if (ISNPHY(pi) && (++count % 4 == 0)) 983 BRCMS_PHY_WAR_PR51571(pi); 984 } 985 } 986 987 i++; 988 } while (radioregs[i].address != 0xffff); 989 990 return i; 991 } 992 993 void wlc_phy_do_dummy_tx(struct brcms_phy *pi, bool ofdm, bool pa_on) 994 { 995 #define DUMMY_PKT_LEN 20 996 struct bcma_device *core = pi->d11core; 997 int i, count; 998 u8 ofdmpkt[DUMMY_PKT_LEN] = { 999 0xcc, 0x01, 0x02, 0x00, 0x00, 0x00, 0xd4, 0x00, 0x00, 0x00, 1000 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00 1001 }; 1002 u8 cckpkt[DUMMY_PKT_LEN] = { 1003 0x6e, 0x84, 0x0b, 0x00, 0x00, 0x00, 0xd4, 0x00, 0x00, 0x00, 1004 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00 1005 }; 1006 u32 *dummypkt; 1007 1008 dummypkt = (u32 *) (ofdm ? ofdmpkt : cckpkt); 1009 wlapi_bmac_write_template_ram(pi->sh->physhim, 0, DUMMY_PKT_LEN, 1010 dummypkt); 1011 1012 bcma_write16(core, D11REGOFFS(xmtsel), 0); 1013 1014 if (D11REV_GE(pi->sh->corerev, 11)) 1015 bcma_write16(core, D11REGOFFS(wepctl), 0x100); 1016 else 1017 bcma_write16(core, D11REGOFFS(wepctl), 0); 1018 1019 bcma_write16(core, D11REGOFFS(txe_phyctl), 1020 (ofdm ? 1 : 0) | PHY_TXC_ANT_0); 1021 if (ISNPHY(pi) || ISLCNPHY(pi)) 1022 bcma_write16(core, D11REGOFFS(txe_phyctl1), 0x1A02); 1023 1024 bcma_write16(core, D11REGOFFS(txe_wm_0), 0); 1025 bcma_write16(core, D11REGOFFS(txe_wm_1), 0); 1026 1027 bcma_write16(core, D11REGOFFS(xmttplatetxptr), 0); 1028 bcma_write16(core, D11REGOFFS(xmttxcnt), DUMMY_PKT_LEN); 1029 1030 bcma_write16(core, D11REGOFFS(xmtsel), 1031 ((8 << 8) | (1 << 5) | (1 << 2) | 2)); 1032 1033 bcma_write16(core, D11REGOFFS(txe_ctl), 0); 1034 1035 if (!pa_on) { 1036 if (ISNPHY(pi)) 1037 wlc_phy_pa_override_nphy(pi, OFF); 1038 } 1039 1040 if (ISNPHY(pi) || ISLCNPHY(pi)) 1041 bcma_write16(core, D11REGOFFS(txe_aux), 0xD0); 1042 else 1043 bcma_write16(core, D11REGOFFS(txe_aux), ((1 << 5) | (1 << 4))); 1044 1045 (void)bcma_read16(core, D11REGOFFS(txe_aux)); 1046 1047 i = 0; 1048 count = ofdm ? 30 : 250; 1049 while ((i++ < count) 1050 && (bcma_read16(core, D11REGOFFS(txe_status)) & (1 << 7))) 1051 udelay(10); 1052 1053 i = 0; 1054 1055 while ((i++ < 10) && 1056 ((bcma_read16(core, D11REGOFFS(txe_status)) & (1 << 10)) == 0)) 1057 udelay(10); 1058 1059 i = 0; 1060 1061 while ((i++ < 10) && 1062 ((bcma_read16(core, D11REGOFFS(ifsstat)) & (1 << 8)))) 1063 udelay(10); 1064 1065 if (!pa_on) { 1066 if (ISNPHY(pi)) 1067 wlc_phy_pa_override_nphy(pi, ON); 1068 } 1069 } 1070 1071 void wlc_phy_hold_upd(struct brcms_phy_pub *pih, u32 id, bool set) 1072 { 1073 struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro); 1074 1075 if (set) 1076 mboolset(pi->measure_hold, id); 1077 else 1078 mboolclr(pi->measure_hold, id); 1079 1080 return; 1081 } 1082 1083 void wlc_phy_mute_upd(struct brcms_phy_pub *pih, bool mute, u32 flags) 1084 { 1085 struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro); 1086 1087 if (mute) 1088 mboolset(pi->measure_hold, PHY_HOLD_FOR_MUTE); 1089 else 1090 mboolclr(pi->measure_hold, PHY_HOLD_FOR_MUTE); 1091 1092 if (!mute && (flags & PHY_MUTE_FOR_PREISM)) 1093 pi->nphy_perical_last = pi->sh->now - pi->sh->glacial_timer; 1094 return; 1095 } 1096 1097 void wlc_phy_clear_tssi(struct brcms_phy_pub *pih) 1098 { 1099 struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro); 1100 1101 if (ISNPHY(pi)) { 1102 return; 1103 } else { 1104 wlapi_bmac_write_shm(pi->sh->physhim, M_B_TSSI_0, NULL_TSSI_W); 1105 wlapi_bmac_write_shm(pi->sh->physhim, M_B_TSSI_1, NULL_TSSI_W); 1106 wlapi_bmac_write_shm(pi->sh->physhim, M_G_TSSI_0, NULL_TSSI_W); 1107 wlapi_bmac_write_shm(pi->sh->physhim, M_G_TSSI_1, NULL_TSSI_W); 1108 } 1109 } 1110 1111 static bool wlc_phy_cal_txpower_recalc_sw(struct brcms_phy *pi) 1112 { 1113 return false; 1114 } 1115 1116 void wlc_phy_switch_radio(struct brcms_phy_pub *pih, bool on) 1117 { 1118 struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro); 1119 (void)bcma_read32(pi->d11core, D11REGOFFS(maccontrol)); 1120 1121 if (ISNPHY(pi)) { 1122 wlc_phy_switch_radio_nphy(pi, on); 1123 } else if (ISLCNPHY(pi)) { 1124 if (on) { 1125 and_phy_reg(pi, 0x44c, 1126 ~((0x1 << 8) | 1127 (0x1 << 9) | 1128 (0x1 << 10) | (0x1 << 11) | (0x1 << 12))); 1129 and_phy_reg(pi, 0x4b0, ~((0x1 << 3) | (0x1 << 11))); 1130 and_phy_reg(pi, 0x4f9, ~(0x1 << 3)); 1131 } else { 1132 and_phy_reg(pi, 0x44d, 1133 ~((0x1 << 10) | 1134 (0x1 << 11) | 1135 (0x1 << 12) | (0x1 << 13) | (0x1 << 14))); 1136 or_phy_reg(pi, 0x44c, 1137 (0x1 << 8) | 1138 (0x1 << 9) | 1139 (0x1 << 10) | (0x1 << 11) | (0x1 << 12)); 1140 1141 and_phy_reg(pi, 0x4b7, ~((0x7f << 8))); 1142 and_phy_reg(pi, 0x4b1, ~((0x1 << 13))); 1143 or_phy_reg(pi, 0x4b0, (0x1 << 3) | (0x1 << 11)); 1144 and_phy_reg(pi, 0x4fa, ~((0x1 << 3))); 1145 or_phy_reg(pi, 0x4f9, (0x1 << 3)); 1146 } 1147 } 1148 } 1149 1150 u16 wlc_phy_bw_state_get(struct brcms_phy_pub *ppi) 1151 { 1152 struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro); 1153 1154 return pi->bw; 1155 } 1156 1157 void wlc_phy_bw_state_set(struct brcms_phy_pub *ppi, u16 bw) 1158 { 1159 struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro); 1160 1161 pi->bw = bw; 1162 } 1163 1164 void wlc_phy_chanspec_radio_set(struct brcms_phy_pub *ppi, u16 newch) 1165 { 1166 struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro); 1167 pi->radio_chanspec = newch; 1168 1169 } 1170 1171 u16 wlc_phy_chanspec_get(struct brcms_phy_pub *ppi) 1172 { 1173 struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro); 1174 1175 return pi->radio_chanspec; 1176 } 1177 1178 void wlc_phy_chanspec_set(struct brcms_phy_pub *ppi, u16 chanspec) 1179 { 1180 struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro); 1181 u16 m_cur_channel; 1182 void (*chanspec_set)(struct brcms_phy *, u16) = NULL; 1183 m_cur_channel = CHSPEC_CHANNEL(chanspec); 1184 if (CHSPEC_IS5G(chanspec)) 1185 m_cur_channel |= D11_CURCHANNEL_5G; 1186 if (CHSPEC_IS40(chanspec)) 1187 m_cur_channel |= D11_CURCHANNEL_40; 1188 wlapi_bmac_write_shm(pi->sh->physhim, M_CURCHANNEL, m_cur_channel); 1189 1190 chanspec_set = pi->pi_fptr.chanset; 1191 if (chanspec_set) 1192 (*chanspec_set)(pi, chanspec); 1193 1194 } 1195 1196 int wlc_phy_chanspec_freq2bandrange_lpssn(uint freq) 1197 { 1198 int range = -1; 1199 1200 if (freq < 2500) 1201 range = WL_CHAN_FREQ_RANGE_2G; 1202 else if (freq <= 5320) 1203 range = WL_CHAN_FREQ_RANGE_5GL; 1204 else if (freq <= 5700) 1205 range = WL_CHAN_FREQ_RANGE_5GM; 1206 else 1207 range = WL_CHAN_FREQ_RANGE_5GH; 1208 1209 return range; 1210 } 1211 1212 int wlc_phy_chanspec_bandrange_get(struct brcms_phy *pi, u16 chanspec) 1213 { 1214 int range = -1; 1215 uint channel = CHSPEC_CHANNEL(chanspec); 1216 uint freq = wlc_phy_channel2freq(channel); 1217 1218 if (ISNPHY(pi)) 1219 range = wlc_phy_get_chan_freq_range_nphy(pi, channel); 1220 else if (ISLCNPHY(pi)) 1221 range = wlc_phy_chanspec_freq2bandrange_lpssn(freq); 1222 1223 return range; 1224 } 1225 1226 void wlc_phy_chanspec_ch14_widefilter_set(struct brcms_phy_pub *ppi, 1227 bool wide_filter) 1228 { 1229 struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro); 1230 1231 pi->channel_14_wide_filter = wide_filter; 1232 1233 } 1234 1235 int wlc_phy_channel2freq(uint channel) 1236 { 1237 uint i; 1238 1239 for (i = 0; i < ARRAY_SIZE(chan_info_all); i++) 1240 if (chan_info_all[i].chan == channel) 1241 return chan_info_all[i].freq; 1242 return 0; 1243 } 1244 1245 void 1246 wlc_phy_chanspec_band_validch(struct brcms_phy_pub *ppi, uint band, 1247 struct brcms_chanvec *channels) 1248 { 1249 struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro); 1250 uint i; 1251 uint channel; 1252 1253 memset(channels, 0, sizeof(struct brcms_chanvec)); 1254 1255 for (i = 0; i < ARRAY_SIZE(chan_info_all); i++) { 1256 channel = chan_info_all[i].chan; 1257 1258 if ((pi->a_band_high_disable) && (channel >= FIRST_REF5_CHANNUM) 1259 && (channel <= LAST_REF5_CHANNUM)) 1260 continue; 1261 1262 if ((band == BRCM_BAND_2G && channel <= CH_MAX_2G_CHANNEL) || 1263 (band == BRCM_BAND_5G && channel > CH_MAX_2G_CHANNEL)) 1264 setbit(channels->vec, channel); 1265 } 1266 } 1267 1268 u16 wlc_phy_chanspec_band_firstch(struct brcms_phy_pub *ppi, uint band) 1269 { 1270 struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro); 1271 uint i; 1272 uint channel; 1273 u16 chspec; 1274 1275 for (i = 0; i < ARRAY_SIZE(chan_info_all); i++) { 1276 channel = chan_info_all[i].chan; 1277 1278 if (ISNPHY(pi) && pi->bw == WL_CHANSPEC_BW_40) { 1279 uint j; 1280 1281 for (j = 0; j < ARRAY_SIZE(chan_info_all); j++) { 1282 if (chan_info_all[j].chan == 1283 channel + CH_10MHZ_APART) 1284 break; 1285 } 1286 1287 if (j == ARRAY_SIZE(chan_info_all)) 1288 continue; 1289 1290 channel = upper_20_sb(channel); 1291 chspec = channel | WL_CHANSPEC_BW_40 | 1292 WL_CHANSPEC_CTL_SB_LOWER; 1293 if (band == BRCM_BAND_2G) 1294 chspec |= WL_CHANSPEC_BAND_2G; 1295 else 1296 chspec |= WL_CHANSPEC_BAND_5G; 1297 } else 1298 chspec = ch20mhz_chspec(channel); 1299 1300 if ((pi->a_band_high_disable) && (channel >= FIRST_REF5_CHANNUM) 1301 && (channel <= LAST_REF5_CHANNUM)) 1302 continue; 1303 1304 if ((band == BRCM_BAND_2G && channel <= CH_MAX_2G_CHANNEL) || 1305 (band == BRCM_BAND_5G && channel > CH_MAX_2G_CHANNEL)) 1306 return chspec; 1307 } 1308 1309 return (u16) INVCHANSPEC; 1310 } 1311 1312 int wlc_phy_txpower_get(struct brcms_phy_pub *ppi, uint *qdbm, bool *override) 1313 { 1314 struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro); 1315 1316 *qdbm = pi->tx_user_target[0]; 1317 if (override != NULL) 1318 *override = pi->txpwroverride; 1319 return 0; 1320 } 1321 1322 void wlc_phy_txpower_target_set(struct brcms_phy_pub *ppi, 1323 struct txpwr_limits *txpwr) 1324 { 1325 bool mac_enabled = false; 1326 struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro); 1327 1328 memcpy(&pi->tx_user_target[TXP_FIRST_CCK], 1329 &txpwr->cck[0], BRCMS_NUM_RATES_CCK); 1330 1331 memcpy(&pi->tx_user_target[TXP_FIRST_OFDM], 1332 &txpwr->ofdm[0], BRCMS_NUM_RATES_OFDM); 1333 memcpy(&pi->tx_user_target[TXP_FIRST_OFDM_20_CDD], 1334 &txpwr->ofdm_cdd[0], BRCMS_NUM_RATES_OFDM); 1335 1336 memcpy(&pi->tx_user_target[TXP_FIRST_OFDM_40_SISO], 1337 &txpwr->ofdm_40_siso[0], BRCMS_NUM_RATES_OFDM); 1338 memcpy(&pi->tx_user_target[TXP_FIRST_OFDM_40_CDD], 1339 &txpwr->ofdm_40_cdd[0], BRCMS_NUM_RATES_OFDM); 1340 1341 memcpy(&pi->tx_user_target[TXP_FIRST_MCS_20_SISO], 1342 &txpwr->mcs_20_siso[0], BRCMS_NUM_RATES_MCS_1_STREAM); 1343 memcpy(&pi->tx_user_target[TXP_FIRST_MCS_20_CDD], 1344 &txpwr->mcs_20_cdd[0], BRCMS_NUM_RATES_MCS_1_STREAM); 1345 memcpy(&pi->tx_user_target[TXP_FIRST_MCS_20_STBC], 1346 &txpwr->mcs_20_stbc[0], BRCMS_NUM_RATES_MCS_1_STREAM); 1347 memcpy(&pi->tx_user_target[TXP_FIRST_MCS_20_SDM], 1348 &txpwr->mcs_20_mimo[0], BRCMS_NUM_RATES_MCS_2_STREAM); 1349 1350 memcpy(&pi->tx_user_target[TXP_FIRST_MCS_40_SISO], 1351 &txpwr->mcs_40_siso[0], BRCMS_NUM_RATES_MCS_1_STREAM); 1352 memcpy(&pi->tx_user_target[TXP_FIRST_MCS_40_CDD], 1353 &txpwr->mcs_40_cdd[0], BRCMS_NUM_RATES_MCS_1_STREAM); 1354 memcpy(&pi->tx_user_target[TXP_FIRST_MCS_40_STBC], 1355 &txpwr->mcs_40_stbc[0], BRCMS_NUM_RATES_MCS_1_STREAM); 1356 memcpy(&pi->tx_user_target[TXP_FIRST_MCS_40_SDM], 1357 &txpwr->mcs_40_mimo[0], BRCMS_NUM_RATES_MCS_2_STREAM); 1358 1359 if (bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) & MCTL_EN_MAC) 1360 mac_enabled = true; 1361 1362 if (mac_enabled) 1363 wlapi_suspend_mac_and_wait(pi->sh->physhim); 1364 1365 wlc_phy_txpower_recalc_target(pi); 1366 wlc_phy_cal_txpower_recalc_sw(pi); 1367 1368 if (mac_enabled) 1369 wlapi_enable_mac(pi->sh->physhim); 1370 } 1371 1372 int wlc_phy_txpower_set(struct brcms_phy_pub *ppi, uint qdbm, bool override) 1373 { 1374 struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro); 1375 int i; 1376 1377 if (qdbm > 127) 1378 return -EINVAL; 1379 1380 for (i = 0; i < TXP_NUM_RATES; i++) 1381 pi->tx_user_target[i] = (u8) qdbm; 1382 1383 pi->txpwroverride = false; 1384 1385 if (pi->sh->up) { 1386 if (!SCAN_INPROG_PHY(pi)) { 1387 bool suspend; 1388 1389 suspend = (0 == (bcma_read32(pi->d11core, 1390 D11REGOFFS(maccontrol)) & 1391 MCTL_EN_MAC)); 1392 1393 if (!suspend) 1394 wlapi_suspend_mac_and_wait(pi->sh->physhim); 1395 1396 wlc_phy_txpower_recalc_target(pi); 1397 wlc_phy_cal_txpower_recalc_sw(pi); 1398 1399 if (!suspend) 1400 wlapi_enable_mac(pi->sh->physhim); 1401 } 1402 } 1403 return 0; 1404 } 1405 1406 void 1407 wlc_phy_txpower_sromlimit(struct brcms_phy_pub *ppi, uint channel, u8 *min_pwr, 1408 u8 *max_pwr, int txp_rate_idx) 1409 { 1410 struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro); 1411 uint i; 1412 1413 *min_pwr = pi->min_txpower * BRCMS_TXPWR_DB_FACTOR; 1414 1415 if (ISNPHY(pi)) { 1416 if (txp_rate_idx < 0) 1417 txp_rate_idx = TXP_FIRST_CCK; 1418 wlc_phy_txpower_sromlimit_get_nphy(pi, channel, max_pwr, 1419 (u8) txp_rate_idx); 1420 1421 } else if ((channel <= CH_MAX_2G_CHANNEL)) { 1422 if (txp_rate_idx < 0) 1423 txp_rate_idx = TXP_FIRST_CCK; 1424 *max_pwr = pi->tx_srom_max_rate_2g[txp_rate_idx]; 1425 } else { 1426 1427 *max_pwr = BRCMS_TXPWR_MAX; 1428 1429 if (txp_rate_idx < 0) 1430 txp_rate_idx = TXP_FIRST_OFDM; 1431 1432 for (i = 0; i < ARRAY_SIZE(chan_info_all); i++) { 1433 if (channel == chan_info_all[i].chan) 1434 break; 1435 } 1436 1437 if (pi->hwtxpwr) { 1438 *max_pwr = pi->hwtxpwr[i]; 1439 } else { 1440 1441 if ((i >= FIRST_MID_5G_CHAN) && (i <= LAST_MID_5G_CHAN)) 1442 *max_pwr = 1443 pi->tx_srom_max_rate_5g_mid[txp_rate_idx]; 1444 if ((i >= FIRST_HIGH_5G_CHAN) 1445 && (i <= LAST_HIGH_5G_CHAN)) 1446 *max_pwr = 1447 pi->tx_srom_max_rate_5g_hi[txp_rate_idx]; 1448 if ((i >= FIRST_LOW_5G_CHAN) && (i <= LAST_LOW_5G_CHAN)) 1449 *max_pwr = 1450 pi->tx_srom_max_rate_5g_low[txp_rate_idx]; 1451 } 1452 } 1453 } 1454 1455 void 1456 wlc_phy_txpower_sromlimit_max_get(struct brcms_phy_pub *ppi, uint chan, 1457 u8 *max_txpwr, u8 *min_txpwr) 1458 { 1459 struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro); 1460 u8 tx_pwr_max = 0; 1461 u8 tx_pwr_min = 255; 1462 u8 max_num_rate; 1463 u8 maxtxpwr, mintxpwr, rate, pactrl; 1464 1465 pactrl = 0; 1466 1467 max_num_rate = ISNPHY(pi) ? TXP_NUM_RATES : 1468 ISLCNPHY(pi) ? (TXP_LAST_SISO_MCS_20 + 1469 1) : (TXP_LAST_OFDM + 1); 1470 1471 for (rate = 0; rate < max_num_rate; rate++) { 1472 1473 wlc_phy_txpower_sromlimit(ppi, chan, &mintxpwr, &maxtxpwr, 1474 rate); 1475 1476 maxtxpwr = (maxtxpwr > pactrl) ? (maxtxpwr - pactrl) : 0; 1477 1478 maxtxpwr = (maxtxpwr > 6) ? (maxtxpwr - 6) : 0; 1479 1480 tx_pwr_max = max(tx_pwr_max, maxtxpwr); 1481 tx_pwr_min = min(tx_pwr_min, maxtxpwr); 1482 } 1483 *max_txpwr = tx_pwr_max; 1484 *min_txpwr = tx_pwr_min; 1485 } 1486 1487 void 1488 wlc_phy_txpower_boardlimit_band(struct brcms_phy_pub *ppi, uint bandunit, 1489 s32 *max_pwr, s32 *min_pwr, u32 *step_pwr) 1490 { 1491 return; 1492 } 1493 1494 u8 wlc_phy_txpower_get_target_min(struct brcms_phy_pub *ppi) 1495 { 1496 struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro); 1497 1498 return pi->tx_power_min; 1499 } 1500 1501 u8 wlc_phy_txpower_get_target_max(struct brcms_phy_pub *ppi) 1502 { 1503 struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro); 1504 1505 return pi->tx_power_max; 1506 } 1507 1508 static s8 wlc_phy_env_measure_vbat(struct brcms_phy *pi) 1509 { 1510 if (ISLCNPHY(pi)) 1511 return wlc_lcnphy_vbatsense(pi, 0); 1512 else 1513 return 0; 1514 } 1515 1516 static s8 wlc_phy_env_measure_temperature(struct brcms_phy *pi) 1517 { 1518 if (ISLCNPHY(pi)) 1519 return wlc_lcnphy_tempsense_degree(pi, 0); 1520 else 1521 return 0; 1522 } 1523 1524 static void wlc_phy_upd_env_txpwr_rate_limits(struct brcms_phy *pi, u32 band) 1525 { 1526 u8 i; 1527 s8 temp, vbat; 1528 1529 for (i = 0; i < TXP_NUM_RATES; i++) 1530 pi->txpwr_env_limit[i] = BRCMS_TXPWR_MAX; 1531 1532 vbat = wlc_phy_env_measure_vbat(pi); 1533 temp = wlc_phy_env_measure_temperature(pi); 1534 1535 } 1536 1537 static s8 1538 wlc_user_txpwr_antport_to_rfport(struct brcms_phy *pi, uint chan, u32 band, 1539 u8 rate) 1540 { 1541 return 0; 1542 } 1543 1544 void wlc_phy_txpower_recalc_target(struct brcms_phy *pi) 1545 { 1546 u8 maxtxpwr, mintxpwr, rate, pactrl; 1547 uint target_chan; 1548 u8 tx_pwr_target[TXP_NUM_RATES]; 1549 u8 tx_pwr_max = 0; 1550 u8 tx_pwr_min = 255; 1551 u8 tx_pwr_max_rate_ind = 0; 1552 u8 max_num_rate; 1553 u8 start_rate = 0; 1554 u16 chspec; 1555 u32 band = CHSPEC2BAND(pi->radio_chanspec); 1556 void (*txpwr_recalc_fn)(struct brcms_phy *) = NULL; 1557 1558 chspec = pi->radio_chanspec; 1559 if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_NONE) 1560 target_chan = CHSPEC_CHANNEL(chspec); 1561 else if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_UPPER) 1562 target_chan = upper_20_sb(CHSPEC_CHANNEL(chspec)); 1563 else 1564 target_chan = lower_20_sb(CHSPEC_CHANNEL(chspec)); 1565 1566 pactrl = 0; 1567 if (ISLCNPHY(pi)) { 1568 u32 offset_mcs, i; 1569 1570 if (CHSPEC_IS40(pi->radio_chanspec)) { 1571 offset_mcs = pi->mcs40_po; 1572 for (i = TXP_FIRST_SISO_MCS_20; 1573 i <= TXP_LAST_SISO_MCS_20; i++) { 1574 pi->tx_srom_max_rate_2g[i - 8] = 1575 pi->tx_srom_max_2g - 1576 ((offset_mcs & 0xf) * 2); 1577 offset_mcs >>= 4; 1578 } 1579 } else { 1580 offset_mcs = pi->mcs20_po; 1581 for (i = TXP_FIRST_SISO_MCS_20; 1582 i <= TXP_LAST_SISO_MCS_20; i++) { 1583 pi->tx_srom_max_rate_2g[i - 8] = 1584 pi->tx_srom_max_2g - 1585 ((offset_mcs & 0xf) * 2); 1586 offset_mcs >>= 4; 1587 } 1588 } 1589 } 1590 1591 max_num_rate = ((ISNPHY(pi)) ? (TXP_NUM_RATES) : 1592 ((ISLCNPHY(pi)) ? 1593 (TXP_LAST_SISO_MCS_20 + 1) : (TXP_LAST_OFDM + 1))); 1594 1595 wlc_phy_upd_env_txpwr_rate_limits(pi, band); 1596 1597 for (rate = start_rate; rate < max_num_rate; rate++) { 1598 1599 tx_pwr_target[rate] = pi->tx_user_target[rate]; 1600 1601 if (pi->user_txpwr_at_rfport) 1602 tx_pwr_target[rate] += 1603 wlc_user_txpwr_antport_to_rfport(pi, 1604 target_chan, 1605 band, 1606 rate); 1607 1608 wlc_phy_txpower_sromlimit((struct brcms_phy_pub *) pi, 1609 target_chan, 1610 &mintxpwr, &maxtxpwr, rate); 1611 1612 maxtxpwr = min(maxtxpwr, pi->txpwr_limit[rate]); 1613 1614 maxtxpwr = (maxtxpwr > pactrl) ? (maxtxpwr - pactrl) : 0; 1615 1616 maxtxpwr = (maxtxpwr > 6) ? (maxtxpwr - 6) : 0; 1617 1618 maxtxpwr = min(maxtxpwr, tx_pwr_target[rate]); 1619 1620 if (pi->txpwr_percent <= 100) 1621 maxtxpwr = (maxtxpwr * pi->txpwr_percent) / 100; 1622 1623 tx_pwr_target[rate] = max(maxtxpwr, mintxpwr); 1624 1625 tx_pwr_target[rate] = 1626 min(tx_pwr_target[rate], pi->txpwr_env_limit[rate]); 1627 1628 if (tx_pwr_target[rate] > tx_pwr_max) 1629 tx_pwr_max_rate_ind = rate; 1630 1631 tx_pwr_max = max(tx_pwr_max, tx_pwr_target[rate]); 1632 tx_pwr_min = min(tx_pwr_min, tx_pwr_target[rate]); 1633 } 1634 1635 memset(pi->tx_power_offset, 0, sizeof(pi->tx_power_offset)); 1636 pi->tx_power_max = tx_pwr_max; 1637 pi->tx_power_min = tx_pwr_min; 1638 pi->tx_power_max_rate_ind = tx_pwr_max_rate_ind; 1639 for (rate = 0; rate < max_num_rate; rate++) { 1640 1641 pi->tx_power_target[rate] = tx_pwr_target[rate]; 1642 1643 if (!pi->hwpwrctrl || ISNPHY(pi)) 1644 pi->tx_power_offset[rate] = 1645 pi->tx_power_max - pi->tx_power_target[rate]; 1646 else 1647 pi->tx_power_offset[rate] = 1648 pi->tx_power_target[rate] - pi->tx_power_min; 1649 } 1650 1651 txpwr_recalc_fn = pi->pi_fptr.txpwrrecalc; 1652 if (txpwr_recalc_fn) 1653 (*txpwr_recalc_fn)(pi); 1654 } 1655 1656 static void 1657 wlc_phy_txpower_reg_limit_calc(struct brcms_phy *pi, struct txpwr_limits *txpwr, 1658 u16 chanspec) 1659 { 1660 u8 tmp_txpwr_limit[2 * BRCMS_NUM_RATES_OFDM]; 1661 u8 *txpwr_ptr1 = NULL, *txpwr_ptr2 = NULL; 1662 int rate_start_index = 0, rate1, rate2, k; 1663 1664 for (rate1 = WL_TX_POWER_CCK_FIRST, rate2 = 0; 1665 rate2 < WL_TX_POWER_CCK_NUM; rate1++, rate2++) 1666 pi->txpwr_limit[rate1] = txpwr->cck[rate2]; 1667 1668 for (rate1 = WL_TX_POWER_OFDM_FIRST, rate2 = 0; 1669 rate2 < WL_TX_POWER_OFDM_NUM; rate1++, rate2++) 1670 pi->txpwr_limit[rate1] = txpwr->ofdm[rate2]; 1671 1672 if (ISNPHY(pi)) { 1673 1674 for (k = 0; k < 4; k++) { 1675 switch (k) { 1676 case 0: 1677 1678 txpwr_ptr1 = txpwr->mcs_20_siso; 1679 txpwr_ptr2 = txpwr->ofdm; 1680 rate_start_index = WL_TX_POWER_OFDM_FIRST; 1681 break; 1682 case 1: 1683 1684 txpwr_ptr1 = txpwr->mcs_20_cdd; 1685 txpwr_ptr2 = txpwr->ofdm_cdd; 1686 rate_start_index = WL_TX_POWER_OFDM20_CDD_FIRST; 1687 break; 1688 case 2: 1689 1690 txpwr_ptr1 = txpwr->mcs_40_siso; 1691 txpwr_ptr2 = txpwr->ofdm_40_siso; 1692 rate_start_index = 1693 WL_TX_POWER_OFDM40_SISO_FIRST; 1694 break; 1695 case 3: 1696 1697 txpwr_ptr1 = txpwr->mcs_40_cdd; 1698 txpwr_ptr2 = txpwr->ofdm_40_cdd; 1699 rate_start_index = WL_TX_POWER_OFDM40_CDD_FIRST; 1700 break; 1701 } 1702 1703 for (rate2 = 0; rate2 < BRCMS_NUM_RATES_OFDM; 1704 rate2++) { 1705 tmp_txpwr_limit[rate2] = 0; 1706 tmp_txpwr_limit[BRCMS_NUM_RATES_OFDM + rate2] = 1707 txpwr_ptr1[rate2]; 1708 } 1709 wlc_phy_mcs_to_ofdm_powers_nphy( 1710 tmp_txpwr_limit, 0, 1711 BRCMS_NUM_RATES_OFDM - 1712 1, BRCMS_NUM_RATES_OFDM); 1713 for (rate1 = rate_start_index, rate2 = 0; 1714 rate2 < BRCMS_NUM_RATES_OFDM; rate1++, rate2++) 1715 pi->txpwr_limit[rate1] = 1716 min(txpwr_ptr2[rate2], 1717 tmp_txpwr_limit[rate2]); 1718 } 1719 1720 for (k = 0; k < 4; k++) { 1721 switch (k) { 1722 case 0: 1723 1724 txpwr_ptr1 = txpwr->ofdm; 1725 txpwr_ptr2 = txpwr->mcs_20_siso; 1726 rate_start_index = WL_TX_POWER_MCS20_SISO_FIRST; 1727 break; 1728 case 1: 1729 1730 txpwr_ptr1 = txpwr->ofdm_cdd; 1731 txpwr_ptr2 = txpwr->mcs_20_cdd; 1732 rate_start_index = WL_TX_POWER_MCS20_CDD_FIRST; 1733 break; 1734 case 2: 1735 1736 txpwr_ptr1 = txpwr->ofdm_40_siso; 1737 txpwr_ptr2 = txpwr->mcs_40_siso; 1738 rate_start_index = WL_TX_POWER_MCS40_SISO_FIRST; 1739 break; 1740 case 3: 1741 1742 txpwr_ptr1 = txpwr->ofdm_40_cdd; 1743 txpwr_ptr2 = txpwr->mcs_40_cdd; 1744 rate_start_index = WL_TX_POWER_MCS40_CDD_FIRST; 1745 break; 1746 } 1747 for (rate2 = 0; rate2 < BRCMS_NUM_RATES_OFDM; 1748 rate2++) { 1749 tmp_txpwr_limit[rate2] = 0; 1750 tmp_txpwr_limit[BRCMS_NUM_RATES_OFDM + rate2] = 1751 txpwr_ptr1[rate2]; 1752 } 1753 wlc_phy_ofdm_to_mcs_powers_nphy( 1754 tmp_txpwr_limit, 0, 1755 BRCMS_NUM_RATES_OFDM - 1756 1, BRCMS_NUM_RATES_OFDM); 1757 for (rate1 = rate_start_index, rate2 = 0; 1758 rate2 < BRCMS_NUM_RATES_MCS_1_STREAM; 1759 rate1++, rate2++) 1760 pi->txpwr_limit[rate1] = 1761 min(txpwr_ptr2[rate2], 1762 tmp_txpwr_limit[rate2]); 1763 } 1764 1765 for (k = 0; k < 2; k++) { 1766 switch (k) { 1767 case 0: 1768 1769 rate_start_index = WL_TX_POWER_MCS20_STBC_FIRST; 1770 txpwr_ptr1 = txpwr->mcs_20_stbc; 1771 break; 1772 case 1: 1773 1774 rate_start_index = WL_TX_POWER_MCS40_STBC_FIRST; 1775 txpwr_ptr1 = txpwr->mcs_40_stbc; 1776 break; 1777 } 1778 for (rate1 = rate_start_index, rate2 = 0; 1779 rate2 < BRCMS_NUM_RATES_MCS_1_STREAM; 1780 rate1++, rate2++) 1781 pi->txpwr_limit[rate1] = txpwr_ptr1[rate2]; 1782 } 1783 1784 for (k = 0; k < 2; k++) { 1785 switch (k) { 1786 case 0: 1787 1788 rate_start_index = WL_TX_POWER_MCS20_SDM_FIRST; 1789 txpwr_ptr1 = txpwr->mcs_20_mimo; 1790 break; 1791 case 1: 1792 1793 rate_start_index = WL_TX_POWER_MCS40_SDM_FIRST; 1794 txpwr_ptr1 = txpwr->mcs_40_mimo; 1795 break; 1796 } 1797 for (rate1 = rate_start_index, rate2 = 0; 1798 rate2 < BRCMS_NUM_RATES_MCS_2_STREAM; 1799 rate1++, rate2++) 1800 pi->txpwr_limit[rate1] = txpwr_ptr1[rate2]; 1801 } 1802 1803 pi->txpwr_limit[WL_TX_POWER_MCS_32] = txpwr->mcs32; 1804 1805 pi->txpwr_limit[WL_TX_POWER_MCS40_CDD_FIRST] = 1806 min(pi->txpwr_limit[WL_TX_POWER_MCS40_CDD_FIRST], 1807 pi->txpwr_limit[WL_TX_POWER_MCS_32]); 1808 pi->txpwr_limit[WL_TX_POWER_MCS_32] = 1809 pi->txpwr_limit[WL_TX_POWER_MCS40_CDD_FIRST]; 1810 } 1811 } 1812 1813 void wlc_phy_txpwr_percent_set(struct brcms_phy_pub *ppi, u8 txpwr_percent) 1814 { 1815 struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro); 1816 1817 pi->txpwr_percent = txpwr_percent; 1818 } 1819 1820 void wlc_phy_machwcap_set(struct brcms_phy_pub *ppi, u32 machwcap) 1821 { 1822 struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro); 1823 1824 pi->sh->machwcap = machwcap; 1825 } 1826 1827 void wlc_phy_runbist_config(struct brcms_phy_pub *ppi, bool start_end) 1828 { 1829 struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro); 1830 u16 rxc; 1831 rxc = 0; 1832 1833 if (start_end == ON) { 1834 if (!ISNPHY(pi)) 1835 return; 1836 1837 if (NREV_IS(pi->pubpi.phy_rev, 3) 1838 || NREV_IS(pi->pubpi.phy_rev, 4)) { 1839 bcma_wflush16(pi->d11core, D11REGOFFS(phyregaddr), 1840 0xa0); 1841 bcma_set16(pi->d11core, D11REGOFFS(phyregdata), 1842 0x1 << 15); 1843 } 1844 } else { 1845 if (NREV_IS(pi->pubpi.phy_rev, 3) 1846 || NREV_IS(pi->pubpi.phy_rev, 4)) { 1847 bcma_wflush16(pi->d11core, D11REGOFFS(phyregaddr), 1848 0xa0); 1849 bcma_write16(pi->d11core, D11REGOFFS(phyregdata), rxc); 1850 } 1851 1852 wlc_phy_por_inform(ppi); 1853 } 1854 } 1855 1856 void 1857 wlc_phy_txpower_limit_set(struct brcms_phy_pub *ppi, struct txpwr_limits *txpwr, 1858 u16 chanspec) 1859 { 1860 struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro); 1861 1862 wlc_phy_txpower_reg_limit_calc(pi, txpwr, chanspec); 1863 1864 if (ISLCNPHY(pi)) { 1865 int i, j; 1866 for (i = TXP_FIRST_OFDM_20_CDD, j = 0; 1867 j < BRCMS_NUM_RATES_MCS_1_STREAM; i++, j++) { 1868 if (txpwr->mcs_20_siso[j]) 1869 pi->txpwr_limit[i] = txpwr->mcs_20_siso[j]; 1870 else 1871 pi->txpwr_limit[i] = txpwr->ofdm[j]; 1872 } 1873 } 1874 1875 wlapi_suspend_mac_and_wait(pi->sh->physhim); 1876 1877 wlc_phy_txpower_recalc_target(pi); 1878 wlc_phy_cal_txpower_recalc_sw(pi); 1879 wlapi_enable_mac(pi->sh->physhim); 1880 } 1881 1882 void wlc_phy_ofdm_rateset_war(struct brcms_phy_pub *pih, bool war) 1883 { 1884 struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro); 1885 1886 pi->ofdm_rateset_war = war; 1887 } 1888 1889 void wlc_phy_bf_preempt_enable(struct brcms_phy_pub *pih, bool bf_preempt) 1890 { 1891 struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro); 1892 1893 pi->bf_preempt_4306 = bf_preempt; 1894 } 1895 1896 void wlc_phy_txpower_update_shm(struct brcms_phy *pi) 1897 { 1898 int j; 1899 if (ISNPHY(pi)) 1900 return; 1901 1902 if (!pi->sh->clk) 1903 return; 1904 1905 if (pi->hwpwrctrl) { 1906 u16 offset; 1907 1908 wlapi_bmac_write_shm(pi->sh->physhim, M_TXPWR_MAX, 63); 1909 wlapi_bmac_write_shm(pi->sh->physhim, M_TXPWR_N, 1910 1 << NUM_TSSI_FRAMES); 1911 1912 wlapi_bmac_write_shm(pi->sh->physhim, M_TXPWR_TARGET, 1913 pi->tx_power_min << NUM_TSSI_FRAMES); 1914 1915 wlapi_bmac_write_shm(pi->sh->physhim, M_TXPWR_CUR, 1916 pi->hwpwr_txcur); 1917 1918 for (j = TXP_FIRST_OFDM; j <= TXP_LAST_OFDM; j++) { 1919 static const u8 ucode_ofdm_rates[] = { 1920 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c 1921 }; 1922 offset = wlapi_bmac_rate_shm_offset( 1923 pi->sh->physhim, 1924 ucode_ofdm_rates[j - TXP_FIRST_OFDM]); 1925 wlapi_bmac_write_shm(pi->sh->physhim, offset + 6, 1926 pi->tx_power_offset[j]); 1927 wlapi_bmac_write_shm(pi->sh->physhim, offset + 14, 1928 -(pi->tx_power_offset[j] / 2)); 1929 } 1930 1931 wlapi_bmac_mhf(pi->sh->physhim, MHF2, MHF2_HWPWRCTL, 1932 MHF2_HWPWRCTL, BRCM_BAND_ALL); 1933 } else { 1934 int i; 1935 1936 for (i = TXP_FIRST_OFDM; i <= TXP_LAST_OFDM; i++) 1937 pi->tx_power_offset[i] = 1938 (u8) roundup(pi->tx_power_offset[i], 8); 1939 wlapi_bmac_write_shm(pi->sh->physhim, M_OFDM_OFFSET, 1940 (u16) 1941 ((pi->tx_power_offset[TXP_FIRST_OFDM] 1942 + 7) >> 3)); 1943 } 1944 } 1945 1946 bool wlc_phy_txpower_hw_ctrl_get(struct brcms_phy_pub *ppi) 1947 { 1948 struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro); 1949 1950 if (ISNPHY(pi)) 1951 return pi->nphy_txpwrctrl; 1952 else 1953 return pi->hwpwrctrl; 1954 } 1955 1956 void wlc_phy_txpower_hw_ctrl_set(struct brcms_phy_pub *ppi, bool hwpwrctrl) 1957 { 1958 struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro); 1959 bool suspend; 1960 1961 if (!pi->hwpwrctrl_capable) 1962 return; 1963 1964 pi->hwpwrctrl = hwpwrctrl; 1965 pi->nphy_txpwrctrl = hwpwrctrl; 1966 pi->txpwrctrl = hwpwrctrl; 1967 1968 if (ISNPHY(pi)) { 1969 suspend = (0 == (bcma_read32(pi->d11core, 1970 D11REGOFFS(maccontrol)) & 1971 MCTL_EN_MAC)); 1972 if (!suspend) 1973 wlapi_suspend_mac_and_wait(pi->sh->physhim); 1974 1975 wlc_phy_txpwrctrl_enable_nphy(pi, pi->nphy_txpwrctrl); 1976 if (pi->nphy_txpwrctrl == PHY_TPC_HW_OFF) 1977 wlc_phy_txpwr_fixpower_nphy(pi); 1978 else 1979 mod_phy_reg(pi, 0x1e7, (0x7f << 0), 1980 pi->saved_txpwr_idx); 1981 1982 if (!suspend) 1983 wlapi_enable_mac(pi->sh->physhim); 1984 } 1985 } 1986 1987 void wlc_phy_txpower_ipa_upd(struct brcms_phy *pi) 1988 { 1989 1990 if (NREV_GE(pi->pubpi.phy_rev, 3)) { 1991 pi->ipa2g_on = (pi->srom_fem2g.extpagain == 2); 1992 pi->ipa5g_on = (pi->srom_fem5g.extpagain == 2); 1993 } else { 1994 pi->ipa2g_on = false; 1995 pi->ipa5g_on = false; 1996 } 1997 } 1998 1999 static u32 wlc_phy_txpower_est_power_nphy(struct brcms_phy *pi) 2000 { 2001 s16 tx0_status, tx1_status; 2002 u16 estPower1, estPower2; 2003 u8 pwr0, pwr1, adj_pwr0, adj_pwr1; 2004 u32 est_pwr; 2005 2006 estPower1 = read_phy_reg(pi, 0x118); 2007 estPower2 = read_phy_reg(pi, 0x119); 2008 2009 if ((estPower1 & (0x1 << 8)) == (0x1 << 8)) 2010 pwr0 = (u8) (estPower1 & (0xff << 0)) >> 0; 2011 else 2012 pwr0 = 0x80; 2013 2014 if ((estPower2 & (0x1 << 8)) == (0x1 << 8)) 2015 pwr1 = (u8) (estPower2 & (0xff << 0)) >> 0; 2016 else 2017 pwr1 = 0x80; 2018 2019 tx0_status = read_phy_reg(pi, 0x1ed); 2020 tx1_status = read_phy_reg(pi, 0x1ee); 2021 2022 if ((tx0_status & (0x1 << 15)) == (0x1 << 15)) 2023 adj_pwr0 = (u8) (tx0_status & (0xff << 0)) >> 0; 2024 else 2025 adj_pwr0 = 0x80; 2026 if ((tx1_status & (0x1 << 15)) == (0x1 << 15)) 2027 adj_pwr1 = (u8) (tx1_status & (0xff << 0)) >> 0; 2028 else 2029 adj_pwr1 = 0x80; 2030 2031 est_pwr = (u32) ((pwr0 << 24) | (pwr1 << 16) | (adj_pwr0 << 8) | 2032 adj_pwr1); 2033 2034 return est_pwr; 2035 } 2036 2037 void 2038 wlc_phy_txpower_get_current(struct brcms_phy_pub *ppi, struct tx_power *power, 2039 uint channel) 2040 { 2041 struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro); 2042 uint rate, num_rates; 2043 u8 min_pwr, max_pwr; 2044 2045 #if WL_TX_POWER_RATES != TXP_NUM_RATES 2046 #error "struct tx_power out of sync with this fn" 2047 #endif 2048 2049 if (ISNPHY(pi)) { 2050 power->rf_cores = 2; 2051 power->flags |= (WL_TX_POWER_F_MIMO); 2052 if (pi->nphy_txpwrctrl == PHY_TPC_HW_ON) 2053 power->flags |= 2054 (WL_TX_POWER_F_ENABLED | WL_TX_POWER_F_HW); 2055 } else if (ISLCNPHY(pi)) { 2056 power->rf_cores = 1; 2057 power->flags |= (WL_TX_POWER_F_SISO); 2058 if (pi->radiopwr_override == RADIOPWR_OVERRIDE_DEF) 2059 power->flags |= WL_TX_POWER_F_ENABLED; 2060 if (pi->hwpwrctrl) 2061 power->flags |= WL_TX_POWER_F_HW; 2062 } 2063 2064 num_rates = ((ISNPHY(pi)) ? (TXP_NUM_RATES) : 2065 ((ISLCNPHY(pi)) ? 2066 (TXP_LAST_OFDM_20_CDD + 1) : (TXP_LAST_OFDM + 1))); 2067 2068 for (rate = 0; rate < num_rates; rate++) { 2069 power->user_limit[rate] = pi->tx_user_target[rate]; 2070 wlc_phy_txpower_sromlimit(ppi, channel, &min_pwr, &max_pwr, 2071 rate); 2072 power->board_limit[rate] = (u8) max_pwr; 2073 power->target[rate] = pi->tx_power_target[rate]; 2074 } 2075 2076 if (ISNPHY(pi)) { 2077 u32 est_pout; 2078 2079 wlapi_suspend_mac_and_wait(pi->sh->physhim); 2080 wlc_phyreg_enter((struct brcms_phy_pub *) pi); 2081 est_pout = wlc_phy_txpower_est_power_nphy(pi); 2082 wlc_phyreg_exit((struct brcms_phy_pub *) pi); 2083 wlapi_enable_mac(pi->sh->physhim); 2084 2085 power->est_Pout[0] = (est_pout >> 8) & 0xff; 2086 power->est_Pout[1] = est_pout & 0xff; 2087 2088 power->est_Pout_act[0] = est_pout >> 24; 2089 power->est_Pout_act[1] = (est_pout >> 16) & 0xff; 2090 2091 if (power->est_Pout[0] == 0x80) 2092 power->est_Pout[0] = 0; 2093 if (power->est_Pout[1] == 0x80) 2094 power->est_Pout[1] = 0; 2095 2096 if (power->est_Pout_act[0] == 0x80) 2097 power->est_Pout_act[0] = 0; 2098 if (power->est_Pout_act[1] == 0x80) 2099 power->est_Pout_act[1] = 0; 2100 2101 power->est_Pout_cck = 0; 2102 2103 power->tx_power_max[0] = pi->tx_power_max; 2104 power->tx_power_max[1] = pi->tx_power_max; 2105 2106 power->tx_power_max_rate_ind[0] = pi->tx_power_max_rate_ind; 2107 power->tx_power_max_rate_ind[1] = pi->tx_power_max_rate_ind; 2108 } else if (pi->hwpwrctrl && pi->sh->up) { 2109 2110 wlc_phyreg_enter(ppi); 2111 if (ISLCNPHY(pi)) { 2112 2113 power->tx_power_max[0] = pi->tx_power_max; 2114 power->tx_power_max[1] = pi->tx_power_max; 2115 2116 power->tx_power_max_rate_ind[0] = 2117 pi->tx_power_max_rate_ind; 2118 power->tx_power_max_rate_ind[1] = 2119 pi->tx_power_max_rate_ind; 2120 2121 if (wlc_phy_tpc_isenabled_lcnphy(pi)) 2122 power->flags |= 2123 (WL_TX_POWER_F_HW | 2124 WL_TX_POWER_F_ENABLED); 2125 else 2126 power->flags &= 2127 ~(WL_TX_POWER_F_HW | 2128 WL_TX_POWER_F_ENABLED); 2129 2130 wlc_lcnphy_get_tssi(pi, (s8 *) &power->est_Pout[0], 2131 (s8 *) &power->est_Pout_cck); 2132 } 2133 wlc_phyreg_exit(ppi); 2134 } 2135 } 2136 2137 void wlc_phy_antsel_type_set(struct brcms_phy_pub *ppi, u8 antsel_type) 2138 { 2139 struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro); 2140 2141 pi->antsel_type = antsel_type; 2142 } 2143 2144 bool wlc_phy_test_ison(struct brcms_phy_pub *ppi) 2145 { 2146 struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro); 2147 2148 return pi->phytest_on; 2149 } 2150 2151 void wlc_phy_ant_rxdiv_set(struct brcms_phy_pub *ppi, u8 val) 2152 { 2153 struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro); 2154 bool suspend; 2155 2156 pi->sh->rx_antdiv = val; 2157 2158 if (!(ISNPHY(pi) && D11REV_IS(pi->sh->corerev, 16))) { 2159 if (val > ANT_RX_DIV_FORCE_1) 2160 wlapi_bmac_mhf(pi->sh->physhim, MHF1, MHF1_ANTDIV, 2161 MHF1_ANTDIV, BRCM_BAND_ALL); 2162 else 2163 wlapi_bmac_mhf(pi->sh->physhim, MHF1, MHF1_ANTDIV, 0, 2164 BRCM_BAND_ALL); 2165 } 2166 2167 if (ISNPHY(pi)) 2168 return; 2169 2170 if (!pi->sh->clk) 2171 return; 2172 2173 suspend = (0 == (bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) & 2174 MCTL_EN_MAC)); 2175 if (!suspend) 2176 wlapi_suspend_mac_and_wait(pi->sh->physhim); 2177 2178 if (ISLCNPHY(pi)) { 2179 if (val > ANT_RX_DIV_FORCE_1) { 2180 mod_phy_reg(pi, 0x410, (0x1 << 1), 0x01 << 1); 2181 mod_phy_reg(pi, 0x410, 2182 (0x1 << 0), 2183 ((ANT_RX_DIV_START_1 == val) ? 1 : 0) << 0); 2184 } else { 2185 mod_phy_reg(pi, 0x410, (0x1 << 1), 0x00 << 1); 2186 mod_phy_reg(pi, 0x410, (0x1 << 0), (u16) val << 0); 2187 } 2188 } 2189 2190 if (!suspend) 2191 wlapi_enable_mac(pi->sh->physhim); 2192 2193 return; 2194 } 2195 2196 static bool 2197 wlc_phy_noise_calc_phy(struct brcms_phy *pi, u32 *cmplx_pwr, s8 *pwr_ant) 2198 { 2199 s8 cmplx_pwr_dbm[PHY_CORE_MAX]; 2200 u8 i; 2201 2202 memset((u8 *) cmplx_pwr_dbm, 0, sizeof(cmplx_pwr_dbm)); 2203 wlc_phy_compute_dB(cmplx_pwr, cmplx_pwr_dbm, pi->pubpi.phy_corenum); 2204 2205 for (i = 0; i < pi->pubpi.phy_corenum; i++) { 2206 if (NREV_GE(pi->pubpi.phy_rev, 3)) 2207 cmplx_pwr_dbm[i] += (s8) PHY_NOISE_OFFSETFACT_4322; 2208 else 2209 2210 cmplx_pwr_dbm[i] += (s8) (16 - (15) * 3 - 70); 2211 } 2212 2213 for (i = 0; i < pi->pubpi.phy_corenum; i++) { 2214 pi->nphy_noise_win[i][pi->nphy_noise_index] = cmplx_pwr_dbm[i]; 2215 pwr_ant[i] = cmplx_pwr_dbm[i]; 2216 } 2217 pi->nphy_noise_index = 2218 MODINC_POW2(pi->nphy_noise_index, PHY_NOISE_WINDOW_SZ); 2219 return true; 2220 } 2221 2222 static void wlc_phy_noise_cb(struct brcms_phy *pi, u8 channel, s8 noise_dbm) 2223 { 2224 if (!pi->phynoise_state) 2225 return; 2226 2227 if (pi->phynoise_state & PHY_NOISE_STATE_MON) { 2228 if (pi->phynoise_chan_watchdog == channel) { 2229 pi->sh->phy_noise_window[pi->sh->phy_noise_index] = 2230 noise_dbm; 2231 pi->sh->phy_noise_index = 2232 MODINC(pi->sh->phy_noise_index, MA_WINDOW_SZ); 2233 } 2234 pi->phynoise_state &= ~PHY_NOISE_STATE_MON; 2235 } 2236 2237 if (pi->phynoise_state & PHY_NOISE_STATE_EXTERNAL) 2238 pi->phynoise_state &= ~PHY_NOISE_STATE_EXTERNAL; 2239 2240 } 2241 2242 static s8 wlc_phy_noise_read_shmem(struct brcms_phy *pi) 2243 { 2244 u32 cmplx_pwr[PHY_CORE_MAX]; 2245 s8 noise_dbm_ant[PHY_CORE_MAX]; 2246 u16 lo, hi; 2247 u32 cmplx_pwr_tot = 0; 2248 s8 noise_dbm = PHY_NOISE_FIXED_VAL_NPHY; 2249 u8 idx, core; 2250 2251 memset((u8 *) cmplx_pwr, 0, sizeof(cmplx_pwr)); 2252 memset((u8 *) noise_dbm_ant, 0, sizeof(noise_dbm_ant)); 2253 2254 for (idx = 0, core = 0; core < pi->pubpi.phy_corenum; idx += 2, 2255 core++) { 2256 lo = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP(idx)); 2257 hi = wlapi_bmac_read_shm(pi->sh->physhim, 2258 M_PWRIND_MAP(idx + 1)); 2259 cmplx_pwr[core] = (hi << 16) + lo; 2260 cmplx_pwr_tot += cmplx_pwr[core]; 2261 if (cmplx_pwr[core] == 0) 2262 noise_dbm_ant[core] = PHY_NOISE_FIXED_VAL_NPHY; 2263 else 2264 cmplx_pwr[core] >>= PHY_NOISE_SAMPLE_LOG_NUM_UCODE; 2265 } 2266 2267 if (cmplx_pwr_tot != 0) 2268 wlc_phy_noise_calc_phy(pi, cmplx_pwr, noise_dbm_ant); 2269 2270 for (core = 0; core < pi->pubpi.phy_corenum; core++) { 2271 pi->nphy_noise_win[core][pi->nphy_noise_index] = 2272 noise_dbm_ant[core]; 2273 2274 if (noise_dbm_ant[core] > noise_dbm) 2275 noise_dbm = noise_dbm_ant[core]; 2276 } 2277 pi->nphy_noise_index = 2278 MODINC_POW2(pi->nphy_noise_index, PHY_NOISE_WINDOW_SZ); 2279 2280 return noise_dbm; 2281 2282 } 2283 2284 void wlc_phy_noise_sample_intr(struct brcms_phy_pub *pih) 2285 { 2286 struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro); 2287 u16 jssi_aux; 2288 u8 channel = 0; 2289 s8 noise_dbm = PHY_NOISE_FIXED_VAL_NPHY; 2290 2291 if (ISLCNPHY(pi)) { 2292 u32 cmplx_pwr, cmplx_pwr0, cmplx_pwr1; 2293 u16 lo, hi; 2294 s32 pwr_offset_dB, gain_dB; 2295 u16 status_0, status_1; 2296 2297 jssi_aux = wlapi_bmac_read_shm(pi->sh->physhim, M_JSSI_AUX); 2298 channel = jssi_aux & D11_CURCHANNEL_MAX; 2299 2300 lo = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP0); 2301 hi = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP1); 2302 cmplx_pwr0 = (hi << 16) + lo; 2303 2304 lo = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP2); 2305 hi = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP3); 2306 cmplx_pwr1 = (hi << 16) + lo; 2307 cmplx_pwr = (cmplx_pwr0 + cmplx_pwr1) >> 6; 2308 2309 status_0 = 0x44; 2310 status_1 = wlapi_bmac_read_shm(pi->sh->physhim, M_JSSI_0); 2311 if ((cmplx_pwr > 0 && cmplx_pwr < 500) 2312 && ((status_1 & 0xc000) == 0x4000)) { 2313 2314 wlc_phy_compute_dB(&cmplx_pwr, &noise_dbm, 2315 pi->pubpi.phy_corenum); 2316 pwr_offset_dB = (read_phy_reg(pi, 0x434) & 0xFF); 2317 if (pwr_offset_dB > 127) 2318 pwr_offset_dB -= 256; 2319 2320 noise_dbm += (s8) (pwr_offset_dB - 30); 2321 2322 gain_dB = (status_0 & 0x1ff); 2323 noise_dbm -= (s8) (gain_dB); 2324 } else { 2325 noise_dbm = PHY_NOISE_FIXED_VAL_LCNPHY; 2326 } 2327 } else if (ISNPHY(pi)) { 2328 2329 jssi_aux = wlapi_bmac_read_shm(pi->sh->physhim, M_JSSI_AUX); 2330 channel = jssi_aux & D11_CURCHANNEL_MAX; 2331 2332 noise_dbm = wlc_phy_noise_read_shmem(pi); 2333 } 2334 2335 wlc_phy_noise_cb(pi, channel, noise_dbm); 2336 2337 } 2338 2339 static void 2340 wlc_phy_noise_sample_request(struct brcms_phy_pub *pih, u8 reason, u8 ch) 2341 { 2342 struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro); 2343 s8 noise_dbm = PHY_NOISE_FIXED_VAL_NPHY; 2344 bool sampling_in_progress = (pi->phynoise_state != 0); 2345 bool wait_for_intr = true; 2346 2347 switch (reason) { 2348 case PHY_NOISE_SAMPLE_MON: 2349 pi->phynoise_chan_watchdog = ch; 2350 pi->phynoise_state |= PHY_NOISE_STATE_MON; 2351 break; 2352 2353 case PHY_NOISE_SAMPLE_EXTERNAL: 2354 pi->phynoise_state |= PHY_NOISE_STATE_EXTERNAL; 2355 break; 2356 2357 default: 2358 break; 2359 } 2360 2361 if (sampling_in_progress) 2362 return; 2363 2364 pi->phynoise_now = pi->sh->now; 2365 2366 if (pi->phy_fixed_noise) { 2367 if (ISNPHY(pi)) { 2368 pi->nphy_noise_win[WL_ANT_IDX_1][pi->nphy_noise_index] = 2369 PHY_NOISE_FIXED_VAL_NPHY; 2370 pi->nphy_noise_win[WL_ANT_IDX_2][pi->nphy_noise_index] = 2371 PHY_NOISE_FIXED_VAL_NPHY; 2372 pi->nphy_noise_index = MODINC_POW2(pi->nphy_noise_index, 2373 PHY_NOISE_WINDOW_SZ); 2374 noise_dbm = PHY_NOISE_FIXED_VAL_NPHY; 2375 } else { 2376 noise_dbm = PHY_NOISE_FIXED_VAL; 2377 } 2378 2379 wait_for_intr = false; 2380 goto done; 2381 } 2382 2383 if (ISLCNPHY(pi)) { 2384 if (!pi->phynoise_polling 2385 || (reason == PHY_NOISE_SAMPLE_EXTERNAL)) { 2386 wlapi_bmac_write_shm(pi->sh->physhim, M_JSSI_0, 0); 2387 wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP0, 0); 2388 wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP1, 0); 2389 wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP2, 0); 2390 wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP3, 0); 2391 2392 bcma_set32(pi->d11core, D11REGOFFS(maccommand), 2393 MCMD_BG_NOISE); 2394 } else { 2395 wlapi_suspend_mac_and_wait(pi->sh->physhim); 2396 wlc_lcnphy_deaf_mode(pi, (bool) 0); 2397 noise_dbm = (s8) wlc_lcnphy_rx_signal_power(pi, 20); 2398 wlc_lcnphy_deaf_mode(pi, (bool) 1); 2399 wlapi_enable_mac(pi->sh->physhim); 2400 wait_for_intr = false; 2401 } 2402 } else if (ISNPHY(pi)) { 2403 if (!pi->phynoise_polling 2404 || (reason == PHY_NOISE_SAMPLE_EXTERNAL)) { 2405 2406 wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP0, 0); 2407 wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP1, 0); 2408 wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP2, 0); 2409 wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP3, 0); 2410 2411 bcma_set32(pi->d11core, D11REGOFFS(maccommand), 2412 MCMD_BG_NOISE); 2413 } else { 2414 struct phy_iq_est est[PHY_CORE_MAX]; 2415 u32 cmplx_pwr[PHY_CORE_MAX]; 2416 s8 noise_dbm_ant[PHY_CORE_MAX]; 2417 u16 log_num_samps, num_samps, classif_state = 0; 2418 u8 wait_time = 32; 2419 u8 wait_crs = 0; 2420 u8 i; 2421 2422 memset((u8 *) est, 0, sizeof(est)); 2423 memset((u8 *) cmplx_pwr, 0, sizeof(cmplx_pwr)); 2424 memset((u8 *) noise_dbm_ant, 0, sizeof(noise_dbm_ant)); 2425 2426 log_num_samps = PHY_NOISE_SAMPLE_LOG_NUM_NPHY; 2427 num_samps = 1 << log_num_samps; 2428 2429 wlapi_suspend_mac_and_wait(pi->sh->physhim); 2430 classif_state = wlc_phy_classifier_nphy(pi, 0, 0); 2431 wlc_phy_classifier_nphy(pi, 3, 0); 2432 wlc_phy_rx_iq_est_nphy(pi, est, num_samps, wait_time, 2433 wait_crs); 2434 wlc_phy_classifier_nphy(pi, (0x7 << 0), classif_state); 2435 wlapi_enable_mac(pi->sh->physhim); 2436 2437 for (i = 0; i < pi->pubpi.phy_corenum; i++) 2438 cmplx_pwr[i] = (est[i].i_pwr + est[i].q_pwr) >> 2439 log_num_samps; 2440 2441 wlc_phy_noise_calc_phy(pi, cmplx_pwr, noise_dbm_ant); 2442 2443 for (i = 0; i < pi->pubpi.phy_corenum; i++) { 2444 pi->nphy_noise_win[i][pi->nphy_noise_index] = 2445 noise_dbm_ant[i]; 2446 2447 if (noise_dbm_ant[i] > noise_dbm) 2448 noise_dbm = noise_dbm_ant[i]; 2449 } 2450 pi->nphy_noise_index = MODINC_POW2(pi->nphy_noise_index, 2451 PHY_NOISE_WINDOW_SZ); 2452 2453 wait_for_intr = false; 2454 } 2455 } 2456 2457 done: 2458 2459 if (!wait_for_intr) 2460 wlc_phy_noise_cb(pi, ch, noise_dbm); 2461 2462 } 2463 2464 void wlc_phy_noise_sample_request_external(struct brcms_phy_pub *pih) 2465 { 2466 u8 channel; 2467 2468 channel = CHSPEC_CHANNEL(wlc_phy_chanspec_get(pih)); 2469 2470 wlc_phy_noise_sample_request(pih, PHY_NOISE_SAMPLE_EXTERNAL, channel); 2471 } 2472 2473 static const s8 lcnphy_gain_index_offset_for_pkt_rssi[] = { 2474 8, 2475 8, 2476 8, 2477 8, 2478 8, 2479 8, 2480 8, 2481 9, 2482 10, 2483 8, 2484 8, 2485 7, 2486 7, 2487 1, 2488 2, 2489 2, 2490 2, 2491 2, 2492 2, 2493 2, 2494 2, 2495 2, 2496 2, 2497 2, 2498 2, 2499 2, 2500 2, 2501 2, 2502 2, 2503 2, 2504 2, 2505 2, 2506 1, 2507 1, 2508 0, 2509 0, 2510 0, 2511 0 2512 }; 2513 2514 void wlc_phy_compute_dB(u32 *cmplx_pwr, s8 *p_cmplx_pwr_dB, u8 core) 2515 { 2516 u8 msb, secondmsb, i; 2517 u32 tmp; 2518 2519 for (i = 0; i < core; i++) { 2520 secondmsb = 0; 2521 tmp = cmplx_pwr[i]; 2522 msb = fls(tmp); 2523 if (msb) 2524 secondmsb = (u8) ((tmp >> (--msb - 1)) & 1); 2525 p_cmplx_pwr_dB[i] = (s8) (3 * msb + 2 * secondmsb); 2526 } 2527 } 2528 2529 int wlc_phy_rssi_compute(struct brcms_phy_pub *pih, 2530 struct d11rxhdr *rxh) 2531 { 2532 int rssi = rxh->PhyRxStatus_1 & PRXS1_JSSI_MASK; 2533 uint radioid = pih->radioid; 2534 struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro); 2535 2536 if ((pi->sh->corerev >= 11) 2537 && !(rxh->RxStatus2 & RXS_PHYRXST_VALID)) { 2538 rssi = BRCMS_RSSI_INVALID; 2539 goto end; 2540 } 2541 2542 if (ISLCNPHY(pi)) { 2543 u8 gidx = (rxh->PhyRxStatus_2 & 0xFC00) >> 10; 2544 struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; 2545 2546 if (rssi > 127) 2547 rssi -= 256; 2548 2549 rssi = rssi + lcnphy_gain_index_offset_for_pkt_rssi[gidx]; 2550 if ((rssi > -46) && (gidx > 18)) 2551 rssi = rssi + 7; 2552 2553 rssi = rssi + pi_lcn->lcnphy_pkteng_rssi_slope; 2554 2555 rssi = rssi + 2; 2556 2557 } 2558 2559 if (ISLCNPHY(pi)) { 2560 if (rssi > 127) 2561 rssi -= 256; 2562 } else if (radioid == BCM2055_ID || radioid == BCM2056_ID 2563 || radioid == BCM2057_ID) { 2564 rssi = wlc_phy_rssi_compute_nphy(pi, rxh); 2565 } 2566 2567 end: 2568 return rssi; 2569 } 2570 2571 void wlc_phy_freqtrack_start(struct brcms_phy_pub *pih) 2572 { 2573 return; 2574 } 2575 2576 void wlc_phy_freqtrack_end(struct brcms_phy_pub *pih) 2577 { 2578 return; 2579 } 2580 2581 void wlc_phy_set_deaf(struct brcms_phy_pub *ppi, bool user_flag) 2582 { 2583 struct brcms_phy *pi; 2584 pi = (struct brcms_phy *) ppi; 2585 2586 if (ISLCNPHY(pi)) 2587 wlc_lcnphy_deaf_mode(pi, true); 2588 else if (ISNPHY(pi)) 2589 wlc_nphy_deaf_mode(pi, true); 2590 } 2591 2592 void wlc_phy_watchdog(struct brcms_phy_pub *pih) 2593 { 2594 struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro); 2595 bool delay_phy_cal = false; 2596 pi->sh->now++; 2597 2598 if (!pi->watchdog_override) 2599 return; 2600 2601 if (!(SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi))) 2602 wlc_phy_noise_sample_request((struct brcms_phy_pub *) pi, 2603 PHY_NOISE_SAMPLE_MON, 2604 CHSPEC_CHANNEL(pi-> 2605 radio_chanspec)); 2606 2607 if (pi->phynoise_state && (pi->sh->now - pi->phynoise_now) > 5) 2608 pi->phynoise_state = 0; 2609 2610 if ((!pi->phycal_txpower) || 2611 ((pi->sh->now - pi->phycal_txpower) >= pi->sh->fast_timer)) { 2612 2613 if (!SCAN_INPROG_PHY(pi) && wlc_phy_cal_txpower_recalc_sw(pi)) 2614 pi->phycal_txpower = pi->sh->now; 2615 } 2616 2617 if ((SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi) 2618 || ASSOC_INPROG_PHY(pi))) 2619 return; 2620 2621 if (ISNPHY(pi) && !pi->disable_percal && !delay_phy_cal) { 2622 2623 if ((pi->nphy_perical != PHY_PERICAL_DISABLE) && 2624 (pi->nphy_perical != PHY_PERICAL_MANUAL) && 2625 ((pi->sh->now - pi->nphy_perical_last) >= 2626 pi->sh->glacial_timer)) 2627 wlc_phy_cal_perical((struct brcms_phy_pub *) pi, 2628 PHY_PERICAL_WATCHDOG); 2629 2630 wlc_phy_txpwr_papd_cal_nphy(pi); 2631 } 2632 2633 if (ISLCNPHY(pi)) { 2634 if (pi->phy_forcecal || 2635 ((pi->sh->now - pi->phy_lastcal) >= 2636 pi->sh->glacial_timer)) { 2637 if (!(SCAN_RM_IN_PROGRESS(pi) || ASSOC_INPROG_PHY(pi))) 2638 wlc_lcnphy_calib_modes( 2639 pi, 2640 LCNPHY_PERICAL_TEMPBASED_TXPWRCTRL); 2641 if (! 2642 (SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi) 2643 || ASSOC_INPROG_PHY(pi) 2644 || pi->carrier_suppr_disable 2645 || pi->disable_percal)) 2646 wlc_lcnphy_calib_modes(pi, 2647 PHY_PERICAL_WATCHDOG); 2648 } 2649 } 2650 } 2651 2652 void wlc_phy_BSSinit(struct brcms_phy_pub *pih, bool bonlyap, int rssi) 2653 { 2654 struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro); 2655 uint i; 2656 uint k; 2657 2658 for (i = 0; i < MA_WINDOW_SZ; i++) 2659 pi->sh->phy_noise_window[i] = (s8) (rssi & 0xff); 2660 if (ISLCNPHY(pi)) { 2661 for (i = 0; i < MA_WINDOW_SZ; i++) 2662 pi->sh->phy_noise_window[i] = 2663 PHY_NOISE_FIXED_VAL_LCNPHY; 2664 } 2665 pi->sh->phy_noise_index = 0; 2666 2667 for (i = 0; i < PHY_NOISE_WINDOW_SZ; i++) { 2668 for (k = WL_ANT_IDX_1; k < WL_ANT_RX_MAX; k++) 2669 pi->nphy_noise_win[k][i] = PHY_NOISE_FIXED_VAL_NPHY; 2670 } 2671 pi->nphy_noise_index = 0; 2672 } 2673 2674 void 2675 wlc_phy_papd_decode_epsilon(u32 epsilon, s32 *eps_real, s32 *eps_imag) 2676 { 2677 *eps_imag = (epsilon >> 13); 2678 if (*eps_imag > 0xfff) 2679 *eps_imag -= 0x2000; 2680 2681 *eps_real = (epsilon & 0x1fff); 2682 if (*eps_real > 0xfff) 2683 *eps_real -= 0x2000; 2684 } 2685 2686 void wlc_phy_cal_perical_mphase_reset(struct brcms_phy *pi) 2687 { 2688 wlapi_del_timer(pi->phycal_timer); 2689 2690 pi->cal_type_override = PHY_PERICAL_AUTO; 2691 pi->mphase_cal_phase_id = MPHASE_CAL_STATE_IDLE; 2692 pi->mphase_txcal_cmdidx = 0; 2693 } 2694 2695 static void 2696 wlc_phy_cal_perical_mphase_schedule(struct brcms_phy *pi, uint delay) 2697 { 2698 2699 if ((pi->nphy_perical != PHY_PERICAL_MPHASE) && 2700 (pi->nphy_perical != PHY_PERICAL_MANUAL)) 2701 return; 2702 2703 wlapi_del_timer(pi->phycal_timer); 2704 2705 pi->mphase_cal_phase_id = MPHASE_CAL_STATE_INIT; 2706 wlapi_add_timer(pi->phycal_timer, delay, 0); 2707 } 2708 2709 void wlc_phy_cal_perical(struct brcms_phy_pub *pih, u8 reason) 2710 { 2711 s16 nphy_currtemp = 0; 2712 s16 delta_temp = 0; 2713 bool do_periodic_cal = true; 2714 struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro); 2715 2716 if (!ISNPHY(pi)) 2717 return; 2718 2719 if ((pi->nphy_perical == PHY_PERICAL_DISABLE) || 2720 (pi->nphy_perical == PHY_PERICAL_MANUAL)) 2721 return; 2722 2723 switch (reason) { 2724 case PHY_PERICAL_DRIVERUP: 2725 break; 2726 2727 case PHY_PERICAL_PHYINIT: 2728 if (pi->nphy_perical == PHY_PERICAL_MPHASE) { 2729 if (PHY_PERICAL_MPHASE_PENDING(pi)) 2730 wlc_phy_cal_perical_mphase_reset(pi); 2731 2732 wlc_phy_cal_perical_mphase_schedule( 2733 pi, 2734 PHY_PERICAL_INIT_DELAY); 2735 } 2736 break; 2737 2738 case PHY_PERICAL_JOIN_BSS: 2739 case PHY_PERICAL_START_IBSS: 2740 case PHY_PERICAL_UP_BSS: 2741 if ((pi->nphy_perical == PHY_PERICAL_MPHASE) && 2742 PHY_PERICAL_MPHASE_PENDING(pi)) 2743 wlc_phy_cal_perical_mphase_reset(pi); 2744 2745 pi->first_cal_after_assoc = true; 2746 2747 pi->cal_type_override = PHY_PERICAL_FULL; 2748 2749 if (pi->phycal_tempdelta) 2750 pi->nphy_lastcal_temp = wlc_phy_tempsense_nphy(pi); 2751 2752 wlc_phy_cal_perical_nphy_run(pi, PHY_PERICAL_FULL); 2753 break; 2754 2755 case PHY_PERICAL_WATCHDOG: 2756 if (pi->phycal_tempdelta) { 2757 nphy_currtemp = wlc_phy_tempsense_nphy(pi); 2758 delta_temp = 2759 (nphy_currtemp > pi->nphy_lastcal_temp) ? 2760 nphy_currtemp - pi->nphy_lastcal_temp : 2761 pi->nphy_lastcal_temp - nphy_currtemp; 2762 2763 if ((delta_temp < (s16) pi->phycal_tempdelta) && 2764 (pi->nphy_txiqlocal_chanspec == 2765 pi->radio_chanspec)) 2766 do_periodic_cal = false; 2767 else 2768 pi->nphy_lastcal_temp = nphy_currtemp; 2769 } 2770 2771 if (do_periodic_cal) { 2772 if (pi->nphy_perical == PHY_PERICAL_MPHASE) { 2773 if (!PHY_PERICAL_MPHASE_PENDING(pi)) 2774 wlc_phy_cal_perical_mphase_schedule( 2775 pi, 2776 PHY_PERICAL_WDOG_DELAY); 2777 } else if (pi->nphy_perical == PHY_PERICAL_SPHASE) 2778 wlc_phy_cal_perical_nphy_run(pi, 2779 PHY_PERICAL_AUTO); 2780 } 2781 break; 2782 default: 2783 break; 2784 } 2785 } 2786 2787 void wlc_phy_cal_perical_mphase_restart(struct brcms_phy *pi) 2788 { 2789 pi->mphase_cal_phase_id = MPHASE_CAL_STATE_INIT; 2790 pi->mphase_txcal_cmdidx = 0; 2791 } 2792 2793 u8 wlc_phy_nbits(s32 value) 2794 { 2795 s32 abs_val; 2796 u8 nbits = 0; 2797 2798 abs_val = abs(value); 2799 while ((abs_val >> nbits) > 0) 2800 nbits++; 2801 2802 return nbits; 2803 } 2804 2805 void wlc_phy_stf_chain_init(struct brcms_phy_pub *pih, u8 txchain, u8 rxchain) 2806 { 2807 struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro); 2808 2809 pi->sh->hw_phytxchain = txchain; 2810 pi->sh->hw_phyrxchain = rxchain; 2811 pi->sh->phytxchain = txchain; 2812 pi->sh->phyrxchain = rxchain; 2813 pi->pubpi.phy_corenum = (u8)hweight8(pi->sh->phyrxchain); 2814 } 2815 2816 void wlc_phy_stf_chain_set(struct brcms_phy_pub *pih, u8 txchain, u8 rxchain) 2817 { 2818 struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro); 2819 2820 pi->sh->phytxchain = txchain; 2821 2822 if (ISNPHY(pi)) 2823 wlc_phy_rxcore_setstate_nphy(pih, rxchain); 2824 2825 pi->pubpi.phy_corenum = (u8)hweight8(pi->sh->phyrxchain); 2826 } 2827 2828 void wlc_phy_stf_chain_get(struct brcms_phy_pub *pih, u8 *txchain, u8 *rxchain) 2829 { 2830 struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro); 2831 2832 *txchain = pi->sh->phytxchain; 2833 *rxchain = pi->sh->phyrxchain; 2834 } 2835 2836 u8 wlc_phy_stf_chain_active_get(struct brcms_phy_pub *pih) 2837 { 2838 s16 nphy_currtemp; 2839 u8 active_bitmap; 2840 struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro); 2841 2842 active_bitmap = (pi->phy_txcore_heatedup) ? 0x31 : 0x33; 2843 2844 if (!pi->watchdog_override) 2845 return active_bitmap; 2846 2847 if (NREV_GE(pi->pubpi.phy_rev, 6)) { 2848 wlapi_suspend_mac_and_wait(pi->sh->physhim); 2849 nphy_currtemp = wlc_phy_tempsense_nphy(pi); 2850 wlapi_enable_mac(pi->sh->physhim); 2851 2852 if (!pi->phy_txcore_heatedup) { 2853 if (nphy_currtemp >= pi->phy_txcore_disable_temp) { 2854 active_bitmap &= 0xFD; 2855 pi->phy_txcore_heatedup = true; 2856 } 2857 } else { 2858 if (nphy_currtemp <= pi->phy_txcore_enable_temp) { 2859 active_bitmap |= 0x2; 2860 pi->phy_txcore_heatedup = false; 2861 } 2862 } 2863 } 2864 2865 return active_bitmap; 2866 } 2867 2868 s8 wlc_phy_stf_ssmode_get(struct brcms_phy_pub *pih, u16 chanspec) 2869 { 2870 struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro); 2871 u8 siso_mcs_id, cdd_mcs_id; 2872 2873 siso_mcs_id = 2874 (CHSPEC_IS40(chanspec)) ? TXP_FIRST_MCS_40_SISO : 2875 TXP_FIRST_MCS_20_SISO; 2876 cdd_mcs_id = 2877 (CHSPEC_IS40(chanspec)) ? TXP_FIRST_MCS_40_CDD : 2878 TXP_FIRST_MCS_20_CDD; 2879 2880 if (pi->tx_power_target[siso_mcs_id] > 2881 (pi->tx_power_target[cdd_mcs_id] + 12)) 2882 return PHY_TXC1_MODE_SISO; 2883 else 2884 return PHY_TXC1_MODE_CDD; 2885 } 2886 2887 const u8 *wlc_phy_get_ofdm_rate_lookup(void) 2888 { 2889 return ofdm_rate_lookup; 2890 } 2891 2892 void wlc_lcnphy_epa_switch(struct brcms_phy *pi, bool mode) 2893 { 2894 if ((pi->sh->chip == BCMA_CHIP_ID_BCM4313) && 2895 (pi->sh->boardflags & BFL_FEM)) { 2896 if (mode) { 2897 u16 txant = 0; 2898 txant = wlapi_bmac_get_txant(pi->sh->physhim); 2899 if (txant == 1) { 2900 mod_phy_reg(pi, 0x44d, (0x1 << 2), (1) << 2); 2901 2902 mod_phy_reg(pi, 0x44c, (0x1 << 2), (1) << 2); 2903 2904 } 2905 2906 bcma_chipco_gpio_control(&pi->d11core->bus->drv_cc, 2907 0x0, 0x0); 2908 bcma_chipco_gpio_out(&pi->d11core->bus->drv_cc, 2909 ~0x40, 0x40); 2910 bcma_chipco_gpio_outen(&pi->d11core->bus->drv_cc, 2911 ~0x40, 0x40); 2912 } else { 2913 mod_phy_reg(pi, 0x44c, (0x1 << 2), (0) << 2); 2914 2915 mod_phy_reg(pi, 0x44d, (0x1 << 2), (0) << 2); 2916 2917 bcma_chipco_gpio_out(&pi->d11core->bus->drv_cc, 2918 ~0x40, 0x00); 2919 bcma_chipco_gpio_outen(&pi->d11core->bus->drv_cc, 2920 ~0x40, 0x00); 2921 bcma_chipco_gpio_control(&pi->d11core->bus->drv_cc, 2922 0x0, 0x40); 2923 } 2924 } 2925 } 2926 2927 void wlc_phy_ldpc_override_set(struct brcms_phy_pub *ppi, bool ldpc) 2928 { 2929 return; 2930 } 2931 2932 void 2933 wlc_phy_get_pwrdet_offsets(struct brcms_phy *pi, s8 *cckoffset, s8 *ofdmoffset) 2934 { 2935 *cckoffset = 0; 2936 *ofdmoffset = 0; 2937 } 2938 2939 s8 wlc_phy_upd_rssi_offset(struct brcms_phy *pi, s8 rssi, u16 chanspec) 2940 { 2941 2942 return rssi; 2943 } 2944 2945 bool wlc_phy_txpower_ipa_ison(struct brcms_phy_pub *ppi) 2946 { 2947 struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro); 2948 2949 if (ISNPHY(pi)) 2950 return wlc_phy_n_txpower_ipa_ison(pi); 2951 else 2952 return false; 2953 } 2954