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 s8 temp, vbat; 1517 1518 for (i = 0; i < TXP_NUM_RATES; i++) 1519 pi->txpwr_env_limit[i] = BRCMS_TXPWR_MAX; 1520 1521 vbat = wlc_phy_env_measure_vbat(pi); 1522 temp = wlc_phy_env_measure_temperature(pi); 1523 1524 } 1525 1526 static s8 1527 wlc_user_txpwr_antport_to_rfport(struct brcms_phy *pi, uint chan, u32 band, 1528 u8 rate) 1529 { 1530 return 0; 1531 } 1532 1533 void wlc_phy_txpower_recalc_target(struct brcms_phy *pi) 1534 { 1535 u8 maxtxpwr, mintxpwr, rate, pactrl; 1536 uint target_chan; 1537 u8 tx_pwr_target[TXP_NUM_RATES]; 1538 u8 tx_pwr_max = 0; 1539 u8 tx_pwr_min = 255; 1540 u8 tx_pwr_max_rate_ind = 0; 1541 u8 max_num_rate; 1542 u8 start_rate = 0; 1543 u16 chspec; 1544 u32 band = CHSPEC2BAND(pi->radio_chanspec); 1545 void (*txpwr_recalc_fn)(struct brcms_phy *) = NULL; 1546 1547 chspec = pi->radio_chanspec; 1548 if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_NONE) 1549 target_chan = CHSPEC_CHANNEL(chspec); 1550 else if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_UPPER) 1551 target_chan = upper_20_sb(CHSPEC_CHANNEL(chspec)); 1552 else 1553 target_chan = lower_20_sb(CHSPEC_CHANNEL(chspec)); 1554 1555 pactrl = 0; 1556 if (ISLCNPHY(pi)) { 1557 u32 offset_mcs, i; 1558 1559 if (CHSPEC_IS40(pi->radio_chanspec)) { 1560 offset_mcs = pi->mcs40_po; 1561 for (i = TXP_FIRST_SISO_MCS_20; 1562 i <= TXP_LAST_SISO_MCS_20; i++) { 1563 pi->tx_srom_max_rate_2g[i - 8] = 1564 pi->tx_srom_max_2g - 1565 ((offset_mcs & 0xf) * 2); 1566 offset_mcs >>= 4; 1567 } 1568 } else { 1569 offset_mcs = pi->mcs20_po; 1570 for (i = TXP_FIRST_SISO_MCS_20; 1571 i <= TXP_LAST_SISO_MCS_20; i++) { 1572 pi->tx_srom_max_rate_2g[i - 8] = 1573 pi->tx_srom_max_2g - 1574 ((offset_mcs & 0xf) * 2); 1575 offset_mcs >>= 4; 1576 } 1577 } 1578 } 1579 1580 max_num_rate = ((ISNPHY(pi)) ? (TXP_NUM_RATES) : 1581 ((ISLCNPHY(pi)) ? 1582 (TXP_LAST_SISO_MCS_20 + 1) : (TXP_LAST_OFDM + 1))); 1583 1584 wlc_phy_upd_env_txpwr_rate_limits(pi, band); 1585 1586 for (rate = start_rate; rate < max_num_rate; rate++) { 1587 1588 tx_pwr_target[rate] = pi->tx_user_target[rate]; 1589 1590 if (pi->user_txpwr_at_rfport) 1591 tx_pwr_target[rate] += 1592 wlc_user_txpwr_antport_to_rfport(pi, 1593 target_chan, 1594 band, 1595 rate); 1596 1597 wlc_phy_txpower_sromlimit((struct brcms_phy_pub *) pi, 1598 target_chan, 1599 &mintxpwr, &maxtxpwr, rate); 1600 1601 maxtxpwr = min(maxtxpwr, pi->txpwr_limit[rate]); 1602 1603 maxtxpwr = (maxtxpwr > pactrl) ? (maxtxpwr - pactrl) : 0; 1604 1605 maxtxpwr = (maxtxpwr > 6) ? (maxtxpwr - 6) : 0; 1606 1607 maxtxpwr = min(maxtxpwr, tx_pwr_target[rate]); 1608 1609 if (pi->txpwr_percent <= 100) 1610 maxtxpwr = (maxtxpwr * pi->txpwr_percent) / 100; 1611 1612 tx_pwr_target[rate] = max(maxtxpwr, mintxpwr); 1613 1614 tx_pwr_target[rate] = 1615 min(tx_pwr_target[rate], pi->txpwr_env_limit[rate]); 1616 1617 if (tx_pwr_target[rate] > tx_pwr_max) 1618 tx_pwr_max_rate_ind = rate; 1619 1620 tx_pwr_max = max(tx_pwr_max, tx_pwr_target[rate]); 1621 tx_pwr_min = min(tx_pwr_min, tx_pwr_target[rate]); 1622 } 1623 1624 memset(pi->tx_power_offset, 0, sizeof(pi->tx_power_offset)); 1625 pi->tx_power_max = tx_pwr_max; 1626 pi->tx_power_min = tx_pwr_min; 1627 pi->tx_power_max_rate_ind = tx_pwr_max_rate_ind; 1628 for (rate = 0; rate < max_num_rate; rate++) { 1629 1630 pi->tx_power_target[rate] = tx_pwr_target[rate]; 1631 1632 if (!pi->hwpwrctrl || ISNPHY(pi)) 1633 pi->tx_power_offset[rate] = 1634 pi->tx_power_max - pi->tx_power_target[rate]; 1635 else 1636 pi->tx_power_offset[rate] = 1637 pi->tx_power_target[rate] - pi->tx_power_min; 1638 } 1639 1640 txpwr_recalc_fn = pi->pi_fptr.txpwrrecalc; 1641 if (txpwr_recalc_fn) 1642 (*txpwr_recalc_fn)(pi); 1643 } 1644 1645 static void 1646 wlc_phy_txpower_reg_limit_calc(struct brcms_phy *pi, struct txpwr_limits *txpwr, 1647 u16 chanspec) 1648 { 1649 u8 tmp_txpwr_limit[2 * BRCMS_NUM_RATES_OFDM]; 1650 u8 *txpwr_ptr1 = NULL, *txpwr_ptr2 = NULL; 1651 int rate_start_index = 0, rate1, rate2, k; 1652 1653 for (rate1 = WL_TX_POWER_CCK_FIRST, rate2 = 0; 1654 rate2 < WL_TX_POWER_CCK_NUM; rate1++, rate2++) 1655 pi->txpwr_limit[rate1] = txpwr->cck[rate2]; 1656 1657 for (rate1 = WL_TX_POWER_OFDM_FIRST, rate2 = 0; 1658 rate2 < WL_TX_POWER_OFDM_NUM; rate1++, rate2++) 1659 pi->txpwr_limit[rate1] = txpwr->ofdm[rate2]; 1660 1661 if (ISNPHY(pi)) { 1662 1663 for (k = 0; k < 4; k++) { 1664 switch (k) { 1665 case 0: 1666 1667 txpwr_ptr1 = txpwr->mcs_20_siso; 1668 txpwr_ptr2 = txpwr->ofdm; 1669 rate_start_index = WL_TX_POWER_OFDM_FIRST; 1670 break; 1671 case 1: 1672 1673 txpwr_ptr1 = txpwr->mcs_20_cdd; 1674 txpwr_ptr2 = txpwr->ofdm_cdd; 1675 rate_start_index = WL_TX_POWER_OFDM20_CDD_FIRST; 1676 break; 1677 case 2: 1678 1679 txpwr_ptr1 = txpwr->mcs_40_siso; 1680 txpwr_ptr2 = txpwr->ofdm_40_siso; 1681 rate_start_index = 1682 WL_TX_POWER_OFDM40_SISO_FIRST; 1683 break; 1684 case 3: 1685 1686 txpwr_ptr1 = txpwr->mcs_40_cdd; 1687 txpwr_ptr2 = txpwr->ofdm_40_cdd; 1688 rate_start_index = WL_TX_POWER_OFDM40_CDD_FIRST; 1689 break; 1690 } 1691 1692 for (rate2 = 0; rate2 < BRCMS_NUM_RATES_OFDM; 1693 rate2++) { 1694 tmp_txpwr_limit[rate2] = 0; 1695 tmp_txpwr_limit[BRCMS_NUM_RATES_OFDM + rate2] = 1696 txpwr_ptr1[rate2]; 1697 } 1698 wlc_phy_mcs_to_ofdm_powers_nphy( 1699 tmp_txpwr_limit, 0, 1700 BRCMS_NUM_RATES_OFDM - 1701 1, BRCMS_NUM_RATES_OFDM); 1702 for (rate1 = rate_start_index, rate2 = 0; 1703 rate2 < BRCMS_NUM_RATES_OFDM; rate1++, rate2++) 1704 pi->txpwr_limit[rate1] = 1705 min(txpwr_ptr2[rate2], 1706 tmp_txpwr_limit[rate2]); 1707 } 1708 1709 for (k = 0; k < 4; k++) { 1710 switch (k) { 1711 case 0: 1712 1713 txpwr_ptr1 = txpwr->ofdm; 1714 txpwr_ptr2 = txpwr->mcs_20_siso; 1715 rate_start_index = WL_TX_POWER_MCS20_SISO_FIRST; 1716 break; 1717 case 1: 1718 1719 txpwr_ptr1 = txpwr->ofdm_cdd; 1720 txpwr_ptr2 = txpwr->mcs_20_cdd; 1721 rate_start_index = WL_TX_POWER_MCS20_CDD_FIRST; 1722 break; 1723 case 2: 1724 1725 txpwr_ptr1 = txpwr->ofdm_40_siso; 1726 txpwr_ptr2 = txpwr->mcs_40_siso; 1727 rate_start_index = WL_TX_POWER_MCS40_SISO_FIRST; 1728 break; 1729 case 3: 1730 1731 txpwr_ptr1 = txpwr->ofdm_40_cdd; 1732 txpwr_ptr2 = txpwr->mcs_40_cdd; 1733 rate_start_index = WL_TX_POWER_MCS40_CDD_FIRST; 1734 break; 1735 } 1736 for (rate2 = 0; rate2 < BRCMS_NUM_RATES_OFDM; 1737 rate2++) { 1738 tmp_txpwr_limit[rate2] = 0; 1739 tmp_txpwr_limit[BRCMS_NUM_RATES_OFDM + rate2] = 1740 txpwr_ptr1[rate2]; 1741 } 1742 wlc_phy_ofdm_to_mcs_powers_nphy( 1743 tmp_txpwr_limit, 0, 1744 BRCMS_NUM_RATES_OFDM - 1745 1, BRCMS_NUM_RATES_OFDM); 1746 for (rate1 = rate_start_index, rate2 = 0; 1747 rate2 < BRCMS_NUM_RATES_MCS_1_STREAM; 1748 rate1++, rate2++) 1749 pi->txpwr_limit[rate1] = 1750 min(txpwr_ptr2[rate2], 1751 tmp_txpwr_limit[rate2]); 1752 } 1753 1754 for (k = 0; k < 2; k++) { 1755 switch (k) { 1756 case 0: 1757 1758 rate_start_index = WL_TX_POWER_MCS20_STBC_FIRST; 1759 txpwr_ptr1 = txpwr->mcs_20_stbc; 1760 break; 1761 case 1: 1762 1763 rate_start_index = WL_TX_POWER_MCS40_STBC_FIRST; 1764 txpwr_ptr1 = txpwr->mcs_40_stbc; 1765 break; 1766 } 1767 for (rate1 = rate_start_index, rate2 = 0; 1768 rate2 < BRCMS_NUM_RATES_MCS_1_STREAM; 1769 rate1++, rate2++) 1770 pi->txpwr_limit[rate1] = txpwr_ptr1[rate2]; 1771 } 1772 1773 for (k = 0; k < 2; k++) { 1774 switch (k) { 1775 case 0: 1776 1777 rate_start_index = WL_TX_POWER_MCS20_SDM_FIRST; 1778 txpwr_ptr1 = txpwr->mcs_20_mimo; 1779 break; 1780 case 1: 1781 1782 rate_start_index = WL_TX_POWER_MCS40_SDM_FIRST; 1783 txpwr_ptr1 = txpwr->mcs_40_mimo; 1784 break; 1785 } 1786 for (rate1 = rate_start_index, rate2 = 0; 1787 rate2 < BRCMS_NUM_RATES_MCS_2_STREAM; 1788 rate1++, rate2++) 1789 pi->txpwr_limit[rate1] = txpwr_ptr1[rate2]; 1790 } 1791 1792 pi->txpwr_limit[WL_TX_POWER_MCS_32] = txpwr->mcs32; 1793 1794 pi->txpwr_limit[WL_TX_POWER_MCS40_CDD_FIRST] = 1795 min(pi->txpwr_limit[WL_TX_POWER_MCS40_CDD_FIRST], 1796 pi->txpwr_limit[WL_TX_POWER_MCS_32]); 1797 pi->txpwr_limit[WL_TX_POWER_MCS_32] = 1798 pi->txpwr_limit[WL_TX_POWER_MCS40_CDD_FIRST]; 1799 } 1800 } 1801 1802 void wlc_phy_txpwr_percent_set(struct brcms_phy_pub *ppi, u8 txpwr_percent) 1803 { 1804 struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro); 1805 1806 pi->txpwr_percent = txpwr_percent; 1807 } 1808 1809 void wlc_phy_machwcap_set(struct brcms_phy_pub *ppi, u32 machwcap) 1810 { 1811 struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro); 1812 1813 pi->sh->machwcap = machwcap; 1814 } 1815 1816 void wlc_phy_runbist_config(struct brcms_phy_pub *ppi, bool start_end) 1817 { 1818 struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro); 1819 u16 rxc; 1820 rxc = 0; 1821 1822 if (start_end == ON) { 1823 if (!ISNPHY(pi)) 1824 return; 1825 1826 if (NREV_IS(pi->pubpi.phy_rev, 3) 1827 || NREV_IS(pi->pubpi.phy_rev, 4)) { 1828 bcma_wflush16(pi->d11core, D11REGOFFS(phyregaddr), 1829 0xa0); 1830 bcma_set16(pi->d11core, D11REGOFFS(phyregdata), 1831 0x1 << 15); 1832 } 1833 } else { 1834 if (NREV_IS(pi->pubpi.phy_rev, 3) 1835 || NREV_IS(pi->pubpi.phy_rev, 4)) { 1836 bcma_wflush16(pi->d11core, D11REGOFFS(phyregaddr), 1837 0xa0); 1838 bcma_write16(pi->d11core, D11REGOFFS(phyregdata), rxc); 1839 } 1840 1841 wlc_phy_por_inform(ppi); 1842 } 1843 } 1844 1845 void 1846 wlc_phy_txpower_limit_set(struct brcms_phy_pub *ppi, struct txpwr_limits *txpwr, 1847 u16 chanspec) 1848 { 1849 struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro); 1850 1851 wlc_phy_txpower_reg_limit_calc(pi, txpwr, chanspec); 1852 1853 if (ISLCNPHY(pi)) { 1854 int i, j; 1855 for (i = TXP_FIRST_OFDM_20_CDD, j = 0; 1856 j < BRCMS_NUM_RATES_MCS_1_STREAM; i++, j++) { 1857 if (txpwr->mcs_20_siso[j]) 1858 pi->txpwr_limit[i] = txpwr->mcs_20_siso[j]; 1859 else 1860 pi->txpwr_limit[i] = txpwr->ofdm[j]; 1861 } 1862 } 1863 1864 wlapi_suspend_mac_and_wait(pi->sh->physhim); 1865 1866 wlc_phy_txpower_recalc_target(pi); 1867 wlc_phy_cal_txpower_recalc_sw(pi); 1868 wlapi_enable_mac(pi->sh->physhim); 1869 } 1870 1871 void wlc_phy_ofdm_rateset_war(struct brcms_phy_pub *pih, bool war) 1872 { 1873 struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro); 1874 1875 pi->ofdm_rateset_war = war; 1876 } 1877 1878 void wlc_phy_bf_preempt_enable(struct brcms_phy_pub *pih, bool bf_preempt) 1879 { 1880 struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro); 1881 1882 pi->bf_preempt_4306 = bf_preempt; 1883 } 1884 1885 void wlc_phy_txpower_update_shm(struct brcms_phy *pi) 1886 { 1887 int j; 1888 if (ISNPHY(pi)) 1889 return; 1890 1891 if (!pi->sh->clk) 1892 return; 1893 1894 if (pi->hwpwrctrl) { 1895 u16 offset; 1896 1897 wlapi_bmac_write_shm(pi->sh->physhim, M_TXPWR_MAX, 63); 1898 wlapi_bmac_write_shm(pi->sh->physhim, M_TXPWR_N, 1899 1 << NUM_TSSI_FRAMES); 1900 1901 wlapi_bmac_write_shm(pi->sh->physhim, M_TXPWR_TARGET, 1902 pi->tx_power_min << NUM_TSSI_FRAMES); 1903 1904 wlapi_bmac_write_shm(pi->sh->physhim, M_TXPWR_CUR, 1905 pi->hwpwr_txcur); 1906 1907 for (j = TXP_FIRST_OFDM; j <= TXP_LAST_OFDM; j++) { 1908 static const u8 ucode_ofdm_rates[] = { 1909 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c 1910 }; 1911 offset = wlapi_bmac_rate_shm_offset( 1912 pi->sh->physhim, 1913 ucode_ofdm_rates[j - TXP_FIRST_OFDM]); 1914 wlapi_bmac_write_shm(pi->sh->physhim, offset + 6, 1915 pi->tx_power_offset[j]); 1916 wlapi_bmac_write_shm(pi->sh->physhim, offset + 14, 1917 -(pi->tx_power_offset[j] / 2)); 1918 } 1919 1920 wlapi_bmac_mhf(pi->sh->physhim, MHF2, MHF2_HWPWRCTL, 1921 MHF2_HWPWRCTL, BRCM_BAND_ALL); 1922 } else { 1923 int i; 1924 1925 for (i = TXP_FIRST_OFDM; i <= TXP_LAST_OFDM; i++) 1926 pi->tx_power_offset[i] = 1927 (u8) roundup(pi->tx_power_offset[i], 8); 1928 wlapi_bmac_write_shm(pi->sh->physhim, M_OFDM_OFFSET, 1929 (u16) 1930 ((pi->tx_power_offset[TXP_FIRST_OFDM] 1931 + 7) >> 3)); 1932 } 1933 } 1934 1935 bool wlc_phy_txpower_hw_ctrl_get(struct brcms_phy_pub *ppi) 1936 { 1937 struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro); 1938 1939 if (ISNPHY(pi)) 1940 return pi->nphy_txpwrctrl; 1941 else 1942 return pi->hwpwrctrl; 1943 } 1944 1945 void wlc_phy_txpower_hw_ctrl_set(struct brcms_phy_pub *ppi, bool hwpwrctrl) 1946 { 1947 struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro); 1948 bool suspend; 1949 1950 if (!pi->hwpwrctrl_capable) 1951 return; 1952 1953 pi->hwpwrctrl = hwpwrctrl; 1954 pi->nphy_txpwrctrl = hwpwrctrl; 1955 pi->txpwrctrl = hwpwrctrl; 1956 1957 if (ISNPHY(pi)) { 1958 suspend = (0 == (bcma_read32(pi->d11core, 1959 D11REGOFFS(maccontrol)) & 1960 MCTL_EN_MAC)); 1961 if (!suspend) 1962 wlapi_suspend_mac_and_wait(pi->sh->physhim); 1963 1964 wlc_phy_txpwrctrl_enable_nphy(pi, pi->nphy_txpwrctrl); 1965 if (pi->nphy_txpwrctrl == PHY_TPC_HW_OFF) 1966 wlc_phy_txpwr_fixpower_nphy(pi); 1967 else 1968 mod_phy_reg(pi, 0x1e7, (0x7f << 0), 1969 pi->saved_txpwr_idx); 1970 1971 if (!suspend) 1972 wlapi_enable_mac(pi->sh->physhim); 1973 } 1974 } 1975 1976 void wlc_phy_txpower_ipa_upd(struct brcms_phy *pi) 1977 { 1978 1979 if (NREV_GE(pi->pubpi.phy_rev, 3)) { 1980 pi->ipa2g_on = (pi->srom_fem2g.extpagain == 2); 1981 pi->ipa5g_on = (pi->srom_fem5g.extpagain == 2); 1982 } else { 1983 pi->ipa2g_on = false; 1984 pi->ipa5g_on = false; 1985 } 1986 } 1987 1988 static u32 wlc_phy_txpower_est_power_nphy(struct brcms_phy *pi) 1989 { 1990 s16 tx0_status, tx1_status; 1991 u16 estPower1, estPower2; 1992 u8 pwr0, pwr1, adj_pwr0, adj_pwr1; 1993 u32 est_pwr; 1994 1995 estPower1 = read_phy_reg(pi, 0x118); 1996 estPower2 = read_phy_reg(pi, 0x119); 1997 1998 if ((estPower1 & (0x1 << 8)) == (0x1 << 8)) 1999 pwr0 = (u8) (estPower1 & (0xff << 0)) >> 0; 2000 else 2001 pwr0 = 0x80; 2002 2003 if ((estPower2 & (0x1 << 8)) == (0x1 << 8)) 2004 pwr1 = (u8) (estPower2 & (0xff << 0)) >> 0; 2005 else 2006 pwr1 = 0x80; 2007 2008 tx0_status = read_phy_reg(pi, 0x1ed); 2009 tx1_status = read_phy_reg(pi, 0x1ee); 2010 2011 if ((tx0_status & (0x1 << 15)) == (0x1 << 15)) 2012 adj_pwr0 = (u8) (tx0_status & (0xff << 0)) >> 0; 2013 else 2014 adj_pwr0 = 0x80; 2015 if ((tx1_status & (0x1 << 15)) == (0x1 << 15)) 2016 adj_pwr1 = (u8) (tx1_status & (0xff << 0)) >> 0; 2017 else 2018 adj_pwr1 = 0x80; 2019 2020 est_pwr = (u32) ((pwr0 << 24) | (pwr1 << 16) | (adj_pwr0 << 8) | 2021 adj_pwr1); 2022 2023 return est_pwr; 2024 } 2025 2026 void 2027 wlc_phy_txpower_get_current(struct brcms_phy_pub *ppi, struct tx_power *power, 2028 uint channel) 2029 { 2030 struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro); 2031 uint rate, num_rates; 2032 u8 min_pwr, max_pwr; 2033 2034 #if WL_TX_POWER_RATES != TXP_NUM_RATES 2035 #error "struct tx_power out of sync with this fn" 2036 #endif 2037 2038 if (ISNPHY(pi)) { 2039 power->rf_cores = 2; 2040 power->flags |= (WL_TX_POWER_F_MIMO); 2041 if (pi->nphy_txpwrctrl == PHY_TPC_HW_ON) 2042 power->flags |= 2043 (WL_TX_POWER_F_ENABLED | WL_TX_POWER_F_HW); 2044 } else if (ISLCNPHY(pi)) { 2045 power->rf_cores = 1; 2046 power->flags |= (WL_TX_POWER_F_SISO); 2047 if (pi->radiopwr_override == RADIOPWR_OVERRIDE_DEF) 2048 power->flags |= WL_TX_POWER_F_ENABLED; 2049 if (pi->hwpwrctrl) 2050 power->flags |= WL_TX_POWER_F_HW; 2051 } 2052 2053 num_rates = ((ISNPHY(pi)) ? (TXP_NUM_RATES) : 2054 ((ISLCNPHY(pi)) ? 2055 (TXP_LAST_OFDM_20_CDD + 1) : (TXP_LAST_OFDM + 1))); 2056 2057 for (rate = 0; rate < num_rates; rate++) { 2058 power->user_limit[rate] = pi->tx_user_target[rate]; 2059 wlc_phy_txpower_sromlimit(ppi, channel, &min_pwr, &max_pwr, 2060 rate); 2061 power->board_limit[rate] = (u8) max_pwr; 2062 power->target[rate] = pi->tx_power_target[rate]; 2063 } 2064 2065 if (ISNPHY(pi)) { 2066 u32 est_pout; 2067 2068 wlapi_suspend_mac_and_wait(pi->sh->physhim); 2069 wlc_phyreg_enter((struct brcms_phy_pub *) pi); 2070 est_pout = wlc_phy_txpower_est_power_nphy(pi); 2071 wlc_phyreg_exit((struct brcms_phy_pub *) pi); 2072 wlapi_enable_mac(pi->sh->physhim); 2073 2074 power->est_Pout[0] = (est_pout >> 8) & 0xff; 2075 power->est_Pout[1] = est_pout & 0xff; 2076 2077 power->est_Pout_act[0] = est_pout >> 24; 2078 power->est_Pout_act[1] = (est_pout >> 16) & 0xff; 2079 2080 if (power->est_Pout[0] == 0x80) 2081 power->est_Pout[0] = 0; 2082 if (power->est_Pout[1] == 0x80) 2083 power->est_Pout[1] = 0; 2084 2085 if (power->est_Pout_act[0] == 0x80) 2086 power->est_Pout_act[0] = 0; 2087 if (power->est_Pout_act[1] == 0x80) 2088 power->est_Pout_act[1] = 0; 2089 2090 power->est_Pout_cck = 0; 2091 2092 power->tx_power_max[0] = pi->tx_power_max; 2093 power->tx_power_max[1] = pi->tx_power_max; 2094 2095 power->tx_power_max_rate_ind[0] = pi->tx_power_max_rate_ind; 2096 power->tx_power_max_rate_ind[1] = pi->tx_power_max_rate_ind; 2097 } else if (pi->hwpwrctrl && pi->sh->up) { 2098 2099 wlc_phyreg_enter(ppi); 2100 if (ISLCNPHY(pi)) { 2101 2102 power->tx_power_max[0] = pi->tx_power_max; 2103 power->tx_power_max[1] = pi->tx_power_max; 2104 2105 power->tx_power_max_rate_ind[0] = 2106 pi->tx_power_max_rate_ind; 2107 power->tx_power_max_rate_ind[1] = 2108 pi->tx_power_max_rate_ind; 2109 2110 if (wlc_phy_tpc_isenabled_lcnphy(pi)) 2111 power->flags |= 2112 (WL_TX_POWER_F_HW | 2113 WL_TX_POWER_F_ENABLED); 2114 else 2115 power->flags &= 2116 ~(WL_TX_POWER_F_HW | 2117 WL_TX_POWER_F_ENABLED); 2118 2119 wlc_lcnphy_get_tssi(pi, (s8 *) &power->est_Pout[0], 2120 (s8 *) &power->est_Pout_cck); 2121 } 2122 wlc_phyreg_exit(ppi); 2123 } 2124 } 2125 2126 void wlc_phy_antsel_type_set(struct brcms_phy_pub *ppi, u8 antsel_type) 2127 { 2128 struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro); 2129 2130 pi->antsel_type = antsel_type; 2131 } 2132 2133 bool wlc_phy_test_ison(struct brcms_phy_pub *ppi) 2134 { 2135 struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro); 2136 2137 return pi->phytest_on; 2138 } 2139 2140 void wlc_phy_ant_rxdiv_set(struct brcms_phy_pub *ppi, u8 val) 2141 { 2142 struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro); 2143 bool suspend; 2144 2145 pi->sh->rx_antdiv = val; 2146 2147 if (!(ISNPHY(pi) && D11REV_IS(pi->sh->corerev, 16))) { 2148 if (val > ANT_RX_DIV_FORCE_1) 2149 wlapi_bmac_mhf(pi->sh->physhim, MHF1, MHF1_ANTDIV, 2150 MHF1_ANTDIV, BRCM_BAND_ALL); 2151 else 2152 wlapi_bmac_mhf(pi->sh->physhim, MHF1, MHF1_ANTDIV, 0, 2153 BRCM_BAND_ALL); 2154 } 2155 2156 if (ISNPHY(pi)) 2157 return; 2158 2159 if (!pi->sh->clk) 2160 return; 2161 2162 suspend = (0 == (bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) & 2163 MCTL_EN_MAC)); 2164 if (!suspend) 2165 wlapi_suspend_mac_and_wait(pi->sh->physhim); 2166 2167 if (ISLCNPHY(pi)) { 2168 if (val > ANT_RX_DIV_FORCE_1) { 2169 mod_phy_reg(pi, 0x410, (0x1 << 1), 0x01 << 1); 2170 mod_phy_reg(pi, 0x410, 2171 (0x1 << 0), 2172 ((ANT_RX_DIV_START_1 == val) ? 1 : 0) << 0); 2173 } else { 2174 mod_phy_reg(pi, 0x410, (0x1 << 1), 0x00 << 1); 2175 mod_phy_reg(pi, 0x410, (0x1 << 0), (u16) val << 0); 2176 } 2177 } 2178 2179 if (!suspend) 2180 wlapi_enable_mac(pi->sh->physhim); 2181 2182 return; 2183 } 2184 2185 static bool 2186 wlc_phy_noise_calc_phy(struct brcms_phy *pi, u32 *cmplx_pwr, s8 *pwr_ant) 2187 { 2188 s8 cmplx_pwr_dbm[PHY_CORE_MAX]; 2189 u8 i; 2190 2191 memset((u8 *) cmplx_pwr_dbm, 0, sizeof(cmplx_pwr_dbm)); 2192 wlc_phy_compute_dB(cmplx_pwr, cmplx_pwr_dbm, pi->pubpi.phy_corenum); 2193 2194 for (i = 0; i < pi->pubpi.phy_corenum; i++) { 2195 if (NREV_GE(pi->pubpi.phy_rev, 3)) 2196 cmplx_pwr_dbm[i] += (s8) PHY_NOISE_OFFSETFACT_4322; 2197 else 2198 2199 cmplx_pwr_dbm[i] += (s8) (16 - (15) * 3 - 70); 2200 } 2201 2202 for (i = 0; i < pi->pubpi.phy_corenum; i++) { 2203 pi->nphy_noise_win[i][pi->nphy_noise_index] = cmplx_pwr_dbm[i]; 2204 pwr_ant[i] = cmplx_pwr_dbm[i]; 2205 } 2206 pi->nphy_noise_index = 2207 MODINC_POW2(pi->nphy_noise_index, PHY_NOISE_WINDOW_SZ); 2208 return true; 2209 } 2210 2211 static void wlc_phy_noise_cb(struct brcms_phy *pi, u8 channel, s8 noise_dbm) 2212 { 2213 if (!pi->phynoise_state) 2214 return; 2215 2216 if (pi->phynoise_state & PHY_NOISE_STATE_MON) { 2217 if (pi->phynoise_chan_watchdog == channel) { 2218 pi->sh->phy_noise_window[pi->sh->phy_noise_index] = 2219 noise_dbm; 2220 pi->sh->phy_noise_index = 2221 MODINC(pi->sh->phy_noise_index, MA_WINDOW_SZ); 2222 } 2223 pi->phynoise_state &= ~PHY_NOISE_STATE_MON; 2224 } 2225 2226 if (pi->phynoise_state & PHY_NOISE_STATE_EXTERNAL) 2227 pi->phynoise_state &= ~PHY_NOISE_STATE_EXTERNAL; 2228 2229 } 2230 2231 static s8 wlc_phy_noise_read_shmem(struct brcms_phy *pi) 2232 { 2233 u32 cmplx_pwr[PHY_CORE_MAX]; 2234 s8 noise_dbm_ant[PHY_CORE_MAX]; 2235 u16 lo, hi; 2236 u32 cmplx_pwr_tot = 0; 2237 s8 noise_dbm = PHY_NOISE_FIXED_VAL_NPHY; 2238 u8 idx, core; 2239 2240 memset((u8 *) cmplx_pwr, 0, sizeof(cmplx_pwr)); 2241 memset((u8 *) noise_dbm_ant, 0, sizeof(noise_dbm_ant)); 2242 2243 for (idx = 0, core = 0; core < pi->pubpi.phy_corenum; idx += 2, 2244 core++) { 2245 lo = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP(idx)); 2246 hi = wlapi_bmac_read_shm(pi->sh->physhim, 2247 M_PWRIND_MAP(idx + 1)); 2248 cmplx_pwr[core] = (hi << 16) + lo; 2249 cmplx_pwr_tot += cmplx_pwr[core]; 2250 if (cmplx_pwr[core] == 0) 2251 noise_dbm_ant[core] = PHY_NOISE_FIXED_VAL_NPHY; 2252 else 2253 cmplx_pwr[core] >>= PHY_NOISE_SAMPLE_LOG_NUM_UCODE; 2254 } 2255 2256 if (cmplx_pwr_tot != 0) 2257 wlc_phy_noise_calc_phy(pi, cmplx_pwr, noise_dbm_ant); 2258 2259 for (core = 0; core < pi->pubpi.phy_corenum; core++) { 2260 pi->nphy_noise_win[core][pi->nphy_noise_index] = 2261 noise_dbm_ant[core]; 2262 2263 if (noise_dbm_ant[core] > noise_dbm) 2264 noise_dbm = noise_dbm_ant[core]; 2265 } 2266 pi->nphy_noise_index = 2267 MODINC_POW2(pi->nphy_noise_index, PHY_NOISE_WINDOW_SZ); 2268 2269 return noise_dbm; 2270 2271 } 2272 2273 void wlc_phy_noise_sample_intr(struct brcms_phy_pub *pih) 2274 { 2275 struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro); 2276 u16 jssi_aux; 2277 u8 channel = 0; 2278 s8 noise_dbm = PHY_NOISE_FIXED_VAL_NPHY; 2279 2280 if (ISLCNPHY(pi)) { 2281 u32 cmplx_pwr, cmplx_pwr0, cmplx_pwr1; 2282 u16 lo, hi; 2283 s32 pwr_offset_dB, gain_dB; 2284 u16 status_0, status_1; 2285 2286 jssi_aux = wlapi_bmac_read_shm(pi->sh->physhim, M_JSSI_AUX); 2287 channel = jssi_aux & D11_CURCHANNEL_MAX; 2288 2289 lo = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP0); 2290 hi = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP1); 2291 cmplx_pwr0 = (hi << 16) + lo; 2292 2293 lo = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP2); 2294 hi = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP3); 2295 cmplx_pwr1 = (hi << 16) + lo; 2296 cmplx_pwr = (cmplx_pwr0 + cmplx_pwr1) >> 6; 2297 2298 status_0 = 0x44; 2299 status_1 = wlapi_bmac_read_shm(pi->sh->physhim, M_JSSI_0); 2300 if ((cmplx_pwr > 0 && cmplx_pwr < 500) 2301 && ((status_1 & 0xc000) == 0x4000)) { 2302 2303 wlc_phy_compute_dB(&cmplx_pwr, &noise_dbm, 2304 pi->pubpi.phy_corenum); 2305 pwr_offset_dB = (read_phy_reg(pi, 0x434) & 0xFF); 2306 if (pwr_offset_dB > 127) 2307 pwr_offset_dB -= 256; 2308 2309 noise_dbm += (s8) (pwr_offset_dB - 30); 2310 2311 gain_dB = (status_0 & 0x1ff); 2312 noise_dbm -= (s8) (gain_dB); 2313 } else { 2314 noise_dbm = PHY_NOISE_FIXED_VAL_LCNPHY; 2315 } 2316 } else if (ISNPHY(pi)) { 2317 2318 jssi_aux = wlapi_bmac_read_shm(pi->sh->physhim, M_JSSI_AUX); 2319 channel = jssi_aux & D11_CURCHANNEL_MAX; 2320 2321 noise_dbm = wlc_phy_noise_read_shmem(pi); 2322 } 2323 2324 wlc_phy_noise_cb(pi, channel, noise_dbm); 2325 2326 } 2327 2328 static void 2329 wlc_phy_noise_sample_request(struct brcms_phy_pub *pih, u8 reason, u8 ch) 2330 { 2331 struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro); 2332 s8 noise_dbm = PHY_NOISE_FIXED_VAL_NPHY; 2333 bool sampling_in_progress = (pi->phynoise_state != 0); 2334 bool wait_for_intr = true; 2335 2336 switch (reason) { 2337 case PHY_NOISE_SAMPLE_MON: 2338 pi->phynoise_chan_watchdog = ch; 2339 pi->phynoise_state |= PHY_NOISE_STATE_MON; 2340 break; 2341 2342 case PHY_NOISE_SAMPLE_EXTERNAL: 2343 pi->phynoise_state |= PHY_NOISE_STATE_EXTERNAL; 2344 break; 2345 2346 default: 2347 break; 2348 } 2349 2350 if (sampling_in_progress) 2351 return; 2352 2353 pi->phynoise_now = pi->sh->now; 2354 2355 if (pi->phy_fixed_noise) { 2356 if (ISNPHY(pi)) { 2357 pi->nphy_noise_win[WL_ANT_IDX_1][pi->nphy_noise_index] = 2358 PHY_NOISE_FIXED_VAL_NPHY; 2359 pi->nphy_noise_win[WL_ANT_IDX_2][pi->nphy_noise_index] = 2360 PHY_NOISE_FIXED_VAL_NPHY; 2361 pi->nphy_noise_index = MODINC_POW2(pi->nphy_noise_index, 2362 PHY_NOISE_WINDOW_SZ); 2363 noise_dbm = PHY_NOISE_FIXED_VAL_NPHY; 2364 } else { 2365 noise_dbm = PHY_NOISE_FIXED_VAL; 2366 } 2367 2368 wait_for_intr = false; 2369 goto done; 2370 } 2371 2372 if (ISLCNPHY(pi)) { 2373 if (!pi->phynoise_polling 2374 || (reason == PHY_NOISE_SAMPLE_EXTERNAL)) { 2375 wlapi_bmac_write_shm(pi->sh->physhim, M_JSSI_0, 0); 2376 wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP0, 0); 2377 wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP1, 0); 2378 wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP2, 0); 2379 wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP3, 0); 2380 2381 bcma_set32(pi->d11core, D11REGOFFS(maccommand), 2382 MCMD_BG_NOISE); 2383 } else { 2384 wlapi_suspend_mac_and_wait(pi->sh->physhim); 2385 wlc_lcnphy_deaf_mode(pi, (bool) 0); 2386 noise_dbm = (s8) wlc_lcnphy_rx_signal_power(pi, 20); 2387 wlc_lcnphy_deaf_mode(pi, (bool) 1); 2388 wlapi_enable_mac(pi->sh->physhim); 2389 wait_for_intr = false; 2390 } 2391 } else if (ISNPHY(pi)) { 2392 if (!pi->phynoise_polling 2393 || (reason == PHY_NOISE_SAMPLE_EXTERNAL)) { 2394 2395 wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP0, 0); 2396 wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP1, 0); 2397 wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP2, 0); 2398 wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP3, 0); 2399 2400 bcma_set32(pi->d11core, D11REGOFFS(maccommand), 2401 MCMD_BG_NOISE); 2402 } else { 2403 struct phy_iq_est est[PHY_CORE_MAX]; 2404 u32 cmplx_pwr[PHY_CORE_MAX]; 2405 s8 noise_dbm_ant[PHY_CORE_MAX]; 2406 u16 log_num_samps, num_samps, classif_state = 0; 2407 u8 wait_time = 32; 2408 u8 wait_crs = 0; 2409 u8 i; 2410 2411 memset((u8 *) est, 0, sizeof(est)); 2412 memset((u8 *) cmplx_pwr, 0, sizeof(cmplx_pwr)); 2413 memset((u8 *) noise_dbm_ant, 0, sizeof(noise_dbm_ant)); 2414 2415 log_num_samps = PHY_NOISE_SAMPLE_LOG_NUM_NPHY; 2416 num_samps = 1 << log_num_samps; 2417 2418 wlapi_suspend_mac_and_wait(pi->sh->physhim); 2419 classif_state = wlc_phy_classifier_nphy(pi, 0, 0); 2420 wlc_phy_classifier_nphy(pi, 3, 0); 2421 wlc_phy_rx_iq_est_nphy(pi, est, num_samps, wait_time, 2422 wait_crs); 2423 wlc_phy_classifier_nphy(pi, (0x7 << 0), classif_state); 2424 wlapi_enable_mac(pi->sh->physhim); 2425 2426 for (i = 0; i < pi->pubpi.phy_corenum; i++) 2427 cmplx_pwr[i] = (est[i].i_pwr + est[i].q_pwr) >> 2428 log_num_samps; 2429 2430 wlc_phy_noise_calc_phy(pi, cmplx_pwr, noise_dbm_ant); 2431 2432 for (i = 0; i < pi->pubpi.phy_corenum; i++) { 2433 pi->nphy_noise_win[i][pi->nphy_noise_index] = 2434 noise_dbm_ant[i]; 2435 2436 if (noise_dbm_ant[i] > noise_dbm) 2437 noise_dbm = noise_dbm_ant[i]; 2438 } 2439 pi->nphy_noise_index = MODINC_POW2(pi->nphy_noise_index, 2440 PHY_NOISE_WINDOW_SZ); 2441 2442 wait_for_intr = false; 2443 } 2444 } 2445 2446 done: 2447 2448 if (!wait_for_intr) 2449 wlc_phy_noise_cb(pi, ch, noise_dbm); 2450 2451 } 2452 2453 void wlc_phy_noise_sample_request_external(struct brcms_phy_pub *pih) 2454 { 2455 u8 channel; 2456 2457 channel = CHSPEC_CHANNEL(wlc_phy_chanspec_get(pih)); 2458 2459 wlc_phy_noise_sample_request(pih, PHY_NOISE_SAMPLE_EXTERNAL, channel); 2460 } 2461 2462 static const s8 lcnphy_gain_index_offset_for_pkt_rssi[] = { 2463 8, 2464 8, 2465 8, 2466 8, 2467 8, 2468 8, 2469 8, 2470 9, 2471 10, 2472 8, 2473 8, 2474 7, 2475 7, 2476 1, 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 2, 2495 1, 2496 1, 2497 0, 2498 0, 2499 0, 2500 0 2501 }; 2502 2503 void wlc_phy_compute_dB(u32 *cmplx_pwr, s8 *p_cmplx_pwr_dB, u8 core) 2504 { 2505 u8 msb, secondmsb, i; 2506 u32 tmp; 2507 2508 for (i = 0; i < core; i++) { 2509 secondmsb = 0; 2510 tmp = cmplx_pwr[i]; 2511 msb = fls(tmp); 2512 if (msb) 2513 secondmsb = (u8) ((tmp >> (--msb - 1)) & 1); 2514 p_cmplx_pwr_dB[i] = (s8) (3 * msb + 2 * secondmsb); 2515 } 2516 } 2517 2518 int wlc_phy_rssi_compute(struct brcms_phy_pub *pih, 2519 struct d11rxhdr *rxh) 2520 { 2521 int rssi = rxh->PhyRxStatus_1 & PRXS1_JSSI_MASK; 2522 uint radioid = pih->radioid; 2523 struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro); 2524 2525 if ((pi->sh->corerev >= 11) 2526 && !(rxh->RxStatus2 & RXS_PHYRXST_VALID)) { 2527 rssi = BRCMS_RSSI_INVALID; 2528 goto end; 2529 } 2530 2531 if (ISLCNPHY(pi)) { 2532 u8 gidx = (rxh->PhyRxStatus_2 & 0xFC00) >> 10; 2533 struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; 2534 2535 if (rssi > 127) 2536 rssi -= 256; 2537 2538 rssi = rssi + lcnphy_gain_index_offset_for_pkt_rssi[gidx]; 2539 if ((rssi > -46) && (gidx > 18)) 2540 rssi = rssi + 7; 2541 2542 rssi = rssi + pi_lcn->lcnphy_pkteng_rssi_slope; 2543 2544 rssi = rssi + 2; 2545 2546 } 2547 2548 if (ISLCNPHY(pi)) { 2549 if (rssi > 127) 2550 rssi -= 256; 2551 } else if (radioid == BCM2055_ID || radioid == BCM2056_ID 2552 || radioid == BCM2057_ID) { 2553 rssi = wlc_phy_rssi_compute_nphy(pi, rxh); 2554 } 2555 2556 end: 2557 return rssi; 2558 } 2559 2560 void wlc_phy_freqtrack_start(struct brcms_phy_pub *pih) 2561 { 2562 return; 2563 } 2564 2565 void wlc_phy_freqtrack_end(struct brcms_phy_pub *pih) 2566 { 2567 return; 2568 } 2569 2570 void wlc_phy_set_deaf(struct brcms_phy_pub *ppi, bool user_flag) 2571 { 2572 struct brcms_phy *pi; 2573 pi = (struct brcms_phy *) ppi; 2574 2575 if (ISLCNPHY(pi)) 2576 wlc_lcnphy_deaf_mode(pi, true); 2577 else if (ISNPHY(pi)) 2578 wlc_nphy_deaf_mode(pi, true); 2579 } 2580 2581 void wlc_phy_watchdog(struct brcms_phy_pub *pih) 2582 { 2583 struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro); 2584 bool delay_phy_cal = false; 2585 pi->sh->now++; 2586 2587 if (!pi->watchdog_override) 2588 return; 2589 2590 if (!(SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi))) 2591 wlc_phy_noise_sample_request((struct brcms_phy_pub *) pi, 2592 PHY_NOISE_SAMPLE_MON, 2593 CHSPEC_CHANNEL(pi-> 2594 radio_chanspec)); 2595 2596 if (pi->phynoise_state && (pi->sh->now - pi->phynoise_now) > 5) 2597 pi->phynoise_state = 0; 2598 2599 if ((!pi->phycal_txpower) || 2600 ((pi->sh->now - pi->phycal_txpower) >= pi->sh->fast_timer)) { 2601 2602 if (!SCAN_INPROG_PHY(pi) && wlc_phy_cal_txpower_recalc_sw(pi)) 2603 pi->phycal_txpower = pi->sh->now; 2604 } 2605 2606 if ((SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi) 2607 || ASSOC_INPROG_PHY(pi))) 2608 return; 2609 2610 if (ISNPHY(pi) && !pi->disable_percal && !delay_phy_cal) { 2611 2612 if ((pi->nphy_perical != PHY_PERICAL_DISABLE) && 2613 (pi->nphy_perical != PHY_PERICAL_MANUAL) && 2614 ((pi->sh->now - pi->nphy_perical_last) >= 2615 pi->sh->glacial_timer)) 2616 wlc_phy_cal_perical((struct brcms_phy_pub *) pi, 2617 PHY_PERICAL_WATCHDOG); 2618 2619 wlc_phy_txpwr_papd_cal_nphy(pi); 2620 } 2621 2622 if (ISLCNPHY(pi)) { 2623 if (pi->phy_forcecal || 2624 ((pi->sh->now - pi->phy_lastcal) >= 2625 pi->sh->glacial_timer)) { 2626 if (!(SCAN_RM_IN_PROGRESS(pi) || ASSOC_INPROG_PHY(pi))) 2627 wlc_lcnphy_calib_modes( 2628 pi, 2629 LCNPHY_PERICAL_TEMPBASED_TXPWRCTRL); 2630 if (! 2631 (SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi) 2632 || ASSOC_INPROG_PHY(pi) 2633 || pi->carrier_suppr_disable 2634 || pi->disable_percal)) 2635 wlc_lcnphy_calib_modes(pi, 2636 PHY_PERICAL_WATCHDOG); 2637 } 2638 } 2639 } 2640 2641 void wlc_phy_BSSinit(struct brcms_phy_pub *pih, bool bonlyap, int rssi) 2642 { 2643 struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro); 2644 uint i; 2645 uint k; 2646 2647 for (i = 0; i < MA_WINDOW_SZ; i++) 2648 pi->sh->phy_noise_window[i] = (s8) (rssi & 0xff); 2649 if (ISLCNPHY(pi)) { 2650 for (i = 0; i < MA_WINDOW_SZ; i++) 2651 pi->sh->phy_noise_window[i] = 2652 PHY_NOISE_FIXED_VAL_LCNPHY; 2653 } 2654 pi->sh->phy_noise_index = 0; 2655 2656 for (i = 0; i < PHY_NOISE_WINDOW_SZ; i++) { 2657 for (k = WL_ANT_IDX_1; k < WL_ANT_RX_MAX; k++) 2658 pi->nphy_noise_win[k][i] = PHY_NOISE_FIXED_VAL_NPHY; 2659 } 2660 pi->nphy_noise_index = 0; 2661 } 2662 2663 void 2664 wlc_phy_papd_decode_epsilon(u32 epsilon, s32 *eps_real, s32 *eps_imag) 2665 { 2666 *eps_imag = (epsilon >> 13); 2667 if (*eps_imag > 0xfff) 2668 *eps_imag -= 0x2000; 2669 2670 *eps_real = (epsilon & 0x1fff); 2671 if (*eps_real > 0xfff) 2672 *eps_real -= 0x2000; 2673 } 2674 2675 void wlc_phy_cal_perical_mphase_reset(struct brcms_phy *pi) 2676 { 2677 wlapi_del_timer(pi->phycal_timer); 2678 2679 pi->cal_type_override = PHY_PERICAL_AUTO; 2680 pi->mphase_cal_phase_id = MPHASE_CAL_STATE_IDLE; 2681 pi->mphase_txcal_cmdidx = 0; 2682 } 2683 2684 static void 2685 wlc_phy_cal_perical_mphase_schedule(struct brcms_phy *pi, uint delay) 2686 { 2687 2688 if ((pi->nphy_perical != PHY_PERICAL_MPHASE) && 2689 (pi->nphy_perical != PHY_PERICAL_MANUAL)) 2690 return; 2691 2692 wlapi_del_timer(pi->phycal_timer); 2693 2694 pi->mphase_cal_phase_id = MPHASE_CAL_STATE_INIT; 2695 wlapi_add_timer(pi->phycal_timer, delay, 0); 2696 } 2697 2698 void wlc_phy_cal_perical(struct brcms_phy_pub *pih, u8 reason) 2699 { 2700 s16 nphy_currtemp = 0; 2701 s16 delta_temp = 0; 2702 bool do_periodic_cal = true; 2703 struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro); 2704 2705 if (!ISNPHY(pi)) 2706 return; 2707 2708 if ((pi->nphy_perical == PHY_PERICAL_DISABLE) || 2709 (pi->nphy_perical == PHY_PERICAL_MANUAL)) 2710 return; 2711 2712 switch (reason) { 2713 case PHY_PERICAL_DRIVERUP: 2714 break; 2715 2716 case PHY_PERICAL_PHYINIT: 2717 if (pi->nphy_perical == PHY_PERICAL_MPHASE) { 2718 if (PHY_PERICAL_MPHASE_PENDING(pi)) 2719 wlc_phy_cal_perical_mphase_reset(pi); 2720 2721 wlc_phy_cal_perical_mphase_schedule( 2722 pi, 2723 PHY_PERICAL_INIT_DELAY); 2724 } 2725 break; 2726 2727 case PHY_PERICAL_JOIN_BSS: 2728 case PHY_PERICAL_START_IBSS: 2729 case PHY_PERICAL_UP_BSS: 2730 if ((pi->nphy_perical == PHY_PERICAL_MPHASE) && 2731 PHY_PERICAL_MPHASE_PENDING(pi)) 2732 wlc_phy_cal_perical_mphase_reset(pi); 2733 2734 pi->first_cal_after_assoc = true; 2735 2736 pi->cal_type_override = PHY_PERICAL_FULL; 2737 2738 if (pi->phycal_tempdelta) 2739 pi->nphy_lastcal_temp = wlc_phy_tempsense_nphy(pi); 2740 2741 wlc_phy_cal_perical_nphy_run(pi, PHY_PERICAL_FULL); 2742 break; 2743 2744 case PHY_PERICAL_WATCHDOG: 2745 if (pi->phycal_tempdelta) { 2746 nphy_currtemp = wlc_phy_tempsense_nphy(pi); 2747 delta_temp = 2748 (nphy_currtemp > pi->nphy_lastcal_temp) ? 2749 nphy_currtemp - pi->nphy_lastcal_temp : 2750 pi->nphy_lastcal_temp - nphy_currtemp; 2751 2752 if ((delta_temp < (s16) pi->phycal_tempdelta) && 2753 (pi->nphy_txiqlocal_chanspec == 2754 pi->radio_chanspec)) 2755 do_periodic_cal = false; 2756 else 2757 pi->nphy_lastcal_temp = nphy_currtemp; 2758 } 2759 2760 if (do_periodic_cal) { 2761 if (pi->nphy_perical == PHY_PERICAL_MPHASE) { 2762 if (!PHY_PERICAL_MPHASE_PENDING(pi)) 2763 wlc_phy_cal_perical_mphase_schedule( 2764 pi, 2765 PHY_PERICAL_WDOG_DELAY); 2766 } else if (pi->nphy_perical == PHY_PERICAL_SPHASE) 2767 wlc_phy_cal_perical_nphy_run(pi, 2768 PHY_PERICAL_AUTO); 2769 } 2770 break; 2771 default: 2772 break; 2773 } 2774 } 2775 2776 void wlc_phy_cal_perical_mphase_restart(struct brcms_phy *pi) 2777 { 2778 pi->mphase_cal_phase_id = MPHASE_CAL_STATE_INIT; 2779 pi->mphase_txcal_cmdidx = 0; 2780 } 2781 2782 u8 wlc_phy_nbits(s32 value) 2783 { 2784 s32 abs_val; 2785 u8 nbits = 0; 2786 2787 abs_val = abs(value); 2788 while ((abs_val >> nbits) > 0) 2789 nbits++; 2790 2791 return nbits; 2792 } 2793 2794 void wlc_phy_stf_chain_init(struct brcms_phy_pub *pih, u8 txchain, u8 rxchain) 2795 { 2796 struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro); 2797 2798 pi->sh->hw_phytxchain = txchain; 2799 pi->sh->hw_phyrxchain = rxchain; 2800 pi->sh->phytxchain = txchain; 2801 pi->sh->phyrxchain = rxchain; 2802 pi->pubpi.phy_corenum = (u8)hweight8(pi->sh->phyrxchain); 2803 } 2804 2805 void wlc_phy_stf_chain_set(struct brcms_phy_pub *pih, u8 txchain, u8 rxchain) 2806 { 2807 struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro); 2808 2809 pi->sh->phytxchain = txchain; 2810 2811 if (ISNPHY(pi)) 2812 wlc_phy_rxcore_setstate_nphy(pih, rxchain); 2813 2814 pi->pubpi.phy_corenum = (u8)hweight8(pi->sh->phyrxchain); 2815 } 2816 2817 void wlc_phy_stf_chain_get(struct brcms_phy_pub *pih, u8 *txchain, u8 *rxchain) 2818 { 2819 struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro); 2820 2821 *txchain = pi->sh->phytxchain; 2822 *rxchain = pi->sh->phyrxchain; 2823 } 2824 2825 u8 wlc_phy_stf_chain_active_get(struct brcms_phy_pub *pih) 2826 { 2827 s16 nphy_currtemp; 2828 u8 active_bitmap; 2829 struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro); 2830 2831 active_bitmap = (pi->phy_txcore_heatedup) ? 0x31 : 0x33; 2832 2833 if (!pi->watchdog_override) 2834 return active_bitmap; 2835 2836 if (NREV_GE(pi->pubpi.phy_rev, 6)) { 2837 wlapi_suspend_mac_and_wait(pi->sh->physhim); 2838 nphy_currtemp = wlc_phy_tempsense_nphy(pi); 2839 wlapi_enable_mac(pi->sh->physhim); 2840 2841 if (!pi->phy_txcore_heatedup) { 2842 if (nphy_currtemp >= pi->phy_txcore_disable_temp) { 2843 active_bitmap &= 0xFD; 2844 pi->phy_txcore_heatedup = true; 2845 } 2846 } else { 2847 if (nphy_currtemp <= pi->phy_txcore_enable_temp) { 2848 active_bitmap |= 0x2; 2849 pi->phy_txcore_heatedup = false; 2850 } 2851 } 2852 } 2853 2854 return active_bitmap; 2855 } 2856 2857 s8 wlc_phy_stf_ssmode_get(struct brcms_phy_pub *pih, u16 chanspec) 2858 { 2859 struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro); 2860 u8 siso_mcs_id, cdd_mcs_id; 2861 2862 siso_mcs_id = 2863 (CHSPEC_IS40(chanspec)) ? TXP_FIRST_MCS_40_SISO : 2864 TXP_FIRST_MCS_20_SISO; 2865 cdd_mcs_id = 2866 (CHSPEC_IS40(chanspec)) ? TXP_FIRST_MCS_40_CDD : 2867 TXP_FIRST_MCS_20_CDD; 2868 2869 if (pi->tx_power_target[siso_mcs_id] > 2870 (pi->tx_power_target[cdd_mcs_id] + 12)) 2871 return PHY_TXC1_MODE_SISO; 2872 else 2873 return PHY_TXC1_MODE_CDD; 2874 } 2875 2876 const u8 *wlc_phy_get_ofdm_rate_lookup(void) 2877 { 2878 return ofdm_rate_lookup; 2879 } 2880 2881 void wlc_lcnphy_epa_switch(struct brcms_phy *pi, bool mode) 2882 { 2883 if ((pi->sh->chip == BCMA_CHIP_ID_BCM4313) && 2884 (pi->sh->boardflags & BFL_FEM)) { 2885 if (mode) { 2886 u16 txant = 0; 2887 txant = wlapi_bmac_get_txant(pi->sh->physhim); 2888 if (txant == 1) { 2889 mod_phy_reg(pi, 0x44d, (0x1 << 2), (1) << 2); 2890 2891 mod_phy_reg(pi, 0x44c, (0x1 << 2), (1) << 2); 2892 2893 } 2894 2895 bcma_chipco_gpio_control(&pi->d11core->bus->drv_cc, 2896 0x0, 0x0); 2897 bcma_chipco_gpio_out(&pi->d11core->bus->drv_cc, 2898 ~0x40, 0x40); 2899 bcma_chipco_gpio_outen(&pi->d11core->bus->drv_cc, 2900 ~0x40, 0x40); 2901 } else { 2902 mod_phy_reg(pi, 0x44c, (0x1 << 2), (0) << 2); 2903 2904 mod_phy_reg(pi, 0x44d, (0x1 << 2), (0) << 2); 2905 2906 bcma_chipco_gpio_out(&pi->d11core->bus->drv_cc, 2907 ~0x40, 0x00); 2908 bcma_chipco_gpio_outen(&pi->d11core->bus->drv_cc, 2909 ~0x40, 0x00); 2910 bcma_chipco_gpio_control(&pi->d11core->bus->drv_cc, 2911 0x0, 0x40); 2912 } 2913 } 2914 } 2915 2916 void wlc_phy_ldpc_override_set(struct brcms_phy_pub *ppi, bool ldpc) 2917 { 2918 return; 2919 } 2920 2921 void 2922 wlc_phy_get_pwrdet_offsets(struct brcms_phy *pi, s8 *cckoffset, s8 *ofdmoffset) 2923 { 2924 *cckoffset = 0; 2925 *ofdmoffset = 0; 2926 } 2927 2928 s8 wlc_phy_upd_rssi_offset(struct brcms_phy *pi, s8 rssi, u16 chanspec) 2929 { 2930 2931 return rssi; 2932 } 2933 2934 bool wlc_phy_txpower_ipa_ison(struct brcms_phy_pub *ppi) 2935 { 2936 struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro); 2937 2938 if (ISNPHY(pi)) 2939 return wlc_phy_n_txpower_ipa_ison(pi); 2940 else 2941 return false; 2942 } 2943