2 * Copyright (c) 2010 Broadcom Corporation
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
11 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
13 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 #include <linux/kernel.h>
17 #include <linux/delay.h>
19 #include <brcm_hw_ids.h>
20 #include <chipcommon.h>
26 #include "phy_radio.h"
30 #define VALID_N_RADIO(radioid) ((radioid == BCM2055_ID) || \
31 (radioid == BCM2056_ID) || \
32 (radioid == BCM2057_ID))
34 #define VALID_LCN_RADIO(radioid) (radioid == BCM2064_ID)
36 #define VALID_RADIO(pi, radioid) ( \
37 (ISNPHY(pi) ? VALID_N_RADIO(radioid) : false) || \
38 (ISLCNPHY(pi) ? VALID_LCN_RADIO(radioid) : false))
40 /* basic mux operation - can be optimized on several architectures */
41 #define MUX(pred, true, false) ((pred) ? (true) : (false))
43 /* modulo inc/dec - assumes x E [0, bound - 1] */
44 #define MODINC(x, bound) MUX((x) == (bound) - 1, 0, (x) + 1)
46 /* modulo inc/dec, bound = 2^k */
47 #define MODDEC_POW2(x, bound) (((x) - 1) & ((bound) - 1))
48 #define MODINC_POW2(x, bound) (((x) + 1) & ((bound) - 1))
50 struct chan_info_basic {
55 static struct chan_info_basic chan_info_all[] = {
114 u16 ltrn_list[PHY_LTRN_LIST_LEN] = {
115 0x18f9, 0x0d01, 0x00e4, 0xdef4, 0x06f1, 0x0ffc,
116 0xfa27, 0x1dff, 0x10f0, 0x0918, 0xf20a, 0xe010,
117 0x1417, 0x1104, 0xf114, 0xf2fa, 0xf7db, 0xe2fc,
118 0xe1fb, 0x13ee, 0xff0d, 0xe91c, 0x171a, 0x0318,
119 0xda00, 0x03e8, 0x17e6, 0xe9e4, 0xfff3, 0x1312,
120 0xe105, 0xe204, 0xf725, 0xf206, 0xf1ec, 0x11fc,
121 0x14e9, 0xe0f0, 0xf2f6, 0x09e8, 0x1010, 0x1d01,
122 0xfad9, 0x0f04, 0x060f, 0xde0c, 0x001c, 0x0dff,
123 0x1807, 0xf61a, 0xe40e, 0x0f16, 0x05f9, 0x18ec,
124 0x0a1b, 0xff1e, 0x2600, 0xffe2, 0x0ae5, 0x1814,
125 0x0507, 0x0fea, 0xe4f2, 0xf6e6
128 const u8 ofdm_rate_lookup[] = {
140 #define PHY_WREG_LIMIT 24
142 char *phy_getvar(struct brcms_phy *pi, const char *name)
144 char *vars = pi->vars;
155 for (s = vars; s && *s;) {
156 if ((memcmp(s, name, len) == 0) && (s[len] == '='))
166 int phy_getintvar(struct brcms_phy *pi, const char *name)
171 val = PHY_GETVAR(pi, name);
172 if (val && !kstrtoul(val, 0, &res))
178 void wlc_phyreg_enter(struct brcms_phy_pub *pih)
180 struct brcms_phy *pi = (struct brcms_phy *) pih;
181 wlapi_bmac_ucode_wake_override_phyreg_set(pi->sh->physhim);
184 void wlc_phyreg_exit(struct brcms_phy_pub *pih)
186 struct brcms_phy *pi = (struct brcms_phy *) pih;
187 wlapi_bmac_ucode_wake_override_phyreg_clear(pi->sh->physhim);
190 void wlc_radioreg_enter(struct brcms_phy_pub *pih)
192 struct brcms_phy *pi = (struct brcms_phy *) pih;
193 wlapi_bmac_mctrl(pi->sh->physhim, MCTL_LOCK_RADIO, MCTL_LOCK_RADIO);
198 void wlc_radioreg_exit(struct brcms_phy_pub *pih)
200 struct brcms_phy *pi = (struct brcms_phy *) pih;
203 dummy = R_REG(&pi->regs->phyversion);
205 wlapi_bmac_mctrl(pi->sh->physhim, MCTL_LOCK_RADIO, 0);
208 u16 read_radio_reg(struct brcms_phy *pi, u16 addr)
212 if ((addr == RADIO_IDCODE))
215 switch (pi->pubpi.phy_type) {
217 if (!CONF_HAS(PHYTYPE, PHY_TYPE_N))
219 if (NREV_GE(pi->pubpi.phy_rev, 7))
220 addr |= RADIO_2057_READ_OFF;
222 addr |= RADIO_2055_READ_OFF;
226 if (!CONF_HAS(PHYTYPE, PHY_TYPE_LCN))
228 addr |= RADIO_2064_READ_OFF;
235 if ((D11REV_GE(pi->sh->corerev, 24)) ||
236 (D11REV_IS(pi->sh->corerev, 22)
237 && (pi->pubpi.phy_type != PHY_TYPE_SSN))) {
238 W_REG_FLUSH(&pi->regs->radioregaddr, addr);
239 data = R_REG(&pi->regs->radioregdata);
241 W_REG_FLUSH(&pi->regs->phy4waddr, addr);
243 #ifdef __ARM_ARCH_4T__
244 __asm__(" .align 4 ");
246 data = R_REG(&pi->regs->phy4wdatalo);
248 data = R_REG(&pi->regs->phy4wdatalo);
257 void write_radio_reg(struct brcms_phy *pi, u16 addr, u16 val)
259 if ((D11REV_GE(pi->sh->corerev, 24)) ||
260 (D11REV_IS(pi->sh->corerev, 22)
261 && (pi->pubpi.phy_type != PHY_TYPE_SSN))) {
263 W_REG_FLUSH(&pi->regs->radioregaddr, addr);
264 W_REG(&pi->regs->radioregdata, val);
266 W_REG_FLUSH(&pi->regs->phy4waddr, addr);
267 W_REG(&pi->regs->phy4wdatalo, val);
270 if (++pi->phy_wreg >= pi->phy_wreg_limit) {
271 (void)R_REG(&pi->regs->maccontrol);
276 static u32 read_radio_id(struct brcms_phy *pi)
280 if (D11REV_GE(pi->sh->corerev, 24)) {
283 W_REG_FLUSH(&pi->regs->radioregaddr, 0);
284 b0 = (u32) R_REG(&pi->regs->radioregdata);
285 W_REG_FLUSH(&pi->regs->radioregaddr, 1);
286 b1 = (u32) R_REG(&pi->regs->radioregdata);
287 W_REG_FLUSH(&pi->regs->radioregaddr, 2);
288 b2 = (u32) R_REG(&pi->regs->radioregdata);
290 id = ((b0 & 0xf) << 28) | (((b2 << 8) | b1) << 12) | ((b0 >> 4)
293 W_REG_FLUSH(&pi->regs->phy4waddr, RADIO_IDCODE);
294 id = (u32) R_REG(&pi->regs->phy4wdatalo);
295 id |= (u32) R_REG(&pi->regs->phy4wdatahi) << 16;
301 void and_radio_reg(struct brcms_phy *pi, u16 addr, u16 val)
305 rval = read_radio_reg(pi, addr);
306 write_radio_reg(pi, addr, (rval & val));
309 void or_radio_reg(struct brcms_phy *pi, u16 addr, u16 val)
313 rval = read_radio_reg(pi, addr);
314 write_radio_reg(pi, addr, (rval | val));
317 void xor_radio_reg(struct brcms_phy *pi, u16 addr, u16 mask)
321 rval = read_radio_reg(pi, addr);
322 write_radio_reg(pi, addr, (rval ^ mask));
325 void mod_radio_reg(struct brcms_phy *pi, u16 addr, u16 mask, u16 val)
329 rval = read_radio_reg(pi, addr);
330 write_radio_reg(pi, addr, (rval & ~mask) | (val & mask));
333 void write_phy_channel_reg(struct brcms_phy *pi, uint val)
335 W_REG(&pi->regs->phychannel, val);
338 u16 read_phy_reg(struct brcms_phy *pi, u16 addr)
340 struct d11regs *regs;
344 W_REG_FLUSH(®s->phyregaddr, addr);
347 return R_REG(®s->phyregdata);
350 void write_phy_reg(struct brcms_phy *pi, u16 addr, u16 val)
352 struct d11regs *regs;
356 #ifdef CONFIG_BCM47XX
357 W_REG_FLUSH(®s->phyregaddr, addr);
358 W_REG(®s->phyregdata, val);
360 (void)R_REG(®s->phyregdata);
362 W_REG((u32 *)(®s->phyregaddr),
364 if (++pi->phy_wreg >= pi->phy_wreg_limit) {
366 (void)R_REG(®s->phyversion);
371 void and_phy_reg(struct brcms_phy *pi, u16 addr, u16 val)
373 struct d11regs *regs;
377 W_REG_FLUSH(®s->phyregaddr, addr);
379 W_REG(®s->phyregdata, (R_REG(®s->phyregdata) & val));
383 void or_phy_reg(struct brcms_phy *pi, u16 addr, u16 val)
385 struct d11regs *regs;
389 W_REG_FLUSH(®s->phyregaddr, addr);
391 W_REG(®s->phyregdata, (R_REG(®s->phyregdata) | val));
395 void mod_phy_reg(struct brcms_phy *pi, u16 addr, u16 mask, u16 val)
397 struct d11regs *regs;
401 W_REG_FLUSH(®s->phyregaddr, addr);
403 W_REG(®s->phyregdata,
404 ((R_REG(®s->phyregdata) & ~mask) | (val & mask)));
408 static void wlc_set_phy_uninitted(struct brcms_phy *pi)
412 pi->initialized = false;
415 pi->nrssi_table_delta = 0x7fffffff;
417 pi->mintxbias = 0xffff;
420 pi->phy_spuravoid = SPURAVOID_DISABLE;
422 if (NREV_GE(pi->pubpi.phy_rev, 3)
423 && NREV_LT(pi->pubpi.phy_rev, 7))
424 pi->phy_spuravoid = SPURAVOID_AUTO;
426 pi->nphy_papd_skip = 0;
427 pi->nphy_papd_epsilon_offset[0] = 0xf588;
428 pi->nphy_papd_epsilon_offset[1] = 0xf588;
429 pi->nphy_txpwr_idx[0] = 128;
430 pi->nphy_txpwr_idx[1] = 128;
431 pi->nphy_txpwrindex[0].index_internal = 40;
432 pi->nphy_txpwrindex[1].index_internal = 40;
435 pi->phy_spuravoid = SPURAVOID_AUTO;
437 pi->radiopwr = 0xffff;
438 for (i = 0; i < STATIC_NUM_RF; i++) {
439 for (j = 0; j < STATIC_NUM_BB; j++)
440 pi->stats_11b_txpower[i][j] = -1;
444 struct shared_phy *wlc_phy_shared_attach(struct shared_phy_params *shp)
446 struct shared_phy *sh;
448 sh = kzalloc(sizeof(struct shared_phy), GFP_ATOMIC);
453 sh->physhim = shp->physhim;
454 sh->unit = shp->unit;
455 sh->corerev = shp->corerev;
459 sh->chip = shp->chip;
460 sh->chiprev = shp->chiprev;
461 sh->chippkg = shp->chippkg;
462 sh->sromrev = shp->sromrev;
463 sh->boardtype = shp->boardtype;
464 sh->boardrev = shp->boardrev;
465 sh->boardvendor = shp->boardvendor;
466 sh->boardflags = shp->boardflags;
467 sh->boardflags2 = shp->boardflags2;
468 sh->buscorerev = shp->buscorerev;
470 sh->fast_timer = PHY_SW_TIMER_FAST;
471 sh->slow_timer = PHY_SW_TIMER_SLOW;
472 sh->glacial_timer = PHY_SW_TIMER_GLACIAL;
474 sh->rssi_mode = RSSI_ANT_MERGE_MAX;
479 static void wlc_phy_timercb_phycal(struct brcms_phy *pi)
483 if (PHY_PERICAL_MPHASE_PENDING(pi)) {
485 wlc_phy_cal_perical_mphase_reset(pi);
489 if (SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi)) {
492 wlc_phy_cal_perical_mphase_restart(pi);
494 wlc_phy_cal_perical_nphy_run(pi, PHY_PERICAL_AUTO);
495 wlapi_add_timer(pi->sh->physhim, pi->phycal_timer, delay, 0);
501 static u32 wlc_phy_get_radio_ver(struct brcms_phy *pi)
505 ver = read_radio_id(pi);
510 struct brcms_phy_pub *
511 wlc_phy_attach(struct shared_phy *sh, struct d11regs *regs, int bandtype,
512 char *vars, struct wiphy *wiphy)
514 struct brcms_phy *pi;
520 if (D11REV_IS(sh->corerev, 4))
521 sflags = SISF_2G_PHY | SISF_5G_PHY;
523 sflags = ai_core_sflags(sh->sih, 0, 0);
525 if (bandtype == BRCM_BAND_5G) {
526 if ((sflags & (SISF_5G_PHY | SISF_DB_PHY)) == 0)
531 if ((sflags & SISF_DB_PHY) && pi) {
532 wlapi_bmac_corereset(pi->sh->physhim, pi->pubpi.coreflags);
534 return &pi->pubpi_ro;
537 pi = kzalloc(sizeof(struct brcms_phy), GFP_ATOMIC);
543 pi->phy_init_por = true;
544 pi->phy_wreg_limit = PHY_WREG_LIMIT;
548 pi->txpwr_percent = 100;
550 pi->do_initcal = true;
552 pi->phycal_tempdelta = 0;
554 if (bandtype == BRCM_BAND_2G && (sflags & SISF_2G_PHY))
555 pi->pubpi.coreflags = SICF_GMODE;
557 wlapi_bmac_corereset(pi->sh->physhim, pi->pubpi.coreflags);
558 phyversion = R_REG(&pi->regs->phyversion);
560 pi->pubpi.phy_type = PHY_TYPE(phyversion);
561 pi->pubpi.phy_rev = phyversion & PV_PV_MASK;
563 if (pi->pubpi.phy_type == PHY_TYPE_LCNXN) {
564 pi->pubpi.phy_type = PHY_TYPE_N;
565 pi->pubpi.phy_rev += LCNXN_BASEREV;
567 pi->pubpi.phy_corenum = PHY_CORE_NUM_2;
568 pi->pubpi.ana_rev = (phyversion & PV_AV_MASK) >> PV_AV_SHIFT;
570 if (!pi->pubpi.phy_type == PHY_TYPE_N &&
571 !pi->pubpi.phy_type == PHY_TYPE_LCN)
574 if (bandtype == BRCM_BAND_5G) {
577 } else if (!ISNPHY(pi) && !ISLCNPHY(pi)) {
581 wlc_phy_anacore((struct brcms_phy_pub *) pi, ON);
583 idcode = wlc_phy_get_radio_ver(pi);
585 (idcode & IDCODE_ID_MASK) >> IDCODE_ID_SHIFT;
587 (idcode & IDCODE_REV_MASK) >> IDCODE_REV_SHIFT;
589 (idcode & IDCODE_VER_MASK) >> IDCODE_VER_SHIFT;
590 if (!VALID_RADIO(pi, pi->pubpi.radioid))
593 wlc_phy_switch_radio((struct brcms_phy_pub *) pi, OFF);
595 wlc_set_phy_uninitted(pi);
597 pi->bw = WL_CHANSPEC_BW_20;
598 pi->radio_chanspec = (bandtype == BRCM_BAND_2G) ?
599 ch20mhz_chspec(1) : ch20mhz_chspec(36);
601 pi->rxiq_samps = PHY_NOISE_SAMPLE_LOG_NUM_NPHY;
602 pi->rxiq_antsel = ANT_RX_DIV_DEF;
604 pi->watchdog_override = true;
606 pi->cal_type_override = PHY_PERICAL_AUTO;
608 pi->nphy_saved_noisevars.bufcount = 0;
611 pi->min_txpower = PHY_TXPWR_MIN_NPHY;
613 pi->min_txpower = PHY_TXPWR_MIN;
615 pi->sh->phyrxchain = 0x3;
617 pi->rx2tx_biasentry = -1;
619 pi->phy_txcore_disable_temp = PHY_CHAIN_TX_DISABLE_TEMP;
620 pi->phy_txcore_enable_temp =
621 PHY_CHAIN_TX_DISABLE_TEMP - PHY_HYSTERESIS_DELTATEMP;
622 pi->phy_tempsense_offset = 0;
623 pi->phy_txcore_heatedup = false;
625 pi->nphy_lastcal_temp = -50;
627 pi->phynoise_polling = true;
628 if (ISNPHY(pi) || ISLCNPHY(pi))
629 pi->phynoise_polling = false;
631 for (i = 0; i < TXP_NUM_RATES; i++) {
632 pi->txpwr_limit[i] = BRCMS_TXPWR_MAX;
633 pi->txpwr_env_limit[i] = BRCMS_TXPWR_MAX;
634 pi->tx_user_target[i] = BRCMS_TXPWR_MAX;
637 pi->radiopwr_override = RADIOPWR_OVERRIDE_DEF;
639 pi->user_txpwr_at_rfport = false;
643 pi->phycal_timer = wlapi_init_timer(pi->sh->physhim,
644 wlc_phy_timercb_phycal,
646 if (!pi->phycal_timer)
649 if (!wlc_phy_attach_nphy(pi))
652 } else if (ISLCNPHY(pi)) {
653 if (!wlc_phy_attach_lcnphy(pi))
659 pi->next = pi->sh->phy_head;
662 pi->vars = (char *)&pi->vars;
664 memcpy(&pi->pubpi_ro, &pi->pubpi, sizeof(struct brcms_phy_pub));
666 return &pi->pubpi_ro;
673 void wlc_phy_detach(struct brcms_phy_pub *pih)
675 struct brcms_phy *pi = (struct brcms_phy *) pih;
681 if (pi->phycal_timer) {
682 wlapi_free_timer(pi->sh->physhim, pi->phycal_timer);
683 pi->phycal_timer = NULL;
686 if (pi->sh->phy_head == pi)
687 pi->sh->phy_head = pi->next;
688 else if (pi->sh->phy_head->next == pi)
689 pi->sh->phy_head->next = NULL;
691 if (pi->pi_fptr.detach)
692 (pi->pi_fptr.detach)(pi);
699 wlc_phy_get_phyversion(struct brcms_phy_pub *pih, u16 *phytype, u16 *phyrev,
700 u16 *radioid, u16 *radiover)
702 struct brcms_phy *pi = (struct brcms_phy *) pih;
703 *phytype = (u16) pi->pubpi.phy_type;
704 *phyrev = (u16) pi->pubpi.phy_rev;
705 *radioid = pi->pubpi.radioid;
706 *radiover = pi->pubpi.radiorev;
711 bool wlc_phy_get_encore(struct brcms_phy_pub *pih)
713 struct brcms_phy *pi = (struct brcms_phy *) pih;
714 return pi->pubpi.abgphy_encore;
717 u32 wlc_phy_get_coreflags(struct brcms_phy_pub *pih)
719 struct brcms_phy *pi = (struct brcms_phy *) pih;
720 return pi->pubpi.coreflags;
723 void wlc_phy_anacore(struct brcms_phy_pub *pih, bool on)
725 struct brcms_phy *pi = (struct brcms_phy *) pih;
729 if (NREV_GE(pi->pubpi.phy_rev, 3)) {
730 write_phy_reg(pi, 0xa6, 0x0d);
731 write_phy_reg(pi, 0x8f, 0x0);
732 write_phy_reg(pi, 0xa7, 0x0d);
733 write_phy_reg(pi, 0xa5, 0x0);
735 write_phy_reg(pi, 0xa5, 0x0);
738 if (NREV_GE(pi->pubpi.phy_rev, 3)) {
739 write_phy_reg(pi, 0x8f, 0x07ff);
740 write_phy_reg(pi, 0xa6, 0x0fd);
741 write_phy_reg(pi, 0xa5, 0x07ff);
742 write_phy_reg(pi, 0xa7, 0x0fd);
744 write_phy_reg(pi, 0xa5, 0x7fff);
747 } else if (ISLCNPHY(pi)) {
749 and_phy_reg(pi, 0x43b,
750 ~((0x1 << 0) | (0x1 << 1) | (0x1 << 2)));
752 or_phy_reg(pi, 0x43c,
753 (0x1 << 0) | (0x1 << 1) | (0x1 << 2));
754 or_phy_reg(pi, 0x43b,
755 (0x1 << 0) | (0x1 << 1) | (0x1 << 2));
760 u32 wlc_phy_clk_bwbits(struct brcms_phy_pub *pih)
762 struct brcms_phy *pi = (struct brcms_phy *) pih;
764 u32 phy_bw_clkbits = 0;
766 if (pi && (ISNPHY(pi) || ISLCNPHY(pi))) {
768 case WL_CHANSPEC_BW_10:
769 phy_bw_clkbits = SICF_BW10;
771 case WL_CHANSPEC_BW_20:
772 phy_bw_clkbits = SICF_BW20;
774 case WL_CHANSPEC_BW_40:
775 phy_bw_clkbits = SICF_BW40;
782 return phy_bw_clkbits;
785 void wlc_phy_por_inform(struct brcms_phy_pub *ppi)
787 struct brcms_phy *pi = (struct brcms_phy *) ppi;
789 pi->phy_init_por = true;
792 void wlc_phy_edcrs_lock(struct brcms_phy_pub *pih, bool lock)
794 struct brcms_phy *pi = (struct brcms_phy *) pih;
796 pi->edcrs_threshold_lock = lock;
798 write_phy_reg(pi, 0x22c, 0x46b);
799 write_phy_reg(pi, 0x22d, 0x46b);
800 write_phy_reg(pi, 0x22e, 0x3c0);
801 write_phy_reg(pi, 0x22f, 0x3c0);
804 void wlc_phy_initcal_enable(struct brcms_phy_pub *pih, bool initcal)
806 struct brcms_phy *pi = (struct brcms_phy *) pih;
808 pi->do_initcal = initcal;
811 void wlc_phy_hw_clk_state_upd(struct brcms_phy_pub *pih, bool newstate)
813 struct brcms_phy *pi = (struct brcms_phy *) pih;
818 pi->sh->clk = newstate;
821 void wlc_phy_hw_state_upd(struct brcms_phy_pub *pih, bool newstate)
823 struct brcms_phy *pi = (struct brcms_phy *) pih;
828 pi->sh->up = newstate;
831 void wlc_phy_init(struct brcms_phy_pub *pih, u16 chanspec)
834 void (*phy_init)(struct brcms_phy *) = NULL;
835 struct brcms_phy *pi = (struct brcms_phy *) pih;
837 if (pi->init_in_progress)
840 pi->init_in_progress = true;
842 pi->radio_chanspec = chanspec;
844 mc = R_REG(&pi->regs->maccontrol);
845 if (WARN(mc & MCTL_EN_MAC, "HW error MAC running on init"))
848 if (!(pi->measure_hold & PHY_HOLD_FOR_SCAN))
849 pi->measure_hold |= PHY_HOLD_FOR_NOT_ASSOC;
851 if (WARN(!(ai_core_sflags(pi->sh->sih, 0, 0) & SISF_FCLKA),
852 "HW error SISF_FCLKA\n"))
855 phy_init = pi->pi_fptr.init;
857 if (phy_init == NULL)
860 wlc_phy_anacore(pih, ON);
862 if (CHSPEC_BW(pi->radio_chanspec) != pi->bw)
863 wlapi_bmac_bw_set(pi->sh->physhim,
864 CHSPEC_BW(pi->radio_chanspec));
866 pi->nphy_gain_boost = true;
868 wlc_phy_switch_radio((struct brcms_phy_pub *) pi, ON);
872 pi->phy_init_por = false;
874 if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12))
875 wlc_phy_do_dummy_tx(pi, true, OFF);
878 wlc_phy_txpower_update_shm(pi);
880 wlc_phy_ant_rxdiv_set((struct brcms_phy_pub *) pi, pi->sh->rx_antdiv);
882 pi->init_in_progress = false;
885 void wlc_phy_cal_init(struct brcms_phy_pub *pih)
887 struct brcms_phy *pi = (struct brcms_phy *) pih;
888 void (*cal_init)(struct brcms_phy *) = NULL;
890 if (WARN((R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC) != 0,
891 "HW error: MAC enabled during phy cal\n"))
894 if (!pi->initialized) {
895 cal_init = pi->pi_fptr.calinit;
899 pi->initialized = true;
903 int wlc_phy_down(struct brcms_phy_pub *pih)
905 struct brcms_phy *pi = (struct brcms_phy *) pih;
909 && !wlapi_del_timer(pi->sh->physhim, pi->phycal_timer))
912 pi->nphy_iqcal_chanspec_2G = 0;
913 pi->nphy_iqcal_chanspec_5G = 0;
919 wlc_phy_table_addr(struct brcms_phy *pi, uint tbl_id, uint tbl_offset,
920 u16 tblAddr, u16 tblDataHi, u16 tblDataLo)
922 write_phy_reg(pi, tblAddr, (tbl_id << 10) | tbl_offset);
924 pi->tbl_data_hi = tblDataHi;
925 pi->tbl_data_lo = tblDataLo;
927 if (pi->sh->chip == BCM43224_CHIP_ID &&
928 pi->sh->chiprev == 1) {
929 pi->tbl_addr = tblAddr;
930 pi->tbl_save_id = tbl_id;
931 pi->tbl_save_offset = tbl_offset;
935 void wlc_phy_table_data_write(struct brcms_phy *pi, uint width, u32 val)
937 if ((pi->sh->chip == BCM43224_CHIP_ID) &&
938 (pi->sh->chiprev == 1) &&
939 (pi->tbl_save_id == NPHY_TBL_ID_ANTSWCTRLLUT)) {
940 read_phy_reg(pi, pi->tbl_data_lo);
942 write_phy_reg(pi, pi->tbl_addr,
943 (pi->tbl_save_id << 10) | pi->tbl_save_offset);
944 pi->tbl_save_offset++;
948 write_phy_reg(pi, pi->tbl_data_hi, (u16) (val >> 16));
949 write_phy_reg(pi, pi->tbl_data_lo, (u16) val);
951 write_phy_reg(pi, pi->tbl_data_lo, (u16) val);
956 wlc_phy_write_table(struct brcms_phy *pi, const struct phytbl_info *ptbl_info,
957 u16 tblAddr, u16 tblDataHi, u16 tblDataLo)
960 uint tbl_id = ptbl_info->tbl_id;
961 uint tbl_offset = ptbl_info->tbl_offset;
962 uint tbl_width = ptbl_info->tbl_width;
963 const u8 *ptbl_8b = (const u8 *)ptbl_info->tbl_ptr;
964 const u16 *ptbl_16b = (const u16 *)ptbl_info->tbl_ptr;
965 const u32 *ptbl_32b = (const u32 *)ptbl_info->tbl_ptr;
967 write_phy_reg(pi, tblAddr, (tbl_id << 10) | tbl_offset);
969 for (idx = 0; idx < ptbl_info->tbl_len; idx++) {
971 if ((pi->sh->chip == BCM43224_CHIP_ID) &&
972 (pi->sh->chiprev == 1) &&
973 (tbl_id == NPHY_TBL_ID_ANTSWCTRLLUT)) {
974 read_phy_reg(pi, tblDataLo);
976 write_phy_reg(pi, tblAddr,
977 (tbl_id << 10) | (tbl_offset + idx));
980 if (tbl_width == 32) {
981 write_phy_reg(pi, tblDataHi,
982 (u16) (ptbl_32b[idx] >> 16));
983 write_phy_reg(pi, tblDataLo, (u16) ptbl_32b[idx]);
984 } else if (tbl_width == 16) {
985 write_phy_reg(pi, tblDataLo, ptbl_16b[idx]);
987 write_phy_reg(pi, tblDataLo, ptbl_8b[idx]);
993 wlc_phy_read_table(struct brcms_phy *pi, const struct phytbl_info *ptbl_info,
994 u16 tblAddr, u16 tblDataHi, u16 tblDataLo)
997 uint tbl_id = ptbl_info->tbl_id;
998 uint tbl_offset = ptbl_info->tbl_offset;
999 uint tbl_width = ptbl_info->tbl_width;
1000 u8 *ptbl_8b = (u8 *)ptbl_info->tbl_ptr;
1001 u16 *ptbl_16b = (u16 *)ptbl_info->tbl_ptr;
1002 u32 *ptbl_32b = (u32 *)ptbl_info->tbl_ptr;
1004 write_phy_reg(pi, tblAddr, (tbl_id << 10) | tbl_offset);
1006 for (idx = 0; idx < ptbl_info->tbl_len; idx++) {
1008 if ((pi->sh->chip == BCM43224_CHIP_ID) &&
1009 (pi->sh->chiprev == 1)) {
1010 (void)read_phy_reg(pi, tblDataLo);
1012 write_phy_reg(pi, tblAddr,
1013 (tbl_id << 10) | (tbl_offset + idx));
1016 if (tbl_width == 32) {
1017 ptbl_32b[idx] = read_phy_reg(pi, tblDataLo);
1018 ptbl_32b[idx] |= (read_phy_reg(pi, tblDataHi) << 16);
1019 } else if (tbl_width == 16) {
1020 ptbl_16b[idx] = read_phy_reg(pi, tblDataLo);
1022 ptbl_8b[idx] = (u8) read_phy_reg(pi, tblDataLo);
1028 wlc_phy_init_radio_regs_allbands(struct brcms_phy *pi,
1029 struct radio_20xx_regs *radioregs)
1034 if (radioregs[i].do_init)
1035 write_radio_reg(pi, radioregs[i].address,
1036 (u16) radioregs[i].init);
1039 } while (radioregs[i].address != 0xffff);
1045 wlc_phy_init_radio_regs(struct brcms_phy *pi,
1046 const struct radio_regs *radioregs,
1053 if (CHSPEC_IS5G(pi->radio_chanspec)) {
1054 if (radioregs[i].do_init_a) {
1057 address | core_offset,
1058 (u16) radioregs[i].init_a);
1059 if (ISNPHY(pi) && (++count % 4 == 0))
1060 BRCMS_PHY_WAR_PR51571(pi);
1063 if (radioregs[i].do_init_g) {
1066 address | core_offset,
1067 (u16) radioregs[i].init_g);
1068 if (ISNPHY(pi) && (++count % 4 == 0))
1069 BRCMS_PHY_WAR_PR51571(pi);
1074 } while (radioregs[i].address != 0xffff);
1079 void wlc_phy_do_dummy_tx(struct brcms_phy *pi, bool ofdm, bool pa_on)
1081 #define DUMMY_PKT_LEN 20
1082 struct d11regs *regs = pi->regs;
1084 u8 ofdmpkt[DUMMY_PKT_LEN] = {
1085 0xcc, 0x01, 0x02, 0x00, 0x00, 0x00, 0xd4, 0x00, 0x00, 0x00,
1086 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00
1088 u8 cckpkt[DUMMY_PKT_LEN] = {
1089 0x6e, 0x84, 0x0b, 0x00, 0x00, 0x00, 0xd4, 0x00, 0x00, 0x00,
1090 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00
1094 dummypkt = (u32 *) (ofdm ? ofdmpkt : cckpkt);
1095 wlapi_bmac_write_template_ram(pi->sh->physhim, 0, DUMMY_PKT_LEN,
1098 W_REG(®s->xmtsel, 0);
1100 if (D11REV_GE(pi->sh->corerev, 11))
1101 W_REG(®s->wepctl, 0x100);
1103 W_REG(®s->wepctl, 0);
1105 W_REG(®s->txe_phyctl, (ofdm ? 1 : 0) | PHY_TXC_ANT_0);
1106 if (ISNPHY(pi) || ISLCNPHY(pi))
1107 W_REG(®s->txe_phyctl1, 0x1A02);
1109 W_REG(®s->txe_wm_0, 0);
1110 W_REG(®s->txe_wm_1, 0);
1112 W_REG(®s->xmttplatetxptr, 0);
1113 W_REG(®s->xmttxcnt, DUMMY_PKT_LEN);
1115 W_REG(®s->xmtsel, ((8 << 8) | (1 << 5) | (1 << 2) | 2));
1117 W_REG(®s->txe_ctl, 0);
1121 wlc_phy_pa_override_nphy(pi, OFF);
1124 if (ISNPHY(pi) || ISLCNPHY(pi))
1125 W_REG(®s->txe_aux, 0xD0);
1127 W_REG(®s->txe_aux, ((1 << 5) | (1 << 4)));
1129 (void)R_REG(®s->txe_aux);
1132 count = ofdm ? 30 : 250;
1133 while ((i++ < count)
1134 && (R_REG(®s->txe_status) & (1 << 7)))
1140 && ((R_REG(®s->txe_status) & (1 << 10)) == 0))
1145 while ((i++ < 10) && ((R_REG(®s->ifsstat) & (1 << 8))))
1150 wlc_phy_pa_override_nphy(pi, ON);
1154 void wlc_phy_hold_upd(struct brcms_phy_pub *pih, u32 id, bool set)
1156 struct brcms_phy *pi = (struct brcms_phy *) pih;
1159 mboolset(pi->measure_hold, id);
1161 mboolclr(pi->measure_hold, id);
1166 void wlc_phy_mute_upd(struct brcms_phy_pub *pih, bool mute, u32 flags)
1168 struct brcms_phy *pi = (struct brcms_phy *) pih;
1171 mboolset(pi->measure_hold, PHY_HOLD_FOR_MUTE);
1173 mboolclr(pi->measure_hold, PHY_HOLD_FOR_MUTE);
1175 if (!mute && (flags & PHY_MUTE_FOR_PREISM))
1176 pi->nphy_perical_last = pi->sh->now - pi->sh->glacial_timer;
1180 void wlc_phy_clear_tssi(struct brcms_phy_pub *pih)
1182 struct brcms_phy *pi = (struct brcms_phy *) pih;
1187 wlapi_bmac_write_shm(pi->sh->physhim, M_B_TSSI_0, NULL_TSSI_W);
1188 wlapi_bmac_write_shm(pi->sh->physhim, M_B_TSSI_1, NULL_TSSI_W);
1189 wlapi_bmac_write_shm(pi->sh->physhim, M_G_TSSI_0, NULL_TSSI_W);
1190 wlapi_bmac_write_shm(pi->sh->physhim, M_G_TSSI_1, NULL_TSSI_W);
1194 static bool wlc_phy_cal_txpower_recalc_sw(struct brcms_phy *pi)
1199 void wlc_phy_switch_radio(struct brcms_phy_pub *pih, bool on)
1201 struct brcms_phy *pi = (struct brcms_phy *) pih;
1202 (void)R_REG(&pi->regs->maccontrol);
1205 wlc_phy_switch_radio_nphy(pi, on);
1206 } else if (ISLCNPHY(pi)) {
1208 and_phy_reg(pi, 0x44c,
1211 (0x1 << 10) | (0x1 << 11) | (0x1 << 12)));
1212 and_phy_reg(pi, 0x4b0, ~((0x1 << 3) | (0x1 << 11)));
1213 and_phy_reg(pi, 0x4f9, ~(0x1 << 3));
1215 and_phy_reg(pi, 0x44d,
1218 (0x1 << 12) | (0x1 << 13) | (0x1 << 14)));
1219 or_phy_reg(pi, 0x44c,
1222 (0x1 << 10) | (0x1 << 11) | (0x1 << 12));
1224 and_phy_reg(pi, 0x4b7, ~((0x7f << 8)));
1225 and_phy_reg(pi, 0x4b1, ~((0x1 << 13)));
1226 or_phy_reg(pi, 0x4b0, (0x1 << 3) | (0x1 << 11));
1227 and_phy_reg(pi, 0x4fa, ~((0x1 << 3)));
1228 or_phy_reg(pi, 0x4f9, (0x1 << 3));
1233 u16 wlc_phy_bw_state_get(struct brcms_phy_pub *ppi)
1235 struct brcms_phy *pi = (struct brcms_phy *) ppi;
1240 void wlc_phy_bw_state_set(struct brcms_phy_pub *ppi, u16 bw)
1242 struct brcms_phy *pi = (struct brcms_phy *) ppi;
1247 void wlc_phy_chanspec_radio_set(struct brcms_phy_pub *ppi, u16 newch)
1249 struct brcms_phy *pi = (struct brcms_phy *) ppi;
1250 pi->radio_chanspec = newch;
1254 u16 wlc_phy_chanspec_get(struct brcms_phy_pub *ppi)
1256 struct brcms_phy *pi = (struct brcms_phy *) ppi;
1258 return pi->radio_chanspec;
1261 void wlc_phy_chanspec_set(struct brcms_phy_pub *ppi, u16 chanspec)
1263 struct brcms_phy *pi = (struct brcms_phy *) ppi;
1265 void (*chanspec_set)(struct brcms_phy *, u16) = NULL;
1266 m_cur_channel = CHSPEC_CHANNEL(chanspec);
1267 if (CHSPEC_IS5G(chanspec))
1268 m_cur_channel |= D11_CURCHANNEL_5G;
1269 if (CHSPEC_IS40(chanspec))
1270 m_cur_channel |= D11_CURCHANNEL_40;
1271 wlapi_bmac_write_shm(pi->sh->physhim, M_CURCHANNEL, m_cur_channel);
1273 chanspec_set = pi->pi_fptr.chanset;
1275 (*chanspec_set)(pi, chanspec);
1279 int wlc_phy_chanspec_freq2bandrange_lpssn(uint freq)
1284 range = WL_CHAN_FREQ_RANGE_2G;
1285 else if (freq <= 5320)
1286 range = WL_CHAN_FREQ_RANGE_5GL;
1287 else if (freq <= 5700)
1288 range = WL_CHAN_FREQ_RANGE_5GM;
1290 range = WL_CHAN_FREQ_RANGE_5GH;
1295 int wlc_phy_chanspec_bandrange_get(struct brcms_phy *pi, u16 chanspec)
1298 uint channel = CHSPEC_CHANNEL(chanspec);
1299 uint freq = wlc_phy_channel2freq(channel);
1302 range = wlc_phy_get_chan_freq_range_nphy(pi, channel);
1303 else if (ISLCNPHY(pi))
1304 range = wlc_phy_chanspec_freq2bandrange_lpssn(freq);
1309 void wlc_phy_chanspec_ch14_widefilter_set(struct brcms_phy_pub *ppi,
1312 struct brcms_phy *pi = (struct brcms_phy *) ppi;
1314 pi->channel_14_wide_filter = wide_filter;
1318 int wlc_phy_channel2freq(uint channel)
1322 for (i = 0; i < ARRAY_SIZE(chan_info_all); i++)
1323 if (chan_info_all[i].chan == channel)
1324 return chan_info_all[i].freq;
1329 wlc_phy_chanspec_band_validch(struct brcms_phy_pub *ppi, uint band,
1330 struct brcms_chanvec *channels)
1332 struct brcms_phy *pi = (struct brcms_phy *) ppi;
1336 memset(channels, 0, sizeof(struct brcms_chanvec));
1338 for (i = 0; i < ARRAY_SIZE(chan_info_all); i++) {
1339 channel = chan_info_all[i].chan;
1341 if ((pi->a_band_high_disable) && (channel >= FIRST_REF5_CHANNUM)
1342 && (channel <= LAST_REF5_CHANNUM))
1345 if ((band == BRCM_BAND_2G && channel <= CH_MAX_2G_CHANNEL) ||
1346 (band == BRCM_BAND_5G && channel > CH_MAX_2G_CHANNEL))
1347 setbit(channels->vec, channel);
1351 u16 wlc_phy_chanspec_band_firstch(struct brcms_phy_pub *ppi, uint band)
1353 struct brcms_phy *pi = (struct brcms_phy *) ppi;
1358 for (i = 0; i < ARRAY_SIZE(chan_info_all); i++) {
1359 channel = chan_info_all[i].chan;
1361 if (ISNPHY(pi) && pi->bw == WL_CHANSPEC_BW_40) {
1364 for (j = 0; j < ARRAY_SIZE(chan_info_all); j++) {
1365 if (chan_info_all[j].chan ==
1366 channel + CH_10MHZ_APART)
1370 if (j == ARRAY_SIZE(chan_info_all))
1373 channel = upper_20_sb(channel);
1374 chspec = channel | WL_CHANSPEC_BW_40 |
1375 WL_CHANSPEC_CTL_SB_LOWER;
1376 if (band == BRCM_BAND_2G)
1377 chspec |= WL_CHANSPEC_BAND_2G;
1379 chspec |= WL_CHANSPEC_BAND_5G;
1381 chspec = ch20mhz_chspec(channel);
1383 if ((pi->a_band_high_disable) && (channel >= FIRST_REF5_CHANNUM)
1384 && (channel <= LAST_REF5_CHANNUM))
1387 if ((band == BRCM_BAND_2G && channel <= CH_MAX_2G_CHANNEL) ||
1388 (band == BRCM_BAND_5G && channel > CH_MAX_2G_CHANNEL))
1392 return (u16) INVCHANSPEC;
1395 int wlc_phy_txpower_get(struct brcms_phy_pub *ppi, uint *qdbm, bool *override)
1397 struct brcms_phy *pi = (struct brcms_phy *) ppi;
1399 *qdbm = pi->tx_user_target[0];
1400 if (override != NULL)
1401 *override = pi->txpwroverride;
1405 void wlc_phy_txpower_target_set(struct brcms_phy_pub *ppi,
1406 struct txpwr_limits *txpwr)
1408 bool mac_enabled = false;
1409 struct brcms_phy *pi = (struct brcms_phy *) ppi;
1411 memcpy(&pi->tx_user_target[TXP_FIRST_CCK],
1412 &txpwr->cck[0], BRCMS_NUM_RATES_CCK);
1414 memcpy(&pi->tx_user_target[TXP_FIRST_OFDM],
1415 &txpwr->ofdm[0], BRCMS_NUM_RATES_OFDM);
1416 memcpy(&pi->tx_user_target[TXP_FIRST_OFDM_20_CDD],
1417 &txpwr->ofdm_cdd[0], BRCMS_NUM_RATES_OFDM);
1419 memcpy(&pi->tx_user_target[TXP_FIRST_OFDM_40_SISO],
1420 &txpwr->ofdm_40_siso[0], BRCMS_NUM_RATES_OFDM);
1421 memcpy(&pi->tx_user_target[TXP_FIRST_OFDM_40_CDD],
1422 &txpwr->ofdm_40_cdd[0], BRCMS_NUM_RATES_OFDM);
1424 memcpy(&pi->tx_user_target[TXP_FIRST_MCS_20_SISO],
1425 &txpwr->mcs_20_siso[0], BRCMS_NUM_RATES_MCS_1_STREAM);
1426 memcpy(&pi->tx_user_target[TXP_FIRST_MCS_20_CDD],
1427 &txpwr->mcs_20_cdd[0], BRCMS_NUM_RATES_MCS_1_STREAM);
1428 memcpy(&pi->tx_user_target[TXP_FIRST_MCS_20_STBC],
1429 &txpwr->mcs_20_stbc[0], BRCMS_NUM_RATES_MCS_1_STREAM);
1430 memcpy(&pi->tx_user_target[TXP_FIRST_MCS_20_SDM],
1431 &txpwr->mcs_20_mimo[0], BRCMS_NUM_RATES_MCS_2_STREAM);
1433 memcpy(&pi->tx_user_target[TXP_FIRST_MCS_40_SISO],
1434 &txpwr->mcs_40_siso[0], BRCMS_NUM_RATES_MCS_1_STREAM);
1435 memcpy(&pi->tx_user_target[TXP_FIRST_MCS_40_CDD],
1436 &txpwr->mcs_40_cdd[0], BRCMS_NUM_RATES_MCS_1_STREAM);
1437 memcpy(&pi->tx_user_target[TXP_FIRST_MCS_40_STBC],
1438 &txpwr->mcs_40_stbc[0], BRCMS_NUM_RATES_MCS_1_STREAM);
1439 memcpy(&pi->tx_user_target[TXP_FIRST_MCS_40_SDM],
1440 &txpwr->mcs_40_mimo[0], BRCMS_NUM_RATES_MCS_2_STREAM);
1442 if (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC)
1446 wlapi_suspend_mac_and_wait(pi->sh->physhim);
1448 wlc_phy_txpower_recalc_target(pi);
1449 wlc_phy_cal_txpower_recalc_sw(pi);
1452 wlapi_enable_mac(pi->sh->physhim);
1455 int wlc_phy_txpower_set(struct brcms_phy_pub *ppi, uint qdbm, bool override)
1457 struct brcms_phy *pi = (struct brcms_phy *) ppi;
1463 for (i = 0; i < TXP_NUM_RATES; i++)
1464 pi->tx_user_target[i] = (u8) qdbm;
1466 pi->txpwroverride = false;
1469 if (!SCAN_INPROG_PHY(pi)) {
1472 suspend = (0 == (R_REG(&pi->regs->maccontrol) &
1476 wlapi_suspend_mac_and_wait(pi->sh->physhim);
1478 wlc_phy_txpower_recalc_target(pi);
1479 wlc_phy_cal_txpower_recalc_sw(pi);
1482 wlapi_enable_mac(pi->sh->physhim);
1489 wlc_phy_txpower_sromlimit(struct brcms_phy_pub *ppi, uint channel, u8 *min_pwr,
1490 u8 *max_pwr, int txp_rate_idx)
1492 struct brcms_phy *pi = (struct brcms_phy *) ppi;
1495 *min_pwr = pi->min_txpower * BRCMS_TXPWR_DB_FACTOR;
1498 if (txp_rate_idx < 0)
1499 txp_rate_idx = TXP_FIRST_CCK;
1500 wlc_phy_txpower_sromlimit_get_nphy(pi, channel, max_pwr,
1503 } else if ((channel <= CH_MAX_2G_CHANNEL)) {
1504 if (txp_rate_idx < 0)
1505 txp_rate_idx = TXP_FIRST_CCK;
1506 *max_pwr = pi->tx_srom_max_rate_2g[txp_rate_idx];
1509 *max_pwr = BRCMS_TXPWR_MAX;
1511 if (txp_rate_idx < 0)
1512 txp_rate_idx = TXP_FIRST_OFDM;
1514 for (i = 0; i < ARRAY_SIZE(chan_info_all); i++) {
1515 if (channel == chan_info_all[i].chan)
1520 *max_pwr = pi->hwtxpwr[i];
1523 if ((i >= FIRST_MID_5G_CHAN) && (i <= LAST_MID_5G_CHAN))
1525 pi->tx_srom_max_rate_5g_mid[txp_rate_idx];
1526 if ((i >= FIRST_HIGH_5G_CHAN)
1527 && (i <= LAST_HIGH_5G_CHAN))
1529 pi->tx_srom_max_rate_5g_hi[txp_rate_idx];
1530 if ((i >= FIRST_LOW_5G_CHAN) && (i <= LAST_LOW_5G_CHAN))
1532 pi->tx_srom_max_rate_5g_low[txp_rate_idx];
1538 wlc_phy_txpower_sromlimit_max_get(struct brcms_phy_pub *ppi, uint chan,
1539 u8 *max_txpwr, u8 *min_txpwr)
1541 struct brcms_phy *pi = (struct brcms_phy *) ppi;
1543 u8 tx_pwr_min = 255;
1545 u8 maxtxpwr, mintxpwr, rate, pactrl;
1549 max_num_rate = ISNPHY(pi) ? TXP_NUM_RATES :
1550 ISLCNPHY(pi) ? (TXP_LAST_SISO_MCS_20 +
1551 1) : (TXP_LAST_OFDM + 1);
1553 for (rate = 0; rate < max_num_rate; rate++) {
1555 wlc_phy_txpower_sromlimit(ppi, chan, &mintxpwr, &maxtxpwr,
1558 maxtxpwr = (maxtxpwr > pactrl) ? (maxtxpwr - pactrl) : 0;
1560 maxtxpwr = (maxtxpwr > 6) ? (maxtxpwr - 6) : 0;
1562 tx_pwr_max = max(tx_pwr_max, maxtxpwr);
1563 tx_pwr_min = min(tx_pwr_min, maxtxpwr);
1565 *max_txpwr = tx_pwr_max;
1566 *min_txpwr = tx_pwr_min;
1570 wlc_phy_txpower_boardlimit_band(struct brcms_phy_pub *ppi, uint bandunit,
1571 s32 *max_pwr, s32 *min_pwr, u32 *step_pwr)
1576 u8 wlc_phy_txpower_get_target_min(struct brcms_phy_pub *ppi)
1578 struct brcms_phy *pi = (struct brcms_phy *) ppi;
1580 return pi->tx_power_min;
1583 u8 wlc_phy_txpower_get_target_max(struct brcms_phy_pub *ppi)
1585 struct brcms_phy *pi = (struct brcms_phy *) ppi;
1587 return pi->tx_power_max;
1590 static s8 wlc_phy_env_measure_vbat(struct brcms_phy *pi)
1593 return wlc_lcnphy_vbatsense(pi, 0);
1598 static s8 wlc_phy_env_measure_temperature(struct brcms_phy *pi)
1601 return wlc_lcnphy_tempsense_degree(pi, 0);
1606 static void wlc_phy_upd_env_txpwr_rate_limits(struct brcms_phy *pi, u32 band)
1611 for (i = 0; i < TXP_NUM_RATES; i++)
1612 pi->txpwr_env_limit[i] = BRCMS_TXPWR_MAX;
1614 vbat = wlc_phy_env_measure_vbat(pi);
1615 temp = wlc_phy_env_measure_temperature(pi);
1620 wlc_user_txpwr_antport_to_rfport(struct brcms_phy *pi, uint chan, u32 band,
1625 if (!pi->user_txpwr_at_rfport)
1630 void wlc_phy_txpower_recalc_target(struct brcms_phy *pi)
1632 u8 maxtxpwr, mintxpwr, rate, pactrl;
1634 u8 tx_pwr_target[TXP_NUM_RATES];
1636 u8 tx_pwr_min = 255;
1637 u8 tx_pwr_max_rate_ind = 0;
1641 u32 band = CHSPEC2BAND(pi->radio_chanspec);
1642 void (*txpwr_recalc_fn)(struct brcms_phy *) = NULL;
1644 chspec = pi->radio_chanspec;
1645 if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_NONE)
1646 target_chan = CHSPEC_CHANNEL(chspec);
1647 else if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_UPPER)
1648 target_chan = upper_20_sb(CHSPEC_CHANNEL(chspec));
1650 target_chan = lower_20_sb(CHSPEC_CHANNEL(chspec));
1656 if (CHSPEC_IS40(pi->radio_chanspec)) {
1657 offset_mcs = pi->mcs40_po;
1658 for (i = TXP_FIRST_SISO_MCS_20;
1659 i <= TXP_LAST_SISO_MCS_20; i++) {
1660 pi->tx_srom_max_rate_2g[i - 8] =
1661 pi->tx_srom_max_2g -
1662 ((offset_mcs & 0xf) * 2);
1666 offset_mcs = pi->mcs20_po;
1667 for (i = TXP_FIRST_SISO_MCS_20;
1668 i <= TXP_LAST_SISO_MCS_20; i++) {
1669 pi->tx_srom_max_rate_2g[i - 8] =
1670 pi->tx_srom_max_2g -
1671 ((offset_mcs & 0xf) * 2);
1677 max_num_rate = ((ISNPHY(pi)) ? (TXP_NUM_RATES) :
1679 (TXP_LAST_SISO_MCS_20 + 1) : (TXP_LAST_OFDM + 1)));
1681 wlc_phy_upd_env_txpwr_rate_limits(pi, band);
1683 for (rate = start_rate; rate < max_num_rate; rate++) {
1685 tx_pwr_target[rate] = pi->tx_user_target[rate];
1687 if (pi->user_txpwr_at_rfport)
1688 tx_pwr_target[rate] +=
1689 wlc_user_txpwr_antport_to_rfport(pi,
1694 wlc_phy_txpower_sromlimit((struct brcms_phy_pub *) pi,
1696 &mintxpwr, &maxtxpwr, rate);
1698 maxtxpwr = min(maxtxpwr, pi->txpwr_limit[rate]);
1700 maxtxpwr = (maxtxpwr > pactrl) ? (maxtxpwr - pactrl) : 0;
1702 maxtxpwr = (maxtxpwr > 6) ? (maxtxpwr - 6) : 0;
1704 maxtxpwr = min(maxtxpwr, tx_pwr_target[rate]);
1706 if (pi->txpwr_percent <= 100)
1707 maxtxpwr = (maxtxpwr * pi->txpwr_percent) / 100;
1709 tx_pwr_target[rate] = max(maxtxpwr, mintxpwr);
1711 tx_pwr_target[rate] =
1712 min(tx_pwr_target[rate], pi->txpwr_env_limit[rate]);
1714 if (tx_pwr_target[rate] > tx_pwr_max)
1715 tx_pwr_max_rate_ind = rate;
1717 tx_pwr_max = max(tx_pwr_max, tx_pwr_target[rate]);
1718 tx_pwr_min = min(tx_pwr_min, tx_pwr_target[rate]);
1721 memset(pi->tx_power_offset, 0, sizeof(pi->tx_power_offset));
1722 pi->tx_power_max = tx_pwr_max;
1723 pi->tx_power_min = tx_pwr_min;
1724 pi->tx_power_max_rate_ind = tx_pwr_max_rate_ind;
1725 for (rate = 0; rate < max_num_rate; rate++) {
1727 pi->tx_power_target[rate] = tx_pwr_target[rate];
1729 if (!pi->hwpwrctrl || ISNPHY(pi))
1730 pi->tx_power_offset[rate] =
1731 pi->tx_power_max - pi->tx_power_target[rate];
1733 pi->tx_power_offset[rate] =
1734 pi->tx_power_target[rate] - pi->tx_power_min;
1737 txpwr_recalc_fn = pi->pi_fptr.txpwrrecalc;
1738 if (txpwr_recalc_fn)
1739 (*txpwr_recalc_fn)(pi);
1743 wlc_phy_txpower_reg_limit_calc(struct brcms_phy *pi, struct txpwr_limits *txpwr,
1746 u8 tmp_txpwr_limit[2 * BRCMS_NUM_RATES_OFDM];
1747 u8 *txpwr_ptr1 = NULL, *txpwr_ptr2 = NULL;
1748 int rate_start_index = 0, rate1, rate2, k;
1750 for (rate1 = WL_TX_POWER_CCK_FIRST, rate2 = 0;
1751 rate2 < WL_TX_POWER_CCK_NUM; rate1++, rate2++)
1752 pi->txpwr_limit[rate1] = txpwr->cck[rate2];
1754 for (rate1 = WL_TX_POWER_OFDM_FIRST, rate2 = 0;
1755 rate2 < WL_TX_POWER_OFDM_NUM; rate1++, rate2++)
1756 pi->txpwr_limit[rate1] = txpwr->ofdm[rate2];
1760 for (k = 0; k < 4; k++) {
1764 txpwr_ptr1 = txpwr->mcs_20_siso;
1765 txpwr_ptr2 = txpwr->ofdm;
1766 rate_start_index = WL_TX_POWER_OFDM_FIRST;
1770 txpwr_ptr1 = txpwr->mcs_20_cdd;
1771 txpwr_ptr2 = txpwr->ofdm_cdd;
1772 rate_start_index = WL_TX_POWER_OFDM20_CDD_FIRST;
1776 txpwr_ptr1 = txpwr->mcs_40_siso;
1777 txpwr_ptr2 = txpwr->ofdm_40_siso;
1779 WL_TX_POWER_OFDM40_SISO_FIRST;
1783 txpwr_ptr1 = txpwr->mcs_40_cdd;
1784 txpwr_ptr2 = txpwr->ofdm_40_cdd;
1785 rate_start_index = WL_TX_POWER_OFDM40_CDD_FIRST;
1789 for (rate2 = 0; rate2 < BRCMS_NUM_RATES_OFDM;
1791 tmp_txpwr_limit[rate2] = 0;
1792 tmp_txpwr_limit[BRCMS_NUM_RATES_OFDM + rate2] =
1795 wlc_phy_mcs_to_ofdm_powers_nphy(
1797 BRCMS_NUM_RATES_OFDM -
1798 1, BRCMS_NUM_RATES_OFDM);
1799 for (rate1 = rate_start_index, rate2 = 0;
1800 rate2 < BRCMS_NUM_RATES_OFDM; rate1++, rate2++)
1801 pi->txpwr_limit[rate1] =
1802 min(txpwr_ptr2[rate2],
1803 tmp_txpwr_limit[rate2]);
1806 for (k = 0; k < 4; k++) {
1810 txpwr_ptr1 = txpwr->ofdm;
1811 txpwr_ptr2 = txpwr->mcs_20_siso;
1812 rate_start_index = WL_TX_POWER_MCS20_SISO_FIRST;
1816 txpwr_ptr1 = txpwr->ofdm_cdd;
1817 txpwr_ptr2 = txpwr->mcs_20_cdd;
1818 rate_start_index = WL_TX_POWER_MCS20_CDD_FIRST;
1822 txpwr_ptr1 = txpwr->ofdm_40_siso;
1823 txpwr_ptr2 = txpwr->mcs_40_siso;
1824 rate_start_index = WL_TX_POWER_MCS40_SISO_FIRST;
1828 txpwr_ptr1 = txpwr->ofdm_40_cdd;
1829 txpwr_ptr2 = txpwr->mcs_40_cdd;
1830 rate_start_index = WL_TX_POWER_MCS40_CDD_FIRST;
1833 for (rate2 = 0; rate2 < BRCMS_NUM_RATES_OFDM;
1835 tmp_txpwr_limit[rate2] = 0;
1836 tmp_txpwr_limit[BRCMS_NUM_RATES_OFDM + rate2] =
1839 wlc_phy_ofdm_to_mcs_powers_nphy(
1841 BRCMS_NUM_RATES_OFDM -
1842 1, BRCMS_NUM_RATES_OFDM);
1843 for (rate1 = rate_start_index, rate2 = 0;
1844 rate2 < BRCMS_NUM_RATES_MCS_1_STREAM;
1846 pi->txpwr_limit[rate1] =
1847 min(txpwr_ptr2[rate2],
1848 tmp_txpwr_limit[rate2]);
1851 for (k = 0; k < 2; k++) {
1855 rate_start_index = WL_TX_POWER_MCS20_STBC_FIRST;
1856 txpwr_ptr1 = txpwr->mcs_20_stbc;
1860 rate_start_index = WL_TX_POWER_MCS40_STBC_FIRST;
1861 txpwr_ptr1 = txpwr->mcs_40_stbc;
1864 for (rate1 = rate_start_index, rate2 = 0;
1865 rate2 < BRCMS_NUM_RATES_MCS_1_STREAM;
1867 pi->txpwr_limit[rate1] = txpwr_ptr1[rate2];
1870 for (k = 0; k < 2; k++) {
1874 rate_start_index = WL_TX_POWER_MCS20_SDM_FIRST;
1875 txpwr_ptr1 = txpwr->mcs_20_mimo;
1879 rate_start_index = WL_TX_POWER_MCS40_SDM_FIRST;
1880 txpwr_ptr1 = txpwr->mcs_40_mimo;
1883 for (rate1 = rate_start_index, rate2 = 0;
1884 rate2 < BRCMS_NUM_RATES_MCS_2_STREAM;
1886 pi->txpwr_limit[rate1] = txpwr_ptr1[rate2];
1889 pi->txpwr_limit[WL_TX_POWER_MCS_32] = txpwr->mcs32;
1891 pi->txpwr_limit[WL_TX_POWER_MCS40_CDD_FIRST] =
1892 min(pi->txpwr_limit[WL_TX_POWER_MCS40_CDD_FIRST],
1893 pi->txpwr_limit[WL_TX_POWER_MCS_32]);
1894 pi->txpwr_limit[WL_TX_POWER_MCS_32] =
1895 pi->txpwr_limit[WL_TX_POWER_MCS40_CDD_FIRST];
1899 void wlc_phy_txpwr_percent_set(struct brcms_phy_pub *ppi, u8 txpwr_percent)
1901 struct brcms_phy *pi = (struct brcms_phy *) ppi;
1903 pi->txpwr_percent = txpwr_percent;
1906 void wlc_phy_machwcap_set(struct brcms_phy_pub *ppi, u32 machwcap)
1908 struct brcms_phy *pi = (struct brcms_phy *) ppi;
1910 pi->sh->machwcap = machwcap;
1913 void wlc_phy_runbist_config(struct brcms_phy_pub *ppi, bool start_end)
1915 struct brcms_phy *pi = (struct brcms_phy *) ppi;
1919 if (start_end == ON) {
1923 if (NREV_IS(pi->pubpi.phy_rev, 3)
1924 || NREV_IS(pi->pubpi.phy_rev, 4)) {
1925 W_REG(&pi->regs->phyregaddr, 0xa0);
1926 (void)R_REG(&pi->regs->phyregaddr);
1927 rxc = R_REG(&pi->regs->phyregdata);
1928 W_REG(&pi->regs->phyregdata,
1932 if (NREV_IS(pi->pubpi.phy_rev, 3)
1933 || NREV_IS(pi->pubpi.phy_rev, 4)) {
1934 W_REG(&pi->regs->phyregaddr, 0xa0);
1935 (void)R_REG(&pi->regs->phyregaddr);
1936 W_REG(&pi->regs->phyregdata, rxc);
1939 wlc_phy_por_inform(ppi);
1944 wlc_phy_txpower_limit_set(struct brcms_phy_pub *ppi, struct txpwr_limits *txpwr,
1947 struct brcms_phy *pi = (struct brcms_phy *) ppi;
1949 wlc_phy_txpower_reg_limit_calc(pi, txpwr, chanspec);
1953 for (i = TXP_FIRST_OFDM_20_CDD, j = 0;
1954 j < BRCMS_NUM_RATES_MCS_1_STREAM; i++, j++) {
1955 if (txpwr->mcs_20_siso[j])
1956 pi->txpwr_limit[i] = txpwr->mcs_20_siso[j];
1958 pi->txpwr_limit[i] = txpwr->ofdm[j];
1962 wlapi_suspend_mac_and_wait(pi->sh->physhim);
1964 wlc_phy_txpower_recalc_target(pi);
1965 wlc_phy_cal_txpower_recalc_sw(pi);
1966 wlapi_enable_mac(pi->sh->physhim);
1969 void wlc_phy_ofdm_rateset_war(struct brcms_phy_pub *pih, bool war)
1971 struct brcms_phy *pi = (struct brcms_phy *) pih;
1973 pi->ofdm_rateset_war = war;
1976 void wlc_phy_bf_preempt_enable(struct brcms_phy_pub *pih, bool bf_preempt)
1978 struct brcms_phy *pi = (struct brcms_phy *) pih;
1980 pi->bf_preempt_4306 = bf_preempt;
1983 void wlc_phy_txpower_update_shm(struct brcms_phy *pi)
1992 if (pi->hwpwrctrl) {
1995 wlapi_bmac_write_shm(pi->sh->physhim, M_TXPWR_MAX, 63);
1996 wlapi_bmac_write_shm(pi->sh->physhim, M_TXPWR_N,
1997 1 << NUM_TSSI_FRAMES);
1999 wlapi_bmac_write_shm(pi->sh->physhim, M_TXPWR_TARGET,
2000 pi->tx_power_min << NUM_TSSI_FRAMES);
2002 wlapi_bmac_write_shm(pi->sh->physhim, M_TXPWR_CUR,
2005 for (j = TXP_FIRST_OFDM; j <= TXP_LAST_OFDM; j++) {
2006 const u8 ucode_ofdm_rates[] = {
2007 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c
2009 offset = wlapi_bmac_rate_shm_offset(
2011 ucode_ofdm_rates[j - TXP_FIRST_OFDM]);
2012 wlapi_bmac_write_shm(pi->sh->physhim, offset + 6,
2013 pi->tx_power_offset[j]);
2014 wlapi_bmac_write_shm(pi->sh->physhim, offset + 14,
2015 -(pi->tx_power_offset[j] / 2));
2018 wlapi_bmac_mhf(pi->sh->physhim, MHF2, MHF2_HWPWRCTL,
2019 MHF2_HWPWRCTL, BRCM_BAND_ALL);
2023 for (i = TXP_FIRST_OFDM; i <= TXP_LAST_OFDM; i++)
2024 pi->tx_power_offset[i] =
2025 (u8) roundup(pi->tx_power_offset[i], 8);
2026 wlapi_bmac_write_shm(pi->sh->physhim, M_OFDM_OFFSET,
2028 ((pi->tx_power_offset[TXP_FIRST_OFDM]
2033 bool wlc_phy_txpower_hw_ctrl_get(struct brcms_phy_pub *ppi)
2035 struct brcms_phy *pi = (struct brcms_phy *) ppi;
2038 return pi->nphy_txpwrctrl;
2040 return pi->hwpwrctrl;
2043 void wlc_phy_txpower_hw_ctrl_set(struct brcms_phy_pub *ppi, bool hwpwrctrl)
2045 struct brcms_phy *pi = (struct brcms_phy *) ppi;
2048 if (!pi->hwpwrctrl_capable)
2051 pi->hwpwrctrl = hwpwrctrl;
2052 pi->nphy_txpwrctrl = hwpwrctrl;
2053 pi->txpwrctrl = hwpwrctrl;
2056 suspend = (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
2058 wlapi_suspend_mac_and_wait(pi->sh->physhim);
2060 wlc_phy_txpwrctrl_enable_nphy(pi, pi->nphy_txpwrctrl);
2061 if (pi->nphy_txpwrctrl == PHY_TPC_HW_OFF)
2062 wlc_phy_txpwr_fixpower_nphy(pi);
2064 mod_phy_reg(pi, 0x1e7, (0x7f << 0),
2065 pi->saved_txpwr_idx);
2068 wlapi_enable_mac(pi->sh->physhim);
2072 void wlc_phy_txpower_ipa_upd(struct brcms_phy *pi)
2075 if (NREV_GE(pi->pubpi.phy_rev, 3)) {
2076 pi->ipa2g_on = (pi->srom_fem2g.extpagain == 2);
2077 pi->ipa5g_on = (pi->srom_fem5g.extpagain == 2);
2079 pi->ipa2g_on = false;
2080 pi->ipa5g_on = false;
2084 static u32 wlc_phy_txpower_est_power_nphy(struct brcms_phy *pi)
2086 s16 tx0_status, tx1_status;
2087 u16 estPower1, estPower2;
2088 u8 pwr0, pwr1, adj_pwr0, adj_pwr1;
2091 estPower1 = read_phy_reg(pi, 0x118);
2092 estPower2 = read_phy_reg(pi, 0x119);
2094 if ((estPower1 & (0x1 << 8)) == (0x1 << 8))
2095 pwr0 = (u8) (estPower1 & (0xff << 0)) >> 0;
2099 if ((estPower2 & (0x1 << 8)) == (0x1 << 8))
2100 pwr1 = (u8) (estPower2 & (0xff << 0)) >> 0;
2104 tx0_status = read_phy_reg(pi, 0x1ed);
2105 tx1_status = read_phy_reg(pi, 0x1ee);
2107 if ((tx0_status & (0x1 << 15)) == (0x1 << 15))
2108 adj_pwr0 = (u8) (tx0_status & (0xff << 0)) >> 0;
2111 if ((tx1_status & (0x1 << 15)) == (0x1 << 15))
2112 adj_pwr1 = (u8) (tx1_status & (0xff << 0)) >> 0;
2116 est_pwr = (u32) ((pwr0 << 24) | (pwr1 << 16) | (adj_pwr0 << 8) |
2123 wlc_phy_txpower_get_current(struct brcms_phy_pub *ppi, struct tx_power *power,
2126 struct brcms_phy *pi = (struct brcms_phy *) ppi;
2127 uint rate, num_rates;
2128 u8 min_pwr, max_pwr;
2130 #if WL_TX_POWER_RATES != TXP_NUM_RATES
2131 #error "struct tx_power out of sync with this fn"
2135 power->rf_cores = 2;
2136 power->flags |= (WL_TX_POWER_F_MIMO);
2137 if (pi->nphy_txpwrctrl == PHY_TPC_HW_ON)
2139 (WL_TX_POWER_F_ENABLED | WL_TX_POWER_F_HW);
2140 } else if (ISLCNPHY(pi)) {
2141 power->rf_cores = 1;
2142 power->flags |= (WL_TX_POWER_F_SISO);
2143 if (pi->radiopwr_override == RADIOPWR_OVERRIDE_DEF)
2144 power->flags |= WL_TX_POWER_F_ENABLED;
2146 power->flags |= WL_TX_POWER_F_HW;
2149 num_rates = ((ISNPHY(pi)) ? (TXP_NUM_RATES) :
2151 (TXP_LAST_OFDM_20_CDD + 1) : (TXP_LAST_OFDM + 1)));
2153 for (rate = 0; rate < num_rates; rate++) {
2154 power->user_limit[rate] = pi->tx_user_target[rate];
2155 wlc_phy_txpower_sromlimit(ppi, channel, &min_pwr, &max_pwr,
2157 power->board_limit[rate] = (u8) max_pwr;
2158 power->target[rate] = pi->tx_power_target[rate];
2164 wlapi_suspend_mac_and_wait(pi->sh->physhim);
2165 wlc_phyreg_enter((struct brcms_phy_pub *) pi);
2166 est_pout = wlc_phy_txpower_est_power_nphy(pi);
2167 wlc_phyreg_exit((struct brcms_phy_pub *) pi);
2168 wlapi_enable_mac(pi->sh->physhim);
2170 power->est_Pout[0] = (est_pout >> 8) & 0xff;
2171 power->est_Pout[1] = est_pout & 0xff;
2173 power->est_Pout_act[0] = est_pout >> 24;
2174 power->est_Pout_act[1] = (est_pout >> 16) & 0xff;
2176 if (power->est_Pout[0] == 0x80)
2177 power->est_Pout[0] = 0;
2178 if (power->est_Pout[1] == 0x80)
2179 power->est_Pout[1] = 0;
2181 if (power->est_Pout_act[0] == 0x80)
2182 power->est_Pout_act[0] = 0;
2183 if (power->est_Pout_act[1] == 0x80)
2184 power->est_Pout_act[1] = 0;
2186 power->est_Pout_cck = 0;
2188 power->tx_power_max[0] = pi->tx_power_max;
2189 power->tx_power_max[1] = pi->tx_power_max;
2191 power->tx_power_max_rate_ind[0] = pi->tx_power_max_rate_ind;
2192 power->tx_power_max_rate_ind[1] = pi->tx_power_max_rate_ind;
2193 } else if (pi->hwpwrctrl && pi->sh->up) {
2195 wlc_phyreg_enter(ppi);
2198 power->tx_power_max[0] = pi->tx_power_max;
2199 power->tx_power_max[1] = pi->tx_power_max;
2201 power->tx_power_max_rate_ind[0] =
2202 pi->tx_power_max_rate_ind;
2203 power->tx_power_max_rate_ind[1] =
2204 pi->tx_power_max_rate_ind;
2206 if (wlc_phy_tpc_isenabled_lcnphy(pi))
2209 WL_TX_POWER_F_ENABLED);
2212 ~(WL_TX_POWER_F_HW |
2213 WL_TX_POWER_F_ENABLED);
2215 wlc_lcnphy_get_tssi(pi, (s8 *) &power->est_Pout[0],
2216 (s8 *) &power->est_Pout_cck);
2218 wlc_phyreg_exit(ppi);
2222 void wlc_phy_antsel_type_set(struct brcms_phy_pub *ppi, u8 antsel_type)
2224 struct brcms_phy *pi = (struct brcms_phy *) ppi;
2226 pi->antsel_type = antsel_type;
2229 bool wlc_phy_test_ison(struct brcms_phy_pub *ppi)
2231 struct brcms_phy *pi = (struct brcms_phy *) ppi;
2233 return pi->phytest_on;
2236 void wlc_phy_ant_rxdiv_set(struct brcms_phy_pub *ppi, u8 val)
2238 struct brcms_phy *pi = (struct brcms_phy *) ppi;
2241 pi->sh->rx_antdiv = val;
2243 if (!(ISNPHY(pi) && D11REV_IS(pi->sh->corerev, 16))) {
2244 if (val > ANT_RX_DIV_FORCE_1)
2245 wlapi_bmac_mhf(pi->sh->physhim, MHF1, MHF1_ANTDIV,
2246 MHF1_ANTDIV, BRCM_BAND_ALL);
2248 wlapi_bmac_mhf(pi->sh->physhim, MHF1, MHF1_ANTDIV, 0,
2258 suspend = (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
2260 wlapi_suspend_mac_and_wait(pi->sh->physhim);
2263 if (val > ANT_RX_DIV_FORCE_1) {
2264 mod_phy_reg(pi, 0x410, (0x1 << 1), 0x01 << 1);
2265 mod_phy_reg(pi, 0x410,
2267 ((ANT_RX_DIV_START_1 == val) ? 1 : 0) << 0);
2269 mod_phy_reg(pi, 0x410, (0x1 << 1), 0x00 << 1);
2270 mod_phy_reg(pi, 0x410, (0x1 << 0), (u16) val << 0);
2275 wlapi_enable_mac(pi->sh->physhim);
2281 wlc_phy_noise_calc_phy(struct brcms_phy *pi, u32 *cmplx_pwr, s8 *pwr_ant)
2283 s8 cmplx_pwr_dbm[PHY_CORE_MAX];
2286 memset((u8 *) cmplx_pwr_dbm, 0, sizeof(cmplx_pwr_dbm));
2287 wlc_phy_compute_dB(cmplx_pwr, cmplx_pwr_dbm, pi->pubpi.phy_corenum);
2289 for (i = 0; i < pi->pubpi.phy_corenum; i++) {
2290 if (NREV_GE(pi->pubpi.phy_rev, 3))
2291 cmplx_pwr_dbm[i] += (s8) PHY_NOISE_OFFSETFACT_4322;
2294 cmplx_pwr_dbm[i] += (s8) (16 - (15) * 3 - 70);
2297 for (i = 0; i < pi->pubpi.phy_corenum; i++) {
2298 pi->nphy_noise_win[i][pi->nphy_noise_index] = cmplx_pwr_dbm[i];
2299 pwr_ant[i] = cmplx_pwr_dbm[i];
2301 pi->nphy_noise_index =
2302 MODINC_POW2(pi->nphy_noise_index, PHY_NOISE_WINDOW_SZ);
2306 static void wlc_phy_noise_cb(struct brcms_phy *pi, u8 channel, s8 noise_dbm)
2308 if (!pi->phynoise_state)
2311 if (pi->phynoise_state & PHY_NOISE_STATE_MON) {
2312 if (pi->phynoise_chan_watchdog == channel) {
2313 pi->sh->phy_noise_window[pi->sh->phy_noise_index] =
2315 pi->sh->phy_noise_index =
2316 MODINC(pi->sh->phy_noise_index, MA_WINDOW_SZ);
2318 pi->phynoise_state &= ~PHY_NOISE_STATE_MON;
2321 if (pi->phynoise_state & PHY_NOISE_STATE_EXTERNAL)
2322 pi->phynoise_state &= ~PHY_NOISE_STATE_EXTERNAL;
2326 static s8 wlc_phy_noise_read_shmem(struct brcms_phy *pi)
2328 u32 cmplx_pwr[PHY_CORE_MAX];
2329 s8 noise_dbm_ant[PHY_CORE_MAX];
2331 u32 cmplx_pwr_tot = 0;
2332 s8 noise_dbm = PHY_NOISE_FIXED_VAL_NPHY;
2335 memset((u8 *) cmplx_pwr, 0, sizeof(cmplx_pwr));
2336 memset((u8 *) noise_dbm_ant, 0, sizeof(noise_dbm_ant));
2338 for (idx = 0, core = 0; core < pi->pubpi.phy_corenum; idx += 2,
2340 lo = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP(idx));
2341 hi = wlapi_bmac_read_shm(pi->sh->physhim,
2342 M_PWRIND_MAP(idx + 1));
2343 cmplx_pwr[core] = (hi << 16) + lo;
2344 cmplx_pwr_tot += cmplx_pwr[core];
2345 if (cmplx_pwr[core] == 0)
2346 noise_dbm_ant[core] = PHY_NOISE_FIXED_VAL_NPHY;
2348 cmplx_pwr[core] >>= PHY_NOISE_SAMPLE_LOG_NUM_UCODE;
2351 if (cmplx_pwr_tot != 0)
2352 wlc_phy_noise_calc_phy(pi, cmplx_pwr, noise_dbm_ant);
2354 for (core = 0; core < pi->pubpi.phy_corenum; core++) {
2355 pi->nphy_noise_win[core][pi->nphy_noise_index] =
2356 noise_dbm_ant[core];
2358 if (noise_dbm_ant[core] > noise_dbm)
2359 noise_dbm = noise_dbm_ant[core];
2361 pi->nphy_noise_index =
2362 MODINC_POW2(pi->nphy_noise_index, PHY_NOISE_WINDOW_SZ);
2368 void wlc_phy_noise_sample_intr(struct brcms_phy_pub *pih)
2370 struct brcms_phy *pi = (struct brcms_phy *) pih;
2373 s8 noise_dbm = PHY_NOISE_FIXED_VAL_NPHY;
2376 u32 cmplx_pwr, cmplx_pwr0, cmplx_pwr1;
2378 s32 pwr_offset_dB, gain_dB;
2379 u16 status_0, status_1;
2381 jssi_aux = wlapi_bmac_read_shm(pi->sh->physhim, M_JSSI_AUX);
2382 channel = jssi_aux & D11_CURCHANNEL_MAX;
2384 lo = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP0);
2385 hi = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP1);
2386 cmplx_pwr0 = (hi << 16) + lo;
2388 lo = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP2);
2389 hi = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP3);
2390 cmplx_pwr1 = (hi << 16) + lo;
2391 cmplx_pwr = (cmplx_pwr0 + cmplx_pwr1) >> 6;
2394 status_1 = wlapi_bmac_read_shm(pi->sh->physhim, M_JSSI_0);
2395 if ((cmplx_pwr > 0 && cmplx_pwr < 500)
2396 && ((status_1 & 0xc000) == 0x4000)) {
2398 wlc_phy_compute_dB(&cmplx_pwr, &noise_dbm,
2399 pi->pubpi.phy_corenum);
2400 pwr_offset_dB = (read_phy_reg(pi, 0x434) & 0xFF);
2401 if (pwr_offset_dB > 127)
2402 pwr_offset_dB -= 256;
2404 noise_dbm += (s8) (pwr_offset_dB - 30);
2406 gain_dB = (status_0 & 0x1ff);
2407 noise_dbm -= (s8) (gain_dB);
2409 noise_dbm = PHY_NOISE_FIXED_VAL_LCNPHY;
2411 } else if (ISNPHY(pi)) {
2413 jssi_aux = wlapi_bmac_read_shm(pi->sh->physhim, M_JSSI_AUX);
2414 channel = jssi_aux & D11_CURCHANNEL_MAX;
2416 noise_dbm = wlc_phy_noise_read_shmem(pi);
2419 wlc_phy_noise_cb(pi, channel, noise_dbm);
2424 wlc_phy_noise_sample_request(struct brcms_phy_pub *pih, u8 reason, u8 ch)
2426 struct brcms_phy *pi = (struct brcms_phy *) pih;
2427 s8 noise_dbm = PHY_NOISE_FIXED_VAL_NPHY;
2428 bool sampling_in_progress = (pi->phynoise_state != 0);
2429 bool wait_for_intr = true;
2432 case PHY_NOISE_SAMPLE_MON:
2433 pi->phynoise_chan_watchdog = ch;
2434 pi->phynoise_state |= PHY_NOISE_STATE_MON;
2437 case PHY_NOISE_SAMPLE_EXTERNAL:
2438 pi->phynoise_state |= PHY_NOISE_STATE_EXTERNAL;
2445 if (sampling_in_progress)
2448 pi->phynoise_now = pi->sh->now;
2450 if (pi->phy_fixed_noise) {
2452 pi->nphy_noise_win[WL_ANT_IDX_1][pi->nphy_noise_index] =
2453 PHY_NOISE_FIXED_VAL_NPHY;
2454 pi->nphy_noise_win[WL_ANT_IDX_2][pi->nphy_noise_index] =
2455 PHY_NOISE_FIXED_VAL_NPHY;
2456 pi->nphy_noise_index = MODINC_POW2(pi->nphy_noise_index,
2457 PHY_NOISE_WINDOW_SZ);
2458 noise_dbm = PHY_NOISE_FIXED_VAL_NPHY;
2460 noise_dbm = PHY_NOISE_FIXED_VAL;
2463 wait_for_intr = false;
2468 if (!pi->phynoise_polling
2469 || (reason == PHY_NOISE_SAMPLE_EXTERNAL)) {
2470 wlapi_bmac_write_shm(pi->sh->physhim, M_JSSI_0, 0);
2471 wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP0, 0);
2472 wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP1, 0);
2473 wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP2, 0);
2474 wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP3, 0);
2476 OR_REG(&pi->regs->maccommand,
2479 wlapi_suspend_mac_and_wait(pi->sh->physhim);
2480 wlc_lcnphy_deaf_mode(pi, (bool) 0);
2481 noise_dbm = (s8) wlc_lcnphy_rx_signal_power(pi, 20);
2482 wlc_lcnphy_deaf_mode(pi, (bool) 1);
2483 wlapi_enable_mac(pi->sh->physhim);
2484 wait_for_intr = false;
2486 } else if (ISNPHY(pi)) {
2487 if (!pi->phynoise_polling
2488 || (reason == PHY_NOISE_SAMPLE_EXTERNAL)) {
2490 wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP0, 0);
2491 wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP1, 0);
2492 wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP2, 0);
2493 wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP3, 0);
2495 OR_REG(&pi->regs->maccommand,
2498 struct phy_iq_est est[PHY_CORE_MAX];
2499 u32 cmplx_pwr[PHY_CORE_MAX];
2500 s8 noise_dbm_ant[PHY_CORE_MAX];
2501 u16 log_num_samps, num_samps, classif_state = 0;
2506 memset((u8 *) est, 0, sizeof(est));
2507 memset((u8 *) cmplx_pwr, 0, sizeof(cmplx_pwr));
2508 memset((u8 *) noise_dbm_ant, 0, sizeof(noise_dbm_ant));
2510 log_num_samps = PHY_NOISE_SAMPLE_LOG_NUM_NPHY;
2511 num_samps = 1 << log_num_samps;
2513 wlapi_suspend_mac_and_wait(pi->sh->physhim);
2514 classif_state = wlc_phy_classifier_nphy(pi, 0, 0);
2515 wlc_phy_classifier_nphy(pi, 3, 0);
2516 wlc_phy_rx_iq_est_nphy(pi, est, num_samps, wait_time,
2518 wlc_phy_classifier_nphy(pi, (0x7 << 0), classif_state);
2519 wlapi_enable_mac(pi->sh->physhim);
2521 for (i = 0; i < pi->pubpi.phy_corenum; i++)
2522 cmplx_pwr[i] = (est[i].i_pwr + est[i].q_pwr) >>
2525 wlc_phy_noise_calc_phy(pi, cmplx_pwr, noise_dbm_ant);
2527 for (i = 0; i < pi->pubpi.phy_corenum; i++) {
2528 pi->nphy_noise_win[i][pi->nphy_noise_index] =
2531 if (noise_dbm_ant[i] > noise_dbm)
2532 noise_dbm = noise_dbm_ant[i];
2534 pi->nphy_noise_index = MODINC_POW2(pi->nphy_noise_index,
2535 PHY_NOISE_WINDOW_SZ);
2537 wait_for_intr = false;
2544 wlc_phy_noise_cb(pi, ch, noise_dbm);
2548 void wlc_phy_noise_sample_request_external(struct brcms_phy_pub *pih)
2552 channel = CHSPEC_CHANNEL(wlc_phy_chanspec_get(pih));
2554 wlc_phy_noise_sample_request(pih, PHY_NOISE_SAMPLE_EXTERNAL, channel);
2557 static const s8 lcnphy_gain_index_offset_for_pkt_rssi[] = {
2598 void wlc_phy_compute_dB(u32 *cmplx_pwr, s8 *p_cmplx_pwr_dB, u8 core)
2600 u8 msb, secondmsb, i;
2603 for (i = 0; i < core; i++) {
2608 secondmsb = (u8) ((tmp >> (--msb - 1)) & 1);
2609 p_cmplx_pwr_dB[i] = (s8) (3 * msb + 2 * secondmsb);
2613 void wlc_phy_rssi_compute(struct brcms_phy_pub *pih,
2614 struct brcms_d11rxhdr *wlc_rxhdr)
2616 struct d11rxhdr *rxh = &wlc_rxhdr->rxhdr;
2617 int rssi = le16_to_cpu(rxh->PhyRxStatus_1) & PRXS1_JSSI_MASK;
2618 uint radioid = pih->radioid;
2619 struct brcms_phy *pi = (struct brcms_phy *) pih;
2621 if ((pi->sh->corerev >= 11)
2622 && !(le16_to_cpu(rxh->RxStatus2) & RXS_PHYRXST_VALID)) {
2623 rssi = BRCMS_RSSI_INVALID;
2628 u8 gidx = (le16_to_cpu(rxh->PhyRxStatus_2) & 0xFC00) >> 10;
2629 struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
2634 rssi = rssi + lcnphy_gain_index_offset_for_pkt_rssi[gidx];
2635 if ((rssi > -46) && (gidx > 18))
2638 rssi = rssi + pi_lcn->lcnphy_pkteng_rssi_slope;
2647 } else if (radioid == BCM2055_ID || radioid == BCM2056_ID
2648 || radioid == BCM2057_ID) {
2649 rssi = wlc_phy_rssi_compute_nphy(pi, wlc_rxhdr);
2653 wlc_rxhdr->rssi = (s8) rssi;
2656 void wlc_phy_freqtrack_start(struct brcms_phy_pub *pih)
2661 void wlc_phy_freqtrack_end(struct brcms_phy_pub *pih)
2666 void wlc_phy_set_deaf(struct brcms_phy_pub *ppi, bool user_flag)
2668 struct brcms_phy *pi;
2669 pi = (struct brcms_phy *) ppi;
2672 wlc_lcnphy_deaf_mode(pi, true);
2673 else if (ISNPHY(pi))
2674 wlc_nphy_deaf_mode(pi, true);
2677 void wlc_phy_watchdog(struct brcms_phy_pub *pih)
2679 struct brcms_phy *pi = (struct brcms_phy *) pih;
2680 bool delay_phy_cal = false;
2683 if (!pi->watchdog_override)
2686 if (!(SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi)))
2687 wlc_phy_noise_sample_request((struct brcms_phy_pub *) pi,
2688 PHY_NOISE_SAMPLE_MON,
2692 if (pi->phynoise_state && (pi->sh->now - pi->phynoise_now) > 5)
2693 pi->phynoise_state = 0;
2695 if ((!pi->phycal_txpower) ||
2696 ((pi->sh->now - pi->phycal_txpower) >= pi->sh->fast_timer)) {
2698 if (!SCAN_INPROG_PHY(pi) && wlc_phy_cal_txpower_recalc_sw(pi))
2699 pi->phycal_txpower = pi->sh->now;
2702 if ((SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi)
2703 || ASSOC_INPROG_PHY(pi)))
2706 if (ISNPHY(pi) && !pi->disable_percal && !delay_phy_cal) {
2708 if ((pi->nphy_perical != PHY_PERICAL_DISABLE) &&
2709 (pi->nphy_perical != PHY_PERICAL_MANUAL) &&
2710 ((pi->sh->now - pi->nphy_perical_last) >=
2711 pi->sh->glacial_timer))
2712 wlc_phy_cal_perical((struct brcms_phy_pub *) pi,
2713 PHY_PERICAL_WATCHDOG);
2715 wlc_phy_txpwr_papd_cal_nphy(pi);
2719 if (pi->phy_forcecal ||
2720 ((pi->sh->now - pi->phy_lastcal) >=
2721 pi->sh->glacial_timer)) {
2722 if (!(SCAN_RM_IN_PROGRESS(pi) || ASSOC_INPROG_PHY(pi)))
2723 wlc_lcnphy_calib_modes(
2725 LCNPHY_PERICAL_TEMPBASED_TXPWRCTRL);
2727 (SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi)
2728 || ASSOC_INPROG_PHY(pi)
2729 || pi->carrier_suppr_disable
2730 || pi->disable_percal))
2731 wlc_lcnphy_calib_modes(pi,
2732 PHY_PERICAL_WATCHDOG);
2737 void wlc_phy_BSSinit(struct brcms_phy_pub *pih, bool bonlyap, int rssi)
2739 struct brcms_phy *pi = (struct brcms_phy *) pih;
2743 for (i = 0; i < MA_WINDOW_SZ; i++)
2744 pi->sh->phy_noise_window[i] = (s8) (rssi & 0xff);
2746 for (i = 0; i < MA_WINDOW_SZ; i++)
2747 pi->sh->phy_noise_window[i] =
2748 PHY_NOISE_FIXED_VAL_LCNPHY;
2750 pi->sh->phy_noise_index = 0;
2752 for (i = 0; i < PHY_NOISE_WINDOW_SZ; i++) {
2753 for (k = WL_ANT_IDX_1; k < WL_ANT_RX_MAX; k++)
2754 pi->nphy_noise_win[k][i] = PHY_NOISE_FIXED_VAL_NPHY;
2756 pi->nphy_noise_index = 0;
2760 wlc_phy_papd_decode_epsilon(u32 epsilon, s32 *eps_real, s32 *eps_imag)
2762 *eps_imag = (epsilon >> 13);
2763 if (*eps_imag > 0xfff)
2764 *eps_imag -= 0x2000;
2766 *eps_real = (epsilon & 0x1fff);
2767 if (*eps_real > 0xfff)
2768 *eps_real -= 0x2000;
2771 void wlc_phy_cal_perical_mphase_reset(struct brcms_phy *pi)
2773 wlapi_del_timer(pi->sh->physhim, pi->phycal_timer);
2775 pi->cal_type_override = PHY_PERICAL_AUTO;
2776 pi->mphase_cal_phase_id = MPHASE_CAL_STATE_IDLE;
2777 pi->mphase_txcal_cmdidx = 0;
2781 wlc_phy_cal_perical_mphase_schedule(struct brcms_phy *pi, uint delay)
2784 if ((pi->nphy_perical != PHY_PERICAL_MPHASE) &&
2785 (pi->nphy_perical != PHY_PERICAL_MANUAL))
2788 wlapi_del_timer(pi->sh->physhim, pi->phycal_timer);
2790 pi->mphase_cal_phase_id = MPHASE_CAL_STATE_INIT;
2791 wlapi_add_timer(pi->sh->physhim, pi->phycal_timer, delay, 0);
2794 void wlc_phy_cal_perical(struct brcms_phy_pub *pih, u8 reason)
2796 s16 nphy_currtemp = 0;
2798 bool do_periodic_cal = true;
2799 struct brcms_phy *pi = (struct brcms_phy *) pih;
2804 if ((pi->nphy_perical == PHY_PERICAL_DISABLE) ||
2805 (pi->nphy_perical == PHY_PERICAL_MANUAL))
2809 case PHY_PERICAL_DRIVERUP:
2812 case PHY_PERICAL_PHYINIT:
2813 if (pi->nphy_perical == PHY_PERICAL_MPHASE) {
2814 if (PHY_PERICAL_MPHASE_PENDING(pi))
2815 wlc_phy_cal_perical_mphase_reset(pi);
2817 wlc_phy_cal_perical_mphase_schedule(
2819 PHY_PERICAL_INIT_DELAY);
2823 case PHY_PERICAL_JOIN_BSS:
2824 case PHY_PERICAL_START_IBSS:
2825 case PHY_PERICAL_UP_BSS:
2826 if ((pi->nphy_perical == PHY_PERICAL_MPHASE) &&
2827 PHY_PERICAL_MPHASE_PENDING(pi))
2828 wlc_phy_cal_perical_mphase_reset(pi);
2830 pi->first_cal_after_assoc = true;
2832 pi->cal_type_override = PHY_PERICAL_FULL;
2834 if (pi->phycal_tempdelta)
2835 pi->nphy_lastcal_temp = wlc_phy_tempsense_nphy(pi);
2837 wlc_phy_cal_perical_nphy_run(pi, PHY_PERICAL_FULL);
2840 case PHY_PERICAL_WATCHDOG:
2841 if (pi->phycal_tempdelta) {
2842 nphy_currtemp = wlc_phy_tempsense_nphy(pi);
2844 (nphy_currtemp > pi->nphy_lastcal_temp) ?
2845 nphy_currtemp - pi->nphy_lastcal_temp :
2846 pi->nphy_lastcal_temp - nphy_currtemp;
2848 if ((delta_temp < (s16) pi->phycal_tempdelta) &&
2849 (pi->nphy_txiqlocal_chanspec ==
2850 pi->radio_chanspec))
2851 do_periodic_cal = false;
2853 pi->nphy_lastcal_temp = nphy_currtemp;
2856 if (do_periodic_cal) {
2857 if (pi->nphy_perical == PHY_PERICAL_MPHASE) {
2858 if (!PHY_PERICAL_MPHASE_PENDING(pi))
2859 wlc_phy_cal_perical_mphase_schedule(
2861 PHY_PERICAL_WDOG_DELAY);
2862 } else if (pi->nphy_perical == PHY_PERICAL_SPHASE)
2863 wlc_phy_cal_perical_nphy_run(pi,
2872 void wlc_phy_cal_perical_mphase_restart(struct brcms_phy *pi)
2874 pi->mphase_cal_phase_id = MPHASE_CAL_STATE_INIT;
2875 pi->mphase_txcal_cmdidx = 0;
2878 u8 wlc_phy_nbits(s32 value)
2883 abs_val = abs(value);
2884 while ((abs_val >> nbits) > 0)
2890 void wlc_phy_stf_chain_init(struct brcms_phy_pub *pih, u8 txchain, u8 rxchain)
2892 struct brcms_phy *pi = (struct brcms_phy *) pih;
2894 pi->sh->hw_phytxchain = txchain;
2895 pi->sh->hw_phyrxchain = rxchain;
2896 pi->sh->phytxchain = txchain;
2897 pi->sh->phyrxchain = rxchain;
2898 pi->pubpi.phy_corenum = (u8) brcmu_bitcount((u8 *)&pi->sh->phyrxchain,
2902 void wlc_phy_stf_chain_set(struct brcms_phy_pub *pih, u8 txchain, u8 rxchain)
2904 struct brcms_phy *pi = (struct brcms_phy *) pih;
2906 pi->sh->phytxchain = txchain;
2909 wlc_phy_rxcore_setstate_nphy(pih, rxchain);
2911 pi->pubpi.phy_corenum = (u8) brcmu_bitcount((u8 *)&pi->sh->phyrxchain,
2915 void wlc_phy_stf_chain_get(struct brcms_phy_pub *pih, u8 *txchain, u8 *rxchain)
2917 struct brcms_phy *pi = (struct brcms_phy *) pih;
2919 *txchain = pi->sh->phytxchain;
2920 *rxchain = pi->sh->phyrxchain;
2923 u8 wlc_phy_stf_chain_active_get(struct brcms_phy_pub *pih)
2927 struct brcms_phy *pi = (struct brcms_phy *) pih;
2929 active_bitmap = (pi->phy_txcore_heatedup) ? 0x31 : 0x33;
2931 if (!pi->watchdog_override)
2932 return active_bitmap;
2934 if (NREV_GE(pi->pubpi.phy_rev, 6)) {
2935 wlapi_suspend_mac_and_wait(pi->sh->physhim);
2936 nphy_currtemp = wlc_phy_tempsense_nphy(pi);
2937 wlapi_enable_mac(pi->sh->physhim);
2939 if (!pi->phy_txcore_heatedup) {
2940 if (nphy_currtemp >= pi->phy_txcore_disable_temp) {
2941 active_bitmap &= 0xFD;
2942 pi->phy_txcore_heatedup = true;
2945 if (nphy_currtemp <= pi->phy_txcore_enable_temp) {
2946 active_bitmap |= 0x2;
2947 pi->phy_txcore_heatedup = false;
2952 return active_bitmap;
2955 s8 wlc_phy_stf_ssmode_get(struct brcms_phy_pub *pih, u16 chanspec)
2957 struct brcms_phy *pi = (struct brcms_phy *) pih;
2958 u8 siso_mcs_id, cdd_mcs_id;
2961 (CHSPEC_IS40(chanspec)) ? TXP_FIRST_MCS_40_SISO :
2962 TXP_FIRST_MCS_20_SISO;
2964 (CHSPEC_IS40(chanspec)) ? TXP_FIRST_MCS_40_CDD :
2965 TXP_FIRST_MCS_20_CDD;
2967 if (pi->tx_power_target[siso_mcs_id] >
2968 (pi->tx_power_target[cdd_mcs_id] + 12))
2969 return PHY_TXC1_MODE_SISO;
2971 return PHY_TXC1_MODE_CDD;
2974 const u8 *wlc_phy_get_ofdm_rate_lookup(void)
2976 return ofdm_rate_lookup;
2979 void wlc_lcnphy_epa_switch(struct brcms_phy *pi, bool mode)
2981 if ((pi->sh->chip == BCM4313_CHIP_ID) &&
2982 (pi->sh->boardflags & BFL_FEM)) {
2985 txant = wlapi_bmac_get_txant(pi->sh->physhim);
2987 mod_phy_reg(pi, 0x44d, (0x1 << 2), (1) << 2);
2989 mod_phy_reg(pi, 0x44c, (0x1 << 2), (1) << 2);
2992 ai_corereg(pi->sh->sih, SI_CC_IDX,
2993 offsetof(struct chipcregs, gpiocontrol),
2995 ai_corereg(pi->sh->sih, SI_CC_IDX,
2996 offsetof(struct chipcregs, gpioout), 0x40,
2998 ai_corereg(pi->sh->sih, SI_CC_IDX,
2999 offsetof(struct chipcregs, gpioouten), 0x40,
3002 mod_phy_reg(pi, 0x44c, (0x1 << 2), (0) << 2);
3004 mod_phy_reg(pi, 0x44d, (0x1 << 2), (0) << 2);
3006 ai_corereg(pi->sh->sih, SI_CC_IDX,
3007 offsetof(struct chipcregs, gpioout), 0x40,
3009 ai_corereg(pi->sh->sih, SI_CC_IDX,
3010 offsetof(struct chipcregs, gpioouten), 0x40,
3012 ai_corereg(pi->sh->sih, SI_CC_IDX,
3013 offsetof(struct chipcregs, gpiocontrol),
3019 void wlc_phy_ldpc_override_set(struct brcms_phy_pub *ppi, bool ldpc)
3025 wlc_phy_get_pwrdet_offsets(struct brcms_phy *pi, s8 *cckoffset, s8 *ofdmoffset)
3031 s8 wlc_phy_upd_rssi_offset(struct brcms_phy *pi, s8 rssi, u16 chanspec)
3037 bool wlc_phy_txpower_ipa_ison(struct brcms_phy_pub *ppi)
3039 struct brcms_phy *pi = (struct brcms_phy *) ppi;
3042 return wlc_phy_n_txpower_ipa_ison(pi);