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