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