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