root/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_cmn.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. wlc_phyreg_enter
  2. wlc_phyreg_exit
  3. wlc_radioreg_enter
  4. wlc_radioreg_exit
  5. read_radio_reg
  6. write_radio_reg
  7. read_radio_id
  8. and_radio_reg
  9. or_radio_reg
  10. xor_radio_reg
  11. mod_radio_reg
  12. write_phy_channel_reg
  13. read_phy_reg
  14. write_phy_reg
  15. and_phy_reg
  16. or_phy_reg
  17. mod_phy_reg
  18. wlc_set_phy_uninitted
  19. wlc_phy_shared_attach
  20. wlc_phy_timercb_phycal
  21. wlc_phy_get_radio_ver
  22. wlc_phy_attach
  23. wlc_phy_detach
  24. wlc_phy_get_phyversion
  25. wlc_phy_get_encore
  26. wlc_phy_get_coreflags
  27. wlc_phy_anacore
  28. wlc_phy_clk_bwbits
  29. wlc_phy_por_inform
  30. wlc_phy_edcrs_lock
  31. wlc_phy_initcal_enable
  32. wlc_phy_hw_clk_state_upd
  33. wlc_phy_hw_state_upd
  34. wlc_phy_init
  35. wlc_phy_cal_init
  36. wlc_phy_down
  37. wlc_phy_table_addr
  38. wlc_phy_table_data_write
  39. wlc_phy_write_table
  40. wlc_phy_read_table
  41. wlc_phy_init_radio_regs_allbands
  42. wlc_phy_init_radio_regs
  43. wlc_phy_do_dummy_tx
  44. wlc_phy_hold_upd
  45. wlc_phy_mute_upd
  46. wlc_phy_clear_tssi
  47. wlc_phy_cal_txpower_recalc_sw
  48. wlc_phy_switch_radio
  49. wlc_phy_bw_state_get
  50. wlc_phy_bw_state_set
  51. wlc_phy_chanspec_radio_set
  52. wlc_phy_chanspec_get
  53. wlc_phy_chanspec_set
  54. wlc_phy_chanspec_freq2bandrange_lpssn
  55. wlc_phy_chanspec_bandrange_get
  56. wlc_phy_chanspec_ch14_widefilter_set
  57. wlc_phy_channel2freq
  58. wlc_phy_chanspec_band_validch
  59. wlc_phy_chanspec_band_firstch
  60. wlc_phy_txpower_get
  61. wlc_phy_txpower_target_set
  62. wlc_phy_txpower_set
  63. wlc_phy_txpower_sromlimit
  64. wlc_phy_txpower_sromlimit_max_get
  65. wlc_phy_txpower_boardlimit_band
  66. wlc_phy_txpower_get_target_min
  67. wlc_phy_txpower_get_target_max
  68. wlc_phy_env_measure_vbat
  69. wlc_phy_env_measure_temperature
  70. wlc_phy_upd_env_txpwr_rate_limits
  71. wlc_user_txpwr_antport_to_rfport
  72. wlc_phy_txpower_recalc_target
  73. wlc_phy_txpower_reg_limit_calc
  74. wlc_phy_txpwr_percent_set
  75. wlc_phy_machwcap_set
  76. wlc_phy_runbist_config
  77. wlc_phy_txpower_limit_set
  78. wlc_phy_ofdm_rateset_war
  79. wlc_phy_bf_preempt_enable
  80. wlc_phy_txpower_update_shm
  81. wlc_phy_txpower_hw_ctrl_get
  82. wlc_phy_txpower_hw_ctrl_set
  83. wlc_phy_txpower_ipa_upd
  84. wlc_phy_txpower_est_power_nphy
  85. wlc_phy_txpower_get_current
  86. wlc_phy_antsel_type_set
  87. wlc_phy_test_ison
  88. wlc_phy_ant_rxdiv_set
  89. wlc_phy_noise_calc_phy
  90. wlc_phy_noise_cb
  91. wlc_phy_noise_read_shmem
  92. wlc_phy_noise_sample_intr
  93. wlc_phy_noise_sample_request
  94. wlc_phy_noise_sample_request_external
  95. wlc_phy_compute_dB
  96. wlc_phy_rssi_compute
  97. wlc_phy_freqtrack_start
  98. wlc_phy_freqtrack_end
  99. wlc_phy_set_deaf
  100. wlc_phy_watchdog
  101. wlc_phy_BSSinit
  102. wlc_phy_papd_decode_epsilon
  103. wlc_phy_cal_perical_mphase_reset
  104. wlc_phy_cal_perical_mphase_schedule
  105. wlc_phy_cal_perical
  106. wlc_phy_cal_perical_mphase_restart
  107. wlc_phy_nbits
  108. wlc_phy_stf_chain_init
  109. wlc_phy_stf_chain_set
  110. wlc_phy_stf_chain_get
  111. wlc_phy_stf_chain_active_get
  112. wlc_phy_stf_ssmode_get
  113. wlc_phy_get_ofdm_rate_lookup
  114. wlc_lcnphy_epa_switch
  115. wlc_phy_ldpc_override_set
  116. wlc_phy_get_pwrdet_offsets
  117. wlc_phy_upd_rssi_offset
  118. wlc_phy_txpower_ipa_ison

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

/* [<][>][^][v][top][bottom][index][help] */