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.
17 #include <linux/delay.h>
19 #include <brcm_hw_ids.h>
20 #include <chipcommon.h>
26 #include "phy_radio.h"
30 u32 phyhal_msg_level
= PHYHAL_ERROR
;
32 struct chan_info_basic
{
37 static struct chan_info_basic chan_info_all
[] = {
96 u16 ltrn_list
[PHY_LTRN_LIST_LEN
] = {
97 0x18f9, 0x0d01, 0x00e4, 0xdef4, 0x06f1, 0x0ffc,
98 0xfa27, 0x1dff, 0x10f0, 0x0918, 0xf20a, 0xe010,
99 0x1417, 0x1104, 0xf114, 0xf2fa, 0xf7db, 0xe2fc,
100 0xe1fb, 0x13ee, 0xff0d, 0xe91c, 0x171a, 0x0318,
101 0xda00, 0x03e8, 0x17e6, 0xe9e4, 0xfff3, 0x1312,
102 0xe105, 0xe204, 0xf725, 0xf206, 0xf1ec, 0x11fc,
103 0x14e9, 0xe0f0, 0xf2f6, 0x09e8, 0x1010, 0x1d01,
104 0xfad9, 0x0f04, 0x060f, 0xde0c, 0x001c, 0x0dff,
105 0x1807, 0xf61a, 0xe40e, 0x0f16, 0x05f9, 0x18ec,
106 0x0a1b, 0xff1e, 0x2600, 0xffe2, 0x0ae5, 0x1814,
107 0x0507, 0x0fea, 0xe4f2, 0xf6e6
110 const u8 ofdm_rate_lookup
[] = {
122 #define PHY_WREG_LIMIT 24
124 static void wlc_set_phy_uninitted(struct brcms_phy
*pi
);
125 static u32
wlc_phy_get_radio_ver(struct brcms_phy
*pi
);
126 static void wlc_phy_timercb_phycal(struct brcms_phy
*pi
);
128 static bool wlc_phy_noise_calc_phy(struct brcms_phy
*pi
, u32
*cmplx_pwr
,
131 static void wlc_phy_cal_perical_mphase_schedule(struct brcms_phy
*pi
,
134 static void wlc_phy_noise_cb(struct brcms_phy
*pi
, u8 channel
, s8 noise_dbm
);
135 static void wlc_phy_noise_sample_request(struct brcms_phy_pub
*pih
, u8 reason
,
138 static void wlc_phy_txpower_reg_limit_calc(struct brcms_phy
*pi
,
139 struct txpwr_limits
*tp
,
142 static bool wlc_phy_cal_txpower_recalc_sw(struct brcms_phy
*pi
);
144 static s8
wlc_user_txpwr_antport_to_rfport(struct brcms_phy
*pi
, uint chan
,
146 static void wlc_phy_upd_env_txpwr_rate_limits(struct brcms_phy
*pi
, u32 band
);
147 static s8
wlc_phy_env_measure_vbat(struct brcms_phy
*pi
);
148 static s8
wlc_phy_env_measure_temperature(struct brcms_phy
*pi
);
150 char *phy_getvar(struct brcms_phy
*pi
, const char *name
)
152 char *vars
= pi
->vars
;
163 for (s
= vars
; s
&& *s
;) {
164 if ((memcmp(s
, name
, len
) == 0) && (s
[len
] == '='))
174 int phy_getintvar(struct brcms_phy
*pi
, const char *name
)
179 val
= PHY_GETVAR(pi
, name
);
180 if (val
&& !kstrtoul(val
, 0, &res
))
186 void wlc_phyreg_enter(struct brcms_phy_pub
*pih
)
188 struct brcms_phy
*pi
= (struct brcms_phy
*) pih
;
189 wlapi_bmac_ucode_wake_override_phyreg_set(pi
->sh
->physhim
);
192 void wlc_phyreg_exit(struct brcms_phy_pub
*pih
)
194 struct brcms_phy
*pi
= (struct brcms_phy
*) pih
;
195 wlapi_bmac_ucode_wake_override_phyreg_clear(pi
->sh
->physhim
);
198 void wlc_radioreg_enter(struct brcms_phy_pub
*pih
)
200 struct brcms_phy
*pi
= (struct brcms_phy
*) pih
;
201 wlapi_bmac_mctrl(pi
->sh
->physhim
, MCTL_LOCK_RADIO
, MCTL_LOCK_RADIO
);
206 void wlc_radioreg_exit(struct brcms_phy_pub
*pih
)
208 struct brcms_phy
*pi
= (struct brcms_phy
*) pih
;
211 dummy
= R_REG(&pi
->regs
->phyversion
);
213 wlapi_bmac_mctrl(pi
->sh
->physhim
, MCTL_LOCK_RADIO
, 0);
216 u16
read_radio_reg(struct brcms_phy
*pi
, u16 addr
)
220 if ((addr
== RADIO_IDCODE
))
223 if (NORADIO_ENAB(pi
->pubpi
))
224 return NORADIO_IDCODE
& 0xffff;
226 switch (pi
->pubpi
.phy_type
) {
228 CASECHECK(PHYTYPE
, PHY_TYPE_N
);
229 if (NREV_GE(pi
->pubpi
.phy_rev
, 7))
230 addr
|= RADIO_2057_READ_OFF
;
232 addr
|= RADIO_2055_READ_OFF
;
236 CASECHECK(PHYTYPE
, PHY_TYPE_LCN
);
237 addr
|= RADIO_2064_READ_OFF
;
244 if ((D11REV_GE(pi
->sh
->corerev
, 24)) ||
245 (D11REV_IS(pi
->sh
->corerev
, 22)
246 && (pi
->pubpi
.phy_type
!= PHY_TYPE_SSN
))) {
247 W_REG_FLUSH(&pi
->regs
->radioregaddr
, addr
);
248 data
= R_REG(&pi
->regs
->radioregdata
);
250 W_REG_FLUSH(&pi
->regs
->phy4waddr
, addr
);
252 #ifdef __ARM_ARCH_4T__
253 __asm__(" .align 4 ");
255 data
= R_REG(&pi
->regs
->phy4wdatalo
);
257 data
= R_REG(&pi
->regs
->phy4wdatalo
);
266 void write_radio_reg(struct brcms_phy
*pi
, u16 addr
, u16 val
)
268 if (NORADIO_ENAB(pi
->pubpi
))
271 if ((D11REV_GE(pi
->sh
->corerev
, 24)) ||
272 (D11REV_IS(pi
->sh
->corerev
, 22)
273 && (pi
->pubpi
.phy_type
!= PHY_TYPE_SSN
))) {
275 W_REG_FLUSH(&pi
->regs
->radioregaddr
, addr
);
276 W_REG(&pi
->regs
->radioregdata
, val
);
278 W_REG_FLUSH(&pi
->regs
->phy4waddr
, addr
);
279 W_REG(&pi
->regs
->phy4wdatalo
, val
);
282 if (++pi
->phy_wreg
>= pi
->phy_wreg_limit
) {
283 (void)R_REG(&pi
->regs
->maccontrol
);
288 static u32
read_radio_id(struct brcms_phy
*pi
)
292 if (NORADIO_ENAB(pi
->pubpi
))
293 return NORADIO_IDCODE
;
295 if (D11REV_GE(pi
->sh
->corerev
, 24)) {
298 W_REG_FLUSH(&pi
->regs
->radioregaddr
, 0);
299 b0
= (u32
) R_REG(&pi
->regs
->radioregdata
);
300 W_REG_FLUSH(&pi
->regs
->radioregaddr
, 1);
301 b1
= (u32
) R_REG(&pi
->regs
->radioregdata
);
302 W_REG_FLUSH(&pi
->regs
->radioregaddr
, 2);
303 b2
= (u32
) R_REG(&pi
->regs
->radioregdata
);
305 id
= ((b0
& 0xf) << 28) | (((b2
<< 8) | b1
) << 12) | ((b0
>> 4)
308 W_REG_FLUSH(&pi
->regs
->phy4waddr
, RADIO_IDCODE
);
309 id
= (u32
) R_REG(&pi
->regs
->phy4wdatalo
);
310 id
|= (u32
) R_REG(&pi
->regs
->phy4wdatahi
) << 16;
316 void and_radio_reg(struct brcms_phy
*pi
, u16 addr
, u16 val
)
320 if (NORADIO_ENAB(pi
->pubpi
))
323 rval
= read_radio_reg(pi
, addr
);
324 write_radio_reg(pi
, addr
, (rval
& val
));
327 void or_radio_reg(struct brcms_phy
*pi
, u16 addr
, u16 val
)
331 if (NORADIO_ENAB(pi
->pubpi
))
334 rval
= read_radio_reg(pi
, addr
);
335 write_radio_reg(pi
, addr
, (rval
| val
));
338 void xor_radio_reg(struct brcms_phy
*pi
, u16 addr
, u16 mask
)
342 if (NORADIO_ENAB(pi
->pubpi
))
345 rval
= read_radio_reg(pi
, addr
);
346 write_radio_reg(pi
, addr
, (rval
^ mask
));
349 void mod_radio_reg(struct brcms_phy
*pi
, u16 addr
, u16 mask
, u16 val
)
353 if (NORADIO_ENAB(pi
->pubpi
))
356 rval
= read_radio_reg(pi
, addr
);
357 write_radio_reg(pi
, addr
, (rval
& ~mask
) | (val
& mask
));
360 void write_phy_channel_reg(struct brcms_phy
*pi
, uint val
)
362 W_REG(&pi
->regs
->phychannel
, val
);
365 u16
read_phy_reg(struct brcms_phy
*pi
, u16 addr
)
367 struct d11regs
*regs
;
371 W_REG_FLUSH(®s
->phyregaddr
, addr
);
374 return R_REG(®s
->phyregdata
);
377 void write_phy_reg(struct brcms_phy
*pi
, u16 addr
, u16 val
)
379 struct d11regs
*regs
;
384 W_REG_FLUSH(®s
->phyregaddr
, addr
);
385 W_REG(®s
->phyregdata
, val
);
387 (void)R_REG(®s
->phyregdata
);
389 W_REG((u32
*)(®s
->phyregaddr
),
391 if (++pi
->phy_wreg
>= pi
->phy_wreg_limit
) {
393 (void)R_REG(®s
->phyversion
);
398 void and_phy_reg(struct brcms_phy
*pi
, u16 addr
, u16 val
)
400 struct d11regs
*regs
;
404 W_REG_FLUSH(®s
->phyregaddr
, addr
);
406 W_REG(®s
->phyregdata
, (R_REG(®s
->phyregdata
) & val
));
410 void or_phy_reg(struct brcms_phy
*pi
, u16 addr
, u16 val
)
412 struct d11regs
*regs
;
416 W_REG_FLUSH(®s
->phyregaddr
, addr
);
418 W_REG(®s
->phyregdata
, (R_REG(®s
->phyregdata
) | val
));
422 void mod_phy_reg(struct brcms_phy
*pi
, u16 addr
, u16 mask
, u16 val
)
424 struct d11regs
*regs
;
428 W_REG_FLUSH(®s
->phyregaddr
, addr
);
430 W_REG(®s
->phyregdata
,
431 ((R_REG(®s
->phyregdata
) & ~mask
) | (val
& mask
)));
435 static void wlc_set_phy_uninitted(struct brcms_phy
*pi
)
439 pi
->initialized
= false;
442 pi
->nrssi_table_delta
= 0x7fffffff;
444 pi
->mintxbias
= 0xffff;
447 pi
->phy_spuravoid
= SPURAVOID_DISABLE
;
449 if (NREV_GE(pi
->pubpi
.phy_rev
, 3)
450 && NREV_LT(pi
->pubpi
.phy_rev
, 7))
451 pi
->phy_spuravoid
= SPURAVOID_AUTO
;
453 pi
->nphy_papd_skip
= 0;
454 pi
->nphy_papd_epsilon_offset
[0] = 0xf588;
455 pi
->nphy_papd_epsilon_offset
[1] = 0xf588;
456 pi
->nphy_txpwr_idx
[0] = 128;
457 pi
->nphy_txpwr_idx
[1] = 128;
458 pi
->nphy_txpwrindex
[0].index_internal
= 40;
459 pi
->nphy_txpwrindex
[1].index_internal
= 40;
462 pi
->phy_spuravoid
= SPURAVOID_AUTO
;
464 pi
->radiopwr
= 0xffff;
465 for (i
= 0; i
< STATIC_NUM_RF
; i
++) {
466 for (j
= 0; j
< STATIC_NUM_BB
; j
++)
467 pi
->stats_11b_txpower
[i
][j
] = -1;
471 struct shared_phy
*wlc_phy_shared_attach(struct shared_phy_params
*shp
)
473 struct shared_phy
*sh
;
475 sh
= kzalloc(sizeof(struct shared_phy
), GFP_ATOMIC
);
480 sh
->physhim
= shp
->physhim
;
481 sh
->unit
= shp
->unit
;
482 sh
->corerev
= shp
->corerev
;
486 sh
->chip
= shp
->chip
;
487 sh
->chiprev
= shp
->chiprev
;
488 sh
->chippkg
= shp
->chippkg
;
489 sh
->sromrev
= shp
->sromrev
;
490 sh
->boardtype
= shp
->boardtype
;
491 sh
->boardrev
= shp
->boardrev
;
492 sh
->boardvendor
= shp
->boardvendor
;
493 sh
->boardflags
= shp
->boardflags
;
494 sh
->boardflags2
= shp
->boardflags2
;
495 sh
->buscorerev
= shp
->buscorerev
;
497 sh
->fast_timer
= PHY_SW_TIMER_FAST
;
498 sh
->slow_timer
= PHY_SW_TIMER_SLOW
;
499 sh
->glacial_timer
= PHY_SW_TIMER_GLACIAL
;
501 sh
->rssi_mode
= RSSI_ANT_MERGE_MAX
;
506 struct brcms_phy_pub
*
507 wlc_phy_attach(struct shared_phy
*sh
, struct d11regs
*regs
, int bandtype
,
508 char *vars
, struct wiphy
*wiphy
)
510 struct brcms_phy
*pi
;
516 if (D11REV_IS(sh
->corerev
, 4))
517 sflags
= SISF_2G_PHY
| SISF_5G_PHY
;
519 sflags
= ai_core_sflags(sh
->sih
, 0, 0);
521 if (BAND_5G(bandtype
)) {
522 if ((sflags
& (SISF_5G_PHY
| SISF_DB_PHY
)) == 0)
527 if ((sflags
& SISF_DB_PHY
) && pi
) {
528 wlapi_bmac_corereset(pi
->sh
->physhim
, pi
->pubpi
.coreflags
);
530 return &pi
->pubpi_ro
;
533 pi
= kzalloc(sizeof(struct brcms_phy
), GFP_ATOMIC
);
539 pi
->phy_init_por
= true;
540 pi
->phy_wreg_limit
= PHY_WREG_LIMIT
;
544 pi
->txpwr_percent
= 100;
546 pi
->do_initcal
= true;
548 pi
->phycal_tempdelta
= 0;
550 if (BAND_2G(bandtype
) && (sflags
& SISF_2G_PHY
))
551 pi
->pubpi
.coreflags
= SICF_GMODE
;
553 wlapi_bmac_corereset(pi
->sh
->physhim
, pi
->pubpi
.coreflags
);
554 phyversion
= R_REG(&pi
->regs
->phyversion
);
556 pi
->pubpi
.phy_type
= PHY_TYPE(phyversion
);
557 pi
->pubpi
.phy_rev
= phyversion
& PV_PV_MASK
;
559 if (pi
->pubpi
.phy_type
== PHY_TYPE_LCNXN
) {
560 pi
->pubpi
.phy_type
= PHY_TYPE_N
;
561 pi
->pubpi
.phy_rev
+= LCNXN_BASEREV
;
563 pi
->pubpi
.phy_corenum
= PHY_CORE_NUM_2
;
564 pi
->pubpi
.ana_rev
= (phyversion
& PV_AV_MASK
) >> PV_AV_SHIFT
;
566 if (!VALID_PHYTYPE(pi
->pubpi
.phy_type
))
569 if (BAND_5G(bandtype
)) {
572 } else if (!ISNPHY(pi
) && !ISLCNPHY(pi
)) {
576 wlc_phy_anacore((struct brcms_phy_pub
*) pi
, ON
);
578 idcode
= wlc_phy_get_radio_ver(pi
);
580 (idcode
& IDCODE_ID_MASK
) >> IDCODE_ID_SHIFT
;
582 (idcode
& IDCODE_REV_MASK
) >> IDCODE_REV_SHIFT
;
584 (idcode
& IDCODE_VER_MASK
) >> IDCODE_VER_SHIFT
;
585 if (!VALID_RADIO(pi
, pi
->pubpi
.radioid
))
588 wlc_phy_switch_radio((struct brcms_phy_pub
*) pi
, OFF
);
590 wlc_set_phy_uninitted(pi
);
592 pi
->bw
= WL_CHANSPEC_BW_20
;
594 BAND_2G(bandtype
) ? CH20MHZ_CHSPEC(1) : CH20MHZ_CHSPEC(36);
596 pi
->rxiq_samps
= PHY_NOISE_SAMPLE_LOG_NUM_NPHY
;
597 pi
->rxiq_antsel
= ANT_RX_DIV_DEF
;
599 pi
->watchdog_override
= true;
601 pi
->cal_type_override
= PHY_PERICAL_AUTO
;
603 pi
->nphy_saved_noisevars
.bufcount
= 0;
606 pi
->min_txpower
= PHY_TXPWR_MIN_NPHY
;
608 pi
->min_txpower
= PHY_TXPWR_MIN
;
610 pi
->sh
->phyrxchain
= 0x3;
612 pi
->rx2tx_biasentry
= -1;
614 pi
->phy_txcore_disable_temp
= PHY_CHAIN_TX_DISABLE_TEMP
;
615 pi
->phy_txcore_enable_temp
=
616 PHY_CHAIN_TX_DISABLE_TEMP
- PHY_HYSTERESIS_DELTATEMP
;
617 pi
->phy_tempsense_offset
= 0;
618 pi
->phy_txcore_heatedup
= false;
620 pi
->nphy_lastcal_temp
= -50;
622 pi
->phynoise_polling
= true;
623 if (ISNPHY(pi
) || ISLCNPHY(pi
))
624 pi
->phynoise_polling
= false;
626 for (i
= 0; i
< TXP_NUM_RATES
; i
++) {
627 pi
->txpwr_limit
[i
] = BRCMS_TXPWR_MAX
;
628 pi
->txpwr_env_limit
[i
] = BRCMS_TXPWR_MAX
;
629 pi
->tx_user_target
[i
] = BRCMS_TXPWR_MAX
;
632 pi
->radiopwr_override
= RADIOPWR_OVERRIDE_DEF
;
634 pi
->user_txpwr_at_rfport
= false;
638 pi
->phycal_timer
= wlapi_init_timer(pi
->sh
->physhim
,
639 wlc_phy_timercb_phycal
,
641 if (!pi
->phycal_timer
)
644 if (!wlc_phy_attach_nphy(pi
))
647 } else if (ISLCNPHY(pi
)) {
648 if (!wlc_phy_attach_lcnphy(pi
))
654 pi
->next
= pi
->sh
->phy_head
;
657 pi
->vars
= (char *)&pi
->vars
;
659 memcpy(&pi
->pubpi_ro
, &pi
->pubpi
, sizeof(struct brcms_phy_pub
));
661 return &pi
->pubpi_ro
;
668 void wlc_phy_detach(struct brcms_phy_pub
*pih
)
670 struct brcms_phy
*pi
= (struct brcms_phy
*) pih
;
676 if (pi
->phycal_timer
) {
677 wlapi_free_timer(pi
->sh
->physhim
, pi
->phycal_timer
);
678 pi
->phycal_timer
= NULL
;
681 if (pi
->sh
->phy_head
== pi
)
682 pi
->sh
->phy_head
= pi
->next
;
683 else if (pi
->sh
->phy_head
->next
== pi
)
684 pi
->sh
->phy_head
->next
= NULL
;
686 if (pi
->pi_fptr
.detach
)
687 (pi
->pi_fptr
.detach
)(pi
);
694 wlc_phy_get_phyversion(struct brcms_phy_pub
*pih
, u16
*phytype
, u16
*phyrev
,
695 u16
*radioid
, u16
*radiover
)
697 struct brcms_phy
*pi
= (struct brcms_phy
*) pih
;
698 *phytype
= (u16
) pi
->pubpi
.phy_type
;
699 *phyrev
= (u16
) pi
->pubpi
.phy_rev
;
700 *radioid
= pi
->pubpi
.radioid
;
701 *radiover
= pi
->pubpi
.radiorev
;
706 bool wlc_phy_get_encore(struct brcms_phy_pub
*pih
)
708 struct brcms_phy
*pi
= (struct brcms_phy
*) pih
;
709 return pi
->pubpi
.abgphy_encore
;
712 u32
wlc_phy_get_coreflags(struct brcms_phy_pub
*pih
)
714 struct brcms_phy
*pi
= (struct brcms_phy
*) pih
;
715 return pi
->pubpi
.coreflags
;
718 static void wlc_phy_timercb_phycal(struct brcms_phy
*pi
)
722 if (PHY_PERICAL_MPHASE_PENDING(pi
)) {
724 wlc_phy_cal_perical_mphase_reset(pi
);
728 if (SCAN_RM_IN_PROGRESS(pi
) || PLT_INPROG_PHY(pi
)) {
731 wlc_phy_cal_perical_mphase_restart(pi
);
733 wlc_phy_cal_perical_nphy_run(pi
, PHY_PERICAL_AUTO
);
734 wlapi_add_timer(pi
->sh
->physhim
, pi
->phycal_timer
, delay
, 0);
740 void wlc_phy_anacore(struct brcms_phy_pub
*pih
, bool on
)
742 struct brcms_phy
*pi
= (struct brcms_phy
*) pih
;
746 if (NREV_GE(pi
->pubpi
.phy_rev
, 3)) {
747 write_phy_reg(pi
, 0xa6, 0x0d);
748 write_phy_reg(pi
, 0x8f, 0x0);
749 write_phy_reg(pi
, 0xa7, 0x0d);
750 write_phy_reg(pi
, 0xa5, 0x0);
752 write_phy_reg(pi
, 0xa5, 0x0);
755 if (NREV_GE(pi
->pubpi
.phy_rev
, 3)) {
756 write_phy_reg(pi
, 0x8f, 0x07ff);
757 write_phy_reg(pi
, 0xa6, 0x0fd);
758 write_phy_reg(pi
, 0xa5, 0x07ff);
759 write_phy_reg(pi
, 0xa7, 0x0fd);
761 write_phy_reg(pi
, 0xa5, 0x7fff);
764 } else if (ISLCNPHY(pi
)) {
766 and_phy_reg(pi
, 0x43b,
767 ~((0x1 << 0) | (0x1 << 1) | (0x1 << 2)));
769 or_phy_reg(pi
, 0x43c,
770 (0x1 << 0) | (0x1 << 1) | (0x1 << 2));
771 or_phy_reg(pi
, 0x43b,
772 (0x1 << 0) | (0x1 << 1) | (0x1 << 2));
777 u32
wlc_phy_clk_bwbits(struct brcms_phy_pub
*pih
)
779 struct brcms_phy
*pi
= (struct brcms_phy
*) pih
;
781 u32 phy_bw_clkbits
= 0;
783 if (pi
&& (ISNPHY(pi
) || ISLCNPHY(pi
))) {
785 case WL_CHANSPEC_BW_10
:
786 phy_bw_clkbits
= SICF_BW10
;
788 case WL_CHANSPEC_BW_20
:
789 phy_bw_clkbits
= SICF_BW20
;
791 case WL_CHANSPEC_BW_40
:
792 phy_bw_clkbits
= SICF_BW40
;
799 return phy_bw_clkbits
;
802 void wlc_phy_por_inform(struct brcms_phy_pub
*ppi
)
804 struct brcms_phy
*pi
= (struct brcms_phy
*) ppi
;
806 pi
->phy_init_por
= true;
809 void wlc_phy_edcrs_lock(struct brcms_phy_pub
*pih
, bool lock
)
811 struct brcms_phy
*pi
= (struct brcms_phy
*) pih
;
813 pi
->edcrs_threshold_lock
= lock
;
815 write_phy_reg(pi
, 0x22c, 0x46b);
816 write_phy_reg(pi
, 0x22d, 0x46b);
817 write_phy_reg(pi
, 0x22e, 0x3c0);
818 write_phy_reg(pi
, 0x22f, 0x3c0);
821 void wlc_phy_initcal_enable(struct brcms_phy_pub
*pih
, bool initcal
)
823 struct brcms_phy
*pi
= (struct brcms_phy
*) pih
;
825 pi
->do_initcal
= initcal
;
828 void wlc_phy_hw_clk_state_upd(struct brcms_phy_pub
*pih
, bool newstate
)
830 struct brcms_phy
*pi
= (struct brcms_phy
*) pih
;
835 pi
->sh
->clk
= newstate
;
838 void wlc_phy_hw_state_upd(struct brcms_phy_pub
*pih
, bool newstate
)
840 struct brcms_phy
*pi
= (struct brcms_phy
*) pih
;
845 pi
->sh
->up
= newstate
;
848 void wlc_phy_init(struct brcms_phy_pub
*pih
, u16 chanspec
)
851 void (*phy_init
)(struct brcms_phy
*) = NULL
;
852 struct brcms_phy
*pi
= (struct brcms_phy
*) pih
;
854 if (pi
->init_in_progress
)
857 pi
->init_in_progress
= true;
859 pi
->radio_chanspec
= chanspec
;
861 mc
= R_REG(&pi
->regs
->maccontrol
);
862 if (WARN(mc
& MCTL_EN_MAC
, "HW error MAC running on init"))
865 if (!(pi
->measure_hold
& PHY_HOLD_FOR_SCAN
))
866 pi
->measure_hold
|= PHY_HOLD_FOR_NOT_ASSOC
;
868 if (WARN(!(ai_core_sflags(pi
->sh
->sih
, 0, 0) & SISF_FCLKA
),
869 "HW error SISF_FCLKA\n"))
872 phy_init
= pi
->pi_fptr
.init
;
874 if (phy_init
== NULL
)
877 wlc_phy_anacore(pih
, ON
);
879 if (CHSPEC_BW(pi
->radio_chanspec
) != pi
->bw
)
880 wlapi_bmac_bw_set(pi
->sh
->physhim
,
881 CHSPEC_BW(pi
->radio_chanspec
));
883 pi
->nphy_gain_boost
= true;
885 wlc_phy_switch_radio((struct brcms_phy_pub
*) pi
, ON
);
889 pi
->phy_init_por
= false;
891 if (D11REV_IS(pi
->sh
->corerev
, 11) || D11REV_IS(pi
->sh
->corerev
, 12))
892 wlc_phy_do_dummy_tx(pi
, true, OFF
);
895 wlc_phy_txpower_update_shm(pi
);
897 wlc_phy_ant_rxdiv_set((struct brcms_phy_pub
*) pi
, pi
->sh
->rx_antdiv
);
899 pi
->init_in_progress
= false;
902 void wlc_phy_cal_init(struct brcms_phy_pub
*pih
)
904 struct brcms_phy
*pi
= (struct brcms_phy
*) pih
;
905 void (*cal_init
)(struct brcms_phy
*) = NULL
;
907 if (WARN((R_REG(&pi
->regs
->maccontrol
) & MCTL_EN_MAC
) != 0,
908 "HW error: MAC enabled during phy cal\n"))
911 if (!pi
->initialized
) {
912 cal_init
= pi
->pi_fptr
.calinit
;
916 pi
->initialized
= true;
920 int wlc_phy_down(struct brcms_phy_pub
*pih
)
922 struct brcms_phy
*pi
= (struct brcms_phy
*) pih
;
926 && !wlapi_del_timer(pi
->sh
->physhim
, pi
->phycal_timer
))
929 pi
->nphy_iqcal_chanspec_2G
= 0;
930 pi
->nphy_iqcal_chanspec_5G
= 0;
935 static u32
wlc_phy_get_radio_ver(struct brcms_phy
*pi
)
939 ver
= read_radio_id(pi
);
945 wlc_phy_table_addr(struct brcms_phy
*pi
, uint tbl_id
, uint tbl_offset
,
946 u16 tblAddr
, u16 tblDataHi
, u16 tblDataLo
)
948 write_phy_reg(pi
, tblAddr
, (tbl_id
<< 10) | tbl_offset
);
950 pi
->tbl_data_hi
= tblDataHi
;
951 pi
->tbl_data_lo
= tblDataLo
;
953 if (pi
->sh
->chip
== BCM43224_CHIP_ID
&&
954 pi
->sh
->chiprev
== 1) {
955 pi
->tbl_addr
= tblAddr
;
956 pi
->tbl_save_id
= tbl_id
;
957 pi
->tbl_save_offset
= tbl_offset
;
961 void wlc_phy_table_data_write(struct brcms_phy
*pi
, uint width
, u32 val
)
963 if ((pi
->sh
->chip
== BCM43224_CHIP_ID
) &&
964 (pi
->sh
->chiprev
== 1) &&
965 (pi
->tbl_save_id
== NPHY_TBL_ID_ANTSWCTRLLUT
)) {
966 read_phy_reg(pi
, pi
->tbl_data_lo
);
968 write_phy_reg(pi
, pi
->tbl_addr
,
969 (pi
->tbl_save_id
<< 10) | pi
->tbl_save_offset
);
970 pi
->tbl_save_offset
++;
974 write_phy_reg(pi
, pi
->tbl_data_hi
, (u16
) (val
>> 16));
975 write_phy_reg(pi
, pi
->tbl_data_lo
, (u16
) val
);
977 write_phy_reg(pi
, pi
->tbl_data_lo
, (u16
) val
);
982 wlc_phy_write_table(struct brcms_phy
*pi
, const struct phytbl_info
*ptbl_info
,
983 u16 tblAddr
, u16 tblDataHi
, u16 tblDataLo
)
986 uint tbl_id
= ptbl_info
->tbl_id
;
987 uint tbl_offset
= ptbl_info
->tbl_offset
;
988 uint tbl_width
= ptbl_info
->tbl_width
;
989 const u8
*ptbl_8b
= (const u8
*)ptbl_info
->tbl_ptr
;
990 const u16
*ptbl_16b
= (const u16
*)ptbl_info
->tbl_ptr
;
991 const u32
*ptbl_32b
= (const u32
*)ptbl_info
->tbl_ptr
;
993 write_phy_reg(pi
, tblAddr
, (tbl_id
<< 10) | tbl_offset
);
995 for (idx
= 0; idx
< ptbl_info
->tbl_len
; idx
++) {
997 if ((pi
->sh
->chip
== BCM43224_CHIP_ID
) &&
998 (pi
->sh
->chiprev
== 1) &&
999 (tbl_id
== NPHY_TBL_ID_ANTSWCTRLLUT
)) {
1000 read_phy_reg(pi
, tblDataLo
);
1002 write_phy_reg(pi
, tblAddr
,
1003 (tbl_id
<< 10) | (tbl_offset
+ idx
));
1006 if (tbl_width
== 32) {
1007 write_phy_reg(pi
, tblDataHi
,
1008 (u16
) (ptbl_32b
[idx
] >> 16));
1009 write_phy_reg(pi
, tblDataLo
, (u16
) ptbl_32b
[idx
]);
1010 } else if (tbl_width
== 16) {
1011 write_phy_reg(pi
, tblDataLo
, ptbl_16b
[idx
]);
1013 write_phy_reg(pi
, tblDataLo
, ptbl_8b
[idx
]);
1019 wlc_phy_read_table(struct brcms_phy
*pi
, const struct phytbl_info
*ptbl_info
,
1020 u16 tblAddr
, u16 tblDataHi
, u16 tblDataLo
)
1023 uint tbl_id
= ptbl_info
->tbl_id
;
1024 uint tbl_offset
= ptbl_info
->tbl_offset
;
1025 uint tbl_width
= ptbl_info
->tbl_width
;
1026 u8
*ptbl_8b
= (u8
*)ptbl_info
->tbl_ptr
;
1027 u16
*ptbl_16b
= (u16
*)ptbl_info
->tbl_ptr
;
1028 u32
*ptbl_32b
= (u32
*)ptbl_info
->tbl_ptr
;
1030 write_phy_reg(pi
, tblAddr
, (tbl_id
<< 10) | tbl_offset
);
1032 for (idx
= 0; idx
< ptbl_info
->tbl_len
; idx
++) {
1034 if ((pi
->sh
->chip
== BCM43224_CHIP_ID
) &&
1035 (pi
->sh
->chiprev
== 1)) {
1036 (void)read_phy_reg(pi
, tblDataLo
);
1038 write_phy_reg(pi
, tblAddr
,
1039 (tbl_id
<< 10) | (tbl_offset
+ idx
));
1042 if (tbl_width
== 32) {
1043 ptbl_32b
[idx
] = read_phy_reg(pi
, tblDataLo
);
1044 ptbl_32b
[idx
] |= (read_phy_reg(pi
, tblDataHi
) << 16);
1045 } else if (tbl_width
== 16) {
1046 ptbl_16b
[idx
] = read_phy_reg(pi
, tblDataLo
);
1048 ptbl_8b
[idx
] = (u8
) read_phy_reg(pi
, tblDataLo
);
1054 wlc_phy_init_radio_regs_allbands(struct brcms_phy
*pi
,
1055 struct radio_20xx_regs
*radioregs
)
1060 if (radioregs
[i
].do_init
)
1061 write_radio_reg(pi
, radioregs
[i
].address
,
1062 (u16
) radioregs
[i
].init
);
1065 } while (radioregs
[i
].address
!= 0xffff);
1071 wlc_phy_init_radio_regs(struct brcms_phy
*pi
, struct radio_regs
*radioregs
,
1078 if (CHSPEC_IS5G(pi
->radio_chanspec
)) {
1079 if (radioregs
[i
].do_init_a
) {
1082 address
| core_offset
,
1083 (u16
) radioregs
[i
].init_a
);
1084 if (ISNPHY(pi
) && (++count
% 4 == 0))
1085 BRCMS_PHY_WAR_PR51571(pi
);
1088 if (radioregs
[i
].do_init_g
) {
1091 address
| core_offset
,
1092 (u16
) radioregs
[i
].init_g
);
1093 if (ISNPHY(pi
) && (++count
% 4 == 0))
1094 BRCMS_PHY_WAR_PR51571(pi
);
1099 } while (radioregs
[i
].address
!= 0xffff);
1104 void wlc_phy_do_dummy_tx(struct brcms_phy
*pi
, bool ofdm
, bool pa_on
)
1106 #define DUMMY_PKT_LEN 20
1107 struct d11regs
*regs
= pi
->regs
;
1109 u8 ofdmpkt
[DUMMY_PKT_LEN
] = {
1110 0xcc, 0x01, 0x02, 0x00, 0x00, 0x00, 0xd4, 0x00, 0x00, 0x00,
1111 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00
1113 u8 cckpkt
[DUMMY_PKT_LEN
] = {
1114 0x6e, 0x84, 0x0b, 0x00, 0x00, 0x00, 0xd4, 0x00, 0x00, 0x00,
1115 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00
1119 dummypkt
= (u32
*) (ofdm
? ofdmpkt
: cckpkt
);
1120 wlapi_bmac_write_template_ram(pi
->sh
->physhim
, 0, DUMMY_PKT_LEN
,
1123 W_REG(®s
->xmtsel
, 0);
1125 if (D11REV_GE(pi
->sh
->corerev
, 11))
1126 W_REG(®s
->wepctl
, 0x100);
1128 W_REG(®s
->wepctl
, 0);
1130 W_REG(®s
->txe_phyctl
, (ofdm
? 1 : 0) | PHY_TXC_ANT_0
);
1131 if (ISNPHY(pi
) || ISLCNPHY(pi
))
1132 W_REG(®s
->txe_phyctl1
, 0x1A02);
1134 W_REG(®s
->txe_wm_0
, 0);
1135 W_REG(®s
->txe_wm_1
, 0);
1137 W_REG(®s
->xmttplatetxptr
, 0);
1138 W_REG(®s
->xmttxcnt
, DUMMY_PKT_LEN
);
1140 W_REG(®s
->xmtsel
, ((8 << 8) | (1 << 5) | (1 << 2) | 2));
1142 W_REG(®s
->txe_ctl
, 0);
1146 wlc_phy_pa_override_nphy(pi
, OFF
);
1149 if (ISNPHY(pi
) || ISLCNPHY(pi
))
1150 W_REG(®s
->txe_aux
, 0xD0);
1152 W_REG(®s
->txe_aux
, ((1 << 5) | (1 << 4)));
1154 (void)R_REG(®s
->txe_aux
);
1157 count
= ofdm
? 30 : 250;
1158 while ((i
++ < count
)
1159 && (R_REG(®s
->txe_status
) & (1 << 7)))
1165 && ((R_REG(®s
->txe_status
) & (1 << 10)) == 0))
1170 while ((i
++ < 10) && ((R_REG(®s
->ifsstat
) & (1 << 8))))
1175 wlc_phy_pa_override_nphy(pi
, ON
);
1179 void wlc_phy_hold_upd(struct brcms_phy_pub
*pih
, u32 id
, bool set
)
1181 struct brcms_phy
*pi
= (struct brcms_phy
*) pih
;
1184 mboolset(pi
->measure_hold
, id
);
1186 mboolclr(pi
->measure_hold
, id
);
1191 void wlc_phy_mute_upd(struct brcms_phy_pub
*pih
, bool mute
, u32 flags
)
1193 struct brcms_phy
*pi
= (struct brcms_phy
*) pih
;
1196 mboolset(pi
->measure_hold
, PHY_HOLD_FOR_MUTE
);
1198 mboolclr(pi
->measure_hold
, PHY_HOLD_FOR_MUTE
);
1200 if (!mute
&& (flags
& PHY_MUTE_FOR_PREISM
))
1201 pi
->nphy_perical_last
= pi
->sh
->now
- pi
->sh
->glacial_timer
;
1205 void wlc_phy_clear_tssi(struct brcms_phy_pub
*pih
)
1207 struct brcms_phy
*pi
= (struct brcms_phy
*) pih
;
1212 wlapi_bmac_write_shm(pi
->sh
->physhim
, M_B_TSSI_0
, NULL_TSSI_W
);
1213 wlapi_bmac_write_shm(pi
->sh
->physhim
, M_B_TSSI_1
, NULL_TSSI_W
);
1214 wlapi_bmac_write_shm(pi
->sh
->physhim
, M_G_TSSI_0
, NULL_TSSI_W
);
1215 wlapi_bmac_write_shm(pi
->sh
->physhim
, M_G_TSSI_1
, NULL_TSSI_W
);
1219 static bool wlc_phy_cal_txpower_recalc_sw(struct brcms_phy
*pi
)
1224 void wlc_phy_switch_radio(struct brcms_phy_pub
*pih
, bool on
)
1226 struct brcms_phy
*pi
= (struct brcms_phy
*) pih
;
1228 if (NORADIO_ENAB(pi
->pubpi
))
1234 mc
= R_REG(&pi
->regs
->maccontrol
);
1238 wlc_phy_switch_radio_nphy(pi
, on
);
1239 } else if (ISLCNPHY(pi
)) {
1241 and_phy_reg(pi
, 0x44c,
1244 (0x1 << 10) | (0x1 << 11) | (0x1 << 12)));
1245 and_phy_reg(pi
, 0x4b0, ~((0x1 << 3) | (0x1 << 11)));
1246 and_phy_reg(pi
, 0x4f9, ~(0x1 << 3));
1248 and_phy_reg(pi
, 0x44d,
1251 (0x1 << 12) | (0x1 << 13) | (0x1 << 14)));
1252 or_phy_reg(pi
, 0x44c,
1255 (0x1 << 10) | (0x1 << 11) | (0x1 << 12));
1257 and_phy_reg(pi
, 0x4b7, ~((0x7f << 8)));
1258 and_phy_reg(pi
, 0x4b1, ~((0x1 << 13)));
1259 or_phy_reg(pi
, 0x4b0, (0x1 << 3) | (0x1 << 11));
1260 and_phy_reg(pi
, 0x4fa, ~((0x1 << 3)));
1261 or_phy_reg(pi
, 0x4f9, (0x1 << 3));
1266 u16
wlc_phy_bw_state_get(struct brcms_phy_pub
*ppi
)
1268 struct brcms_phy
*pi
= (struct brcms_phy
*) ppi
;
1273 void wlc_phy_bw_state_set(struct brcms_phy_pub
*ppi
, u16 bw
)
1275 struct brcms_phy
*pi
= (struct brcms_phy
*) ppi
;
1280 void wlc_phy_chanspec_radio_set(struct brcms_phy_pub
*ppi
, u16 newch
)
1282 struct brcms_phy
*pi
= (struct brcms_phy
*) ppi
;
1283 pi
->radio_chanspec
= newch
;
1287 u16
wlc_phy_chanspec_get(struct brcms_phy_pub
*ppi
)
1289 struct brcms_phy
*pi
= (struct brcms_phy
*) ppi
;
1291 return pi
->radio_chanspec
;
1294 void wlc_phy_chanspec_set(struct brcms_phy_pub
*ppi
, u16 chanspec
)
1296 struct brcms_phy
*pi
= (struct brcms_phy
*) ppi
;
1298 void (*chanspec_set
)(struct brcms_phy
*, u16
) = NULL
;
1299 m_cur_channel
= CHSPEC_CHANNEL(chanspec
);
1300 if (CHSPEC_IS5G(chanspec
))
1301 m_cur_channel
|= D11_CURCHANNEL_5G
;
1302 if (CHSPEC_IS40(chanspec
))
1303 m_cur_channel
|= D11_CURCHANNEL_40
;
1304 wlapi_bmac_write_shm(pi
->sh
->physhim
, M_CURCHANNEL
, m_cur_channel
);
1306 chanspec_set
= pi
->pi_fptr
.chanset
;
1308 (*chanspec_set
)(pi
, chanspec
);
1312 int wlc_phy_chanspec_freq2bandrange_lpssn(uint freq
)
1317 range
= WL_CHAN_FREQ_RANGE_2G
;
1318 else if (freq
<= 5320)
1319 range
= WL_CHAN_FREQ_RANGE_5GL
;
1320 else if (freq
<= 5700)
1321 range
= WL_CHAN_FREQ_RANGE_5GM
;
1323 range
= WL_CHAN_FREQ_RANGE_5GH
;
1328 int wlc_phy_chanspec_bandrange_get(struct brcms_phy
*pi
, u16 chanspec
)
1331 uint channel
= CHSPEC_CHANNEL(chanspec
);
1332 uint freq
= wlc_phy_channel2freq(channel
);
1335 range
= wlc_phy_get_chan_freq_range_nphy(pi
, channel
);
1336 else if (ISLCNPHY(pi
))
1337 range
= wlc_phy_chanspec_freq2bandrange_lpssn(freq
);
1342 void wlc_phy_chanspec_ch14_widefilter_set(struct brcms_phy_pub
*ppi
,
1345 struct brcms_phy
*pi
= (struct brcms_phy
*) ppi
;
1347 pi
->channel_14_wide_filter
= wide_filter
;
1351 int wlc_phy_channel2freq(uint channel
)
1355 for (i
= 0; i
< ARRAY_SIZE(chan_info_all
); i
++)
1356 if (chan_info_all
[i
].chan
== channel
)
1357 return chan_info_all
[i
].freq
;
1362 wlc_phy_chanspec_band_validch(struct brcms_phy_pub
*ppi
, uint band
,
1363 struct brcms_chanvec
*channels
)
1365 struct brcms_phy
*pi
= (struct brcms_phy
*) ppi
;
1369 memset(channels
, 0, sizeof(struct brcms_chanvec
));
1371 for (i
= 0; i
< ARRAY_SIZE(chan_info_all
); i
++) {
1372 channel
= chan_info_all
[i
].chan
;
1374 if ((pi
->a_band_high_disable
) && (channel
>= FIRST_REF5_CHANNUM
)
1375 && (channel
<= LAST_REF5_CHANNUM
))
1378 if ((band
== BRCM_BAND_2G
&& channel
<= CH_MAX_2G_CHANNEL
) ||
1379 (band
== BRCM_BAND_5G
&& channel
> CH_MAX_2G_CHANNEL
))
1380 setbit(channels
->vec
, channel
);
1384 u16
wlc_phy_chanspec_band_firstch(struct brcms_phy_pub
*ppi
, uint band
)
1386 struct brcms_phy
*pi
= (struct brcms_phy
*) ppi
;
1391 for (i
= 0; i
< ARRAY_SIZE(chan_info_all
); i
++) {
1392 channel
= chan_info_all
[i
].chan
;
1394 if (ISNPHY(pi
) && IS40MHZ(pi
)) {
1397 for (j
= 0; j
< ARRAY_SIZE(chan_info_all
); j
++) {
1398 if (chan_info_all
[j
].chan
==
1399 channel
+ CH_10MHZ_APART
)
1403 if (j
== ARRAY_SIZE(chan_info_all
))
1406 channel
= UPPER_20_SB(channel
);
1407 chspec
= channel
| WL_CHANSPEC_BW_40
|
1408 WL_CHANSPEC_CTL_SB_LOWER
;
1409 if (band
== BRCM_BAND_2G
)
1410 chspec
|= WL_CHANSPEC_BAND_2G
;
1412 chspec
|= WL_CHANSPEC_BAND_5G
;
1414 chspec
= CH20MHZ_CHSPEC(channel
);
1416 if ((pi
->a_band_high_disable
) && (channel
>= FIRST_REF5_CHANNUM
)
1417 && (channel
<= LAST_REF5_CHANNUM
))
1420 if ((band
== BRCM_BAND_2G
&& channel
<= CH_MAX_2G_CHANNEL
) ||
1421 (band
== BRCM_BAND_5G
&& channel
> CH_MAX_2G_CHANNEL
))
1425 return (u16
) INVCHANSPEC
;
1428 int wlc_phy_txpower_get(struct brcms_phy_pub
*ppi
, uint
*qdbm
, bool *override
)
1430 struct brcms_phy
*pi
= (struct brcms_phy
*) ppi
;
1432 *qdbm
= pi
->tx_user_target
[0];
1433 if (override
!= NULL
)
1434 *override
= pi
->txpwroverride
;
1438 void wlc_phy_txpower_target_set(struct brcms_phy_pub
*ppi
,
1439 struct txpwr_limits
*txpwr
)
1441 bool mac_enabled
= false;
1442 struct brcms_phy
*pi
= (struct brcms_phy
*) ppi
;
1444 memcpy(&pi
->tx_user_target
[TXP_FIRST_CCK
],
1445 &txpwr
->cck
[0], BRCMS_NUM_RATES_CCK
);
1447 memcpy(&pi
->tx_user_target
[TXP_FIRST_OFDM
],
1448 &txpwr
->ofdm
[0], BRCMS_NUM_RATES_OFDM
);
1449 memcpy(&pi
->tx_user_target
[TXP_FIRST_OFDM_20_CDD
],
1450 &txpwr
->ofdm_cdd
[0], BRCMS_NUM_RATES_OFDM
);
1452 memcpy(&pi
->tx_user_target
[TXP_FIRST_OFDM_40_SISO
],
1453 &txpwr
->ofdm_40_siso
[0], BRCMS_NUM_RATES_OFDM
);
1454 memcpy(&pi
->tx_user_target
[TXP_FIRST_OFDM_40_CDD
],
1455 &txpwr
->ofdm_40_cdd
[0], BRCMS_NUM_RATES_OFDM
);
1457 memcpy(&pi
->tx_user_target
[TXP_FIRST_MCS_20_SISO
],
1458 &txpwr
->mcs_20_siso
[0], BRCMS_NUM_RATES_MCS_1_STREAM
);
1459 memcpy(&pi
->tx_user_target
[TXP_FIRST_MCS_20_CDD
],
1460 &txpwr
->mcs_20_cdd
[0], BRCMS_NUM_RATES_MCS_1_STREAM
);
1461 memcpy(&pi
->tx_user_target
[TXP_FIRST_MCS_20_STBC
],
1462 &txpwr
->mcs_20_stbc
[0], BRCMS_NUM_RATES_MCS_1_STREAM
);
1463 memcpy(&pi
->tx_user_target
[TXP_FIRST_MCS_20_SDM
],
1464 &txpwr
->mcs_20_mimo
[0], BRCMS_NUM_RATES_MCS_2_STREAM
);
1466 memcpy(&pi
->tx_user_target
[TXP_FIRST_MCS_40_SISO
],
1467 &txpwr
->mcs_40_siso
[0], BRCMS_NUM_RATES_MCS_1_STREAM
);
1468 memcpy(&pi
->tx_user_target
[TXP_FIRST_MCS_40_CDD
],
1469 &txpwr
->mcs_40_cdd
[0], BRCMS_NUM_RATES_MCS_1_STREAM
);
1470 memcpy(&pi
->tx_user_target
[TXP_FIRST_MCS_40_STBC
],
1471 &txpwr
->mcs_40_stbc
[0], BRCMS_NUM_RATES_MCS_1_STREAM
);
1472 memcpy(&pi
->tx_user_target
[TXP_FIRST_MCS_40_SDM
],
1473 &txpwr
->mcs_40_mimo
[0], BRCMS_NUM_RATES_MCS_2_STREAM
);
1475 if (R_REG(&pi
->regs
->maccontrol
) & MCTL_EN_MAC
)
1479 wlapi_suspend_mac_and_wait(pi
->sh
->physhim
);
1481 wlc_phy_txpower_recalc_target(pi
);
1482 wlc_phy_cal_txpower_recalc_sw(pi
);
1485 wlapi_enable_mac(pi
->sh
->physhim
);
1488 int wlc_phy_txpower_set(struct brcms_phy_pub
*ppi
, uint qdbm
, bool override
)
1490 struct brcms_phy
*pi
= (struct brcms_phy
*) ppi
;
1496 for (i
= 0; i
< TXP_NUM_RATES
; i
++)
1497 pi
->tx_user_target
[i
] = (u8
) qdbm
;
1499 pi
->txpwroverride
= false;
1502 if (!SCAN_INPROG_PHY(pi
)) {
1505 suspend
= (0 == (R_REG(&pi
->regs
->maccontrol
) &
1509 wlapi_suspend_mac_and_wait(pi
->sh
->physhim
);
1511 wlc_phy_txpower_recalc_target(pi
);
1512 wlc_phy_cal_txpower_recalc_sw(pi
);
1515 wlapi_enable_mac(pi
->sh
->physhim
);
1522 wlc_phy_txpower_sromlimit(struct brcms_phy_pub
*ppi
, uint channel
, u8
*min_pwr
,
1523 u8
*max_pwr
, int txp_rate_idx
)
1525 struct brcms_phy
*pi
= (struct brcms_phy
*) ppi
;
1528 *min_pwr
= pi
->min_txpower
* BRCMS_TXPWR_DB_FACTOR
;
1531 if (txp_rate_idx
< 0)
1532 txp_rate_idx
= TXP_FIRST_CCK
;
1533 wlc_phy_txpower_sromlimit_get_nphy(pi
, channel
, max_pwr
,
1536 } else if ((channel
<= CH_MAX_2G_CHANNEL
)) {
1537 if (txp_rate_idx
< 0)
1538 txp_rate_idx
= TXP_FIRST_CCK
;
1539 *max_pwr
= pi
->tx_srom_max_rate_2g
[txp_rate_idx
];
1542 *max_pwr
= BRCMS_TXPWR_MAX
;
1544 if (txp_rate_idx
< 0)
1545 txp_rate_idx
= TXP_FIRST_OFDM
;
1547 for (i
= 0; i
< ARRAY_SIZE(chan_info_all
); i
++) {
1548 if (channel
== chan_info_all
[i
].chan
)
1553 *max_pwr
= pi
->hwtxpwr
[i
];
1556 if ((i
>= FIRST_MID_5G_CHAN
) && (i
<= LAST_MID_5G_CHAN
))
1558 pi
->tx_srom_max_rate_5g_mid
[txp_rate_idx
];
1559 if ((i
>= FIRST_HIGH_5G_CHAN
)
1560 && (i
<= LAST_HIGH_5G_CHAN
))
1562 pi
->tx_srom_max_rate_5g_hi
[txp_rate_idx
];
1563 if ((i
>= FIRST_LOW_5G_CHAN
) && (i
<= LAST_LOW_5G_CHAN
))
1565 pi
->tx_srom_max_rate_5g_low
[txp_rate_idx
];
1571 wlc_phy_txpower_sromlimit_max_get(struct brcms_phy_pub
*ppi
, uint chan
,
1572 u8
*max_txpwr
, u8
*min_txpwr
)
1574 struct brcms_phy
*pi
= (struct brcms_phy
*) ppi
;
1576 u8 tx_pwr_min
= 255;
1578 u8 maxtxpwr
, mintxpwr
, rate
, pactrl
;
1582 max_num_rate
= ISNPHY(pi
) ? TXP_NUM_RATES
:
1583 ISLCNPHY(pi
) ? (TXP_LAST_SISO_MCS_20
+
1584 1) : (TXP_LAST_OFDM
+ 1);
1586 for (rate
= 0; rate
< max_num_rate
; rate
++) {
1588 wlc_phy_txpower_sromlimit(ppi
, chan
, &mintxpwr
, &maxtxpwr
,
1591 maxtxpwr
= (maxtxpwr
> pactrl
) ? (maxtxpwr
- pactrl
) : 0;
1593 maxtxpwr
= (maxtxpwr
> 6) ? (maxtxpwr
- 6) : 0;
1595 tx_pwr_max
= max(tx_pwr_max
, maxtxpwr
);
1596 tx_pwr_min
= min(tx_pwr_min
, maxtxpwr
);
1598 *max_txpwr
= tx_pwr_max
;
1599 *min_txpwr
= tx_pwr_min
;
1603 wlc_phy_txpower_boardlimit_band(struct brcms_phy_pub
*ppi
, uint bandunit
,
1604 s32
*max_pwr
, s32
*min_pwr
, u32
*step_pwr
)
1609 u8
wlc_phy_txpower_get_target_min(struct brcms_phy_pub
*ppi
)
1611 struct brcms_phy
*pi
= (struct brcms_phy
*) ppi
;
1613 return pi
->tx_power_min
;
1616 u8
wlc_phy_txpower_get_target_max(struct brcms_phy_pub
*ppi
)
1618 struct brcms_phy
*pi
= (struct brcms_phy
*) ppi
;
1620 return pi
->tx_power_max
;
1623 void wlc_phy_txpower_recalc_target(struct brcms_phy
*pi
)
1625 u8 maxtxpwr
, mintxpwr
, rate
, pactrl
;
1627 u8 tx_pwr_target
[TXP_NUM_RATES
];
1629 u8 tx_pwr_min
= 255;
1630 u8 tx_pwr_max_rate_ind
= 0;
1634 u32 band
= CHSPEC2BAND(pi
->radio_chanspec
);
1635 void (*txpwr_recalc_fn
)(struct brcms_phy
*) = NULL
;
1637 chspec
= pi
->radio_chanspec
;
1638 if (CHSPEC_CTL_SB(chspec
) == WL_CHANSPEC_CTL_SB_NONE
)
1639 target_chan
= CHSPEC_CHANNEL(chspec
);
1640 else if (CHSPEC_CTL_SB(chspec
) == WL_CHANSPEC_CTL_SB_UPPER
)
1641 target_chan
= UPPER_20_SB(CHSPEC_CHANNEL(chspec
));
1643 target_chan
= LOWER_20_SB(CHSPEC_CHANNEL(chspec
));
1649 if (CHSPEC_IS40(pi
->radio_chanspec
)) {
1650 offset_mcs
= pi
->mcs40_po
;
1651 for (i
= TXP_FIRST_SISO_MCS_20
;
1652 i
<= TXP_LAST_SISO_MCS_20
; i
++) {
1653 pi
->tx_srom_max_rate_2g
[i
- 8] =
1654 pi
->tx_srom_max_2g
-
1655 ((offset_mcs
& 0xf) * 2);
1659 offset_mcs
= pi
->mcs20_po
;
1660 for (i
= TXP_FIRST_SISO_MCS_20
;
1661 i
<= TXP_LAST_SISO_MCS_20
; i
++) {
1662 pi
->tx_srom_max_rate_2g
[i
- 8] =
1663 pi
->tx_srom_max_2g
-
1664 ((offset_mcs
& 0xf) * 2);
1670 max_num_rate
= ((ISNPHY(pi
)) ? (TXP_NUM_RATES
) :
1672 (TXP_LAST_SISO_MCS_20
+ 1) : (TXP_LAST_OFDM
+ 1)));
1674 max_num_rate
= ((ISNPHY(pi
)) ? (TXP_NUM_RATES
) : (TXP_LAST_OFDM
+ 1));
1677 wlc_phy_upd_env_txpwr_rate_limits(pi
, band
);
1679 for (rate
= start_rate
; rate
< max_num_rate
; rate
++) {
1681 tx_pwr_target
[rate
] = pi
->tx_user_target
[rate
];
1683 if (pi
->user_txpwr_at_rfport
)
1684 tx_pwr_target
[rate
] +=
1685 wlc_user_txpwr_antport_to_rfport(pi
,
1692 wlc_phy_txpower_sromlimit((struct brcms_phy_pub
*) pi
,
1694 &mintxpwr
, &maxtxpwr
, rate
);
1696 maxtxpwr
= min(maxtxpwr
, pi
->txpwr_limit
[rate
]);
1699 (maxtxpwr
> pactrl
) ? (maxtxpwr
- pactrl
) : 0;
1701 maxtxpwr
= (maxtxpwr
> 6) ? (maxtxpwr
- 6) : 0;
1703 maxtxpwr
= min(maxtxpwr
, tx_pwr_target
[rate
]);
1705 if (pi
->txpwr_percent
<= 100)
1706 maxtxpwr
= (maxtxpwr
* pi
->txpwr_percent
) / 100;
1708 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
);
2307 wlc_phy_noise_sample_request(struct brcms_phy_pub
*pih
, u8 reason
, u8 ch
)
2309 struct brcms_phy
*pi
= (struct brcms_phy
*) pih
;
2310 s8 noise_dbm
= PHY_NOISE_FIXED_VAL_NPHY
;
2311 bool sampling_in_progress
= (pi
->phynoise_state
!= 0);
2312 bool wait_for_intr
= true;
2314 if (NORADIO_ENAB(pi
->pubpi
))
2318 case PHY_NOISE_SAMPLE_MON
:
2319 pi
->phynoise_chan_watchdog
= ch
;
2320 pi
->phynoise_state
|= PHY_NOISE_STATE_MON
;
2323 case PHY_NOISE_SAMPLE_EXTERNAL
:
2324 pi
->phynoise_state
|= PHY_NOISE_STATE_EXTERNAL
;
2331 if (sampling_in_progress
)
2334 pi
->phynoise_now
= pi
->sh
->now
;
2336 if (pi
->phy_fixed_noise
) {
2338 pi
->nphy_noise_win
[WL_ANT_IDX_1
][pi
->nphy_noise_index
] =
2339 PHY_NOISE_FIXED_VAL_NPHY
;
2340 pi
->nphy_noise_win
[WL_ANT_IDX_2
][pi
->nphy_noise_index
] =
2341 PHY_NOISE_FIXED_VAL_NPHY
;
2342 pi
->nphy_noise_index
= MODINC_POW2(pi
->nphy_noise_index
,
2343 PHY_NOISE_WINDOW_SZ
);
2344 noise_dbm
= PHY_NOISE_FIXED_VAL_NPHY
;
2346 noise_dbm
= PHY_NOISE_FIXED_VAL
;
2349 wait_for_intr
= false;
2354 if (!pi
->phynoise_polling
2355 || (reason
== PHY_NOISE_SAMPLE_EXTERNAL
)) {
2356 wlapi_bmac_write_shm(pi
->sh
->physhim
, M_JSSI_0
, 0);
2357 wlapi_bmac_write_shm(pi
->sh
->physhim
, M_PWRIND_MAP0
, 0);
2358 wlapi_bmac_write_shm(pi
->sh
->physhim
, M_PWRIND_MAP1
, 0);
2359 wlapi_bmac_write_shm(pi
->sh
->physhim
, M_PWRIND_MAP2
, 0);
2360 wlapi_bmac_write_shm(pi
->sh
->physhim
, M_PWRIND_MAP3
, 0);
2362 OR_REG(&pi
->regs
->maccommand
,
2365 wlapi_suspend_mac_and_wait(pi
->sh
->physhim
);
2366 wlc_lcnphy_deaf_mode(pi
, (bool) 0);
2367 noise_dbm
= (s8
) wlc_lcnphy_rx_signal_power(pi
, 20);
2368 wlc_lcnphy_deaf_mode(pi
, (bool) 1);
2369 wlapi_enable_mac(pi
->sh
->physhim
);
2370 wait_for_intr
= false;
2372 } else if (ISNPHY(pi
)) {
2373 if (!pi
->phynoise_polling
2374 || (reason
== PHY_NOISE_SAMPLE_EXTERNAL
)) {
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);
2381 OR_REG(&pi
->regs
->maccommand
,
2384 struct phy_iq_est est
[PHY_CORE_MAX
];
2385 u32 cmplx_pwr
[PHY_CORE_MAX
];
2386 s8 noise_dbm_ant
[PHY_CORE_MAX
];
2387 u16 log_num_samps
, num_samps
, classif_state
= 0;
2392 memset((u8
*) est
, 0, sizeof(est
));
2393 memset((u8
*) cmplx_pwr
, 0, sizeof(cmplx_pwr
));
2394 memset((u8
*) noise_dbm_ant
, 0, sizeof(noise_dbm_ant
));
2396 log_num_samps
= PHY_NOISE_SAMPLE_LOG_NUM_NPHY
;
2397 num_samps
= 1 << log_num_samps
;
2399 wlapi_suspend_mac_and_wait(pi
->sh
->physhim
);
2400 classif_state
= wlc_phy_classifier_nphy(pi
, 0, 0);
2401 wlc_phy_classifier_nphy(pi
, 3, 0);
2402 wlc_phy_rx_iq_est_nphy(pi
, est
, num_samps
, wait_time
,
2404 wlc_phy_classifier_nphy(pi
, (0x7 << 0), classif_state
);
2405 wlapi_enable_mac(pi
->sh
->physhim
);
2407 for (i
= 0; i
< pi
->pubpi
.phy_corenum
; i
++)
2408 cmplx_pwr
[i
] = (est
[i
].i_pwr
+ est
[i
].q_pwr
) >>
2411 wlc_phy_noise_calc_phy(pi
, cmplx_pwr
, noise_dbm_ant
);
2413 for (i
= 0; i
< pi
->pubpi
.phy_corenum
; i
++) {
2414 pi
->nphy_noise_win
[i
][pi
->nphy_noise_index
] =
2417 if (noise_dbm_ant
[i
] > noise_dbm
)
2418 noise_dbm
= noise_dbm_ant
[i
];
2420 pi
->nphy_noise_index
= MODINC_POW2(pi
->nphy_noise_index
,
2421 PHY_NOISE_WINDOW_SZ
);
2423 wait_for_intr
= false;
2430 wlc_phy_noise_cb(pi
, ch
, noise_dbm
);
2434 void wlc_phy_noise_sample_request_external(struct brcms_phy_pub
*pih
)
2438 channel
= CHSPEC_CHANNEL(wlc_phy_chanspec_get(pih
));
2440 wlc_phy_noise_sample_request(pih
, PHY_NOISE_SAMPLE_EXTERNAL
, channel
);
2443 static void wlc_phy_noise_cb(struct brcms_phy
*pi
, u8 channel
, s8 noise_dbm
)
2445 if (!pi
->phynoise_state
)
2448 if (pi
->phynoise_state
& PHY_NOISE_STATE_MON
) {
2449 if (pi
->phynoise_chan_watchdog
== channel
) {
2450 pi
->sh
->phy_noise_window
[pi
->sh
->phy_noise_index
] =
2452 pi
->sh
->phy_noise_index
=
2453 MODINC(pi
->sh
->phy_noise_index
, MA_WINDOW_SZ
);
2455 pi
->phynoise_state
&= ~PHY_NOISE_STATE_MON
;
2458 if (pi
->phynoise_state
& PHY_NOISE_STATE_EXTERNAL
)
2459 pi
->phynoise_state
&= ~PHY_NOISE_STATE_EXTERNAL
;
2463 static s8
wlc_phy_noise_read_shmem(struct brcms_phy
*pi
)
2465 u32 cmplx_pwr
[PHY_CORE_MAX
];
2466 s8 noise_dbm_ant
[PHY_CORE_MAX
];
2468 u32 cmplx_pwr_tot
= 0;
2469 s8 noise_dbm
= PHY_NOISE_FIXED_VAL_NPHY
;
2472 memset((u8
*) cmplx_pwr
, 0, sizeof(cmplx_pwr
));
2473 memset((u8
*) noise_dbm_ant
, 0, sizeof(noise_dbm_ant
));
2475 for (idx
= 0, core
= 0; core
< pi
->pubpi
.phy_corenum
; idx
+= 2,
2477 lo
= wlapi_bmac_read_shm(pi
->sh
->physhim
, M_PWRIND_MAP(idx
));
2478 hi
= wlapi_bmac_read_shm(pi
->sh
->physhim
,
2479 M_PWRIND_MAP(idx
+ 1));
2480 cmplx_pwr
[core
] = (hi
<< 16) + lo
;
2481 cmplx_pwr_tot
+= cmplx_pwr
[core
];
2482 if (cmplx_pwr
[core
] == 0)
2483 noise_dbm_ant
[core
] = PHY_NOISE_FIXED_VAL_NPHY
;
2485 cmplx_pwr
[core
] >>= PHY_NOISE_SAMPLE_LOG_NUM_UCODE
;
2488 if (cmplx_pwr_tot
!= 0)
2489 wlc_phy_noise_calc_phy(pi
, cmplx_pwr
, noise_dbm_ant
);
2491 for (core
= 0; core
< pi
->pubpi
.phy_corenum
; core
++) {
2492 pi
->nphy_noise_win
[core
][pi
->nphy_noise_index
] =
2493 noise_dbm_ant
[core
];
2495 if (noise_dbm_ant
[core
] > noise_dbm
)
2496 noise_dbm
= noise_dbm_ant
[core
];
2498 pi
->nphy_noise_index
=
2499 MODINC_POW2(pi
->nphy_noise_index
, PHY_NOISE_WINDOW_SZ
);
2505 void wlc_phy_noise_sample_intr(struct brcms_phy_pub
*pih
)
2507 struct brcms_phy
*pi
= (struct brcms_phy
*) pih
;
2510 s8 noise_dbm
= PHY_NOISE_FIXED_VAL_NPHY
;
2513 u32 cmplx_pwr
, cmplx_pwr0
, cmplx_pwr1
;
2515 s32 pwr_offset_dB
, gain_dB
;
2516 u16 status_0
, status_1
;
2518 jssi_aux
= wlapi_bmac_read_shm(pi
->sh
->physhim
, M_JSSI_AUX
);
2519 channel
= jssi_aux
& D11_CURCHANNEL_MAX
;
2521 lo
= wlapi_bmac_read_shm(pi
->sh
->physhim
, M_PWRIND_MAP0
);
2522 hi
= wlapi_bmac_read_shm(pi
->sh
->physhim
, M_PWRIND_MAP1
);
2523 cmplx_pwr0
= (hi
<< 16) + lo
;
2525 lo
= wlapi_bmac_read_shm(pi
->sh
->physhim
, M_PWRIND_MAP2
);
2526 hi
= wlapi_bmac_read_shm(pi
->sh
->physhim
, M_PWRIND_MAP3
);
2527 cmplx_pwr1
= (hi
<< 16) + lo
;
2528 cmplx_pwr
= (cmplx_pwr0
+ cmplx_pwr1
) >> 6;
2531 status_1
= wlapi_bmac_read_shm(pi
->sh
->physhim
, M_JSSI_0
);
2532 if ((cmplx_pwr
> 0 && cmplx_pwr
< 500)
2533 && ((status_1
& 0xc000) == 0x4000)) {
2535 wlc_phy_compute_dB(&cmplx_pwr
, &noise_dbm
,
2536 pi
->pubpi
.phy_corenum
);
2537 pwr_offset_dB
= (read_phy_reg(pi
, 0x434) & 0xFF);
2538 if (pwr_offset_dB
> 127)
2539 pwr_offset_dB
-= 256;
2541 noise_dbm
+= (s8
) (pwr_offset_dB
- 30);
2543 gain_dB
= (status_0
& 0x1ff);
2544 noise_dbm
-= (s8
) (gain_dB
);
2546 noise_dbm
= PHY_NOISE_FIXED_VAL_LCNPHY
;
2548 } else if (ISNPHY(pi
)) {
2550 jssi_aux
= wlapi_bmac_read_shm(pi
->sh
->physhim
, M_JSSI_AUX
);
2551 channel
= jssi_aux
& D11_CURCHANNEL_MAX
;
2553 noise_dbm
= wlc_phy_noise_read_shmem(pi
);
2556 wlc_phy_noise_cb(pi
, channel
, noise_dbm
);
2560 s8 lcnphy_gain_index_offset_for_pkt_rssi
[] = {
2601 void wlc_phy_compute_dB(u32
*cmplx_pwr
, s8
*p_cmplx_pwr_dB
, u8 core
)
2603 u8 msb
, secondmsb
, i
;
2606 for (i
= 0; i
< core
; i
++) {
2611 secondmsb
= (u8
) ((tmp
>> (--msb
- 1)) & 1);
2612 p_cmplx_pwr_dB
[i
] = (s8
) (3 * msb
+ 2 * secondmsb
);
2616 void wlc_phy_rssi_compute(struct brcms_phy_pub
*pih
,
2617 struct brcms_d11rxhdr
*wlc_rxhdr
)
2619 struct d11rxhdr
*rxh
= &wlc_rxhdr
->rxhdr
;
2620 int rssi
= le16_to_cpu(rxh
->PhyRxStatus_1
) & PRXS1_JSSI_MASK
;
2621 uint radioid
= pih
->radioid
;
2622 struct brcms_phy
*pi
= (struct brcms_phy
*) pih
;
2624 if (NORADIO_ENAB(pi
->pubpi
)) {
2625 rssi
= BRCMS_RSSI_INVALID
;
2629 if ((pi
->sh
->corerev
>= 11)
2630 && !(le16_to_cpu(rxh
->RxStatus2
) & RXS_PHYRXST_VALID
)) {
2631 rssi
= BRCMS_RSSI_INVALID
;
2636 u8 gidx
= (le16_to_cpu(rxh
->PhyRxStatus_2
) & 0xFC00) >> 10;
2637 struct brcms_phy_lcnphy
*pi_lcn
= pi
->u
.pi_lcnphy
;
2642 rssi
= rssi
+ lcnphy_gain_index_offset_for_pkt_rssi
[gidx
];
2643 if ((rssi
> -46) && (gidx
> 18))
2646 rssi
= rssi
+ pi_lcn
->lcnphy_pkteng_rssi_slope
;
2655 } else if (radioid
== BCM2055_ID
|| radioid
== BCM2056_ID
2656 || radioid
== BCM2057_ID
) {
2657 rssi
= wlc_phy_rssi_compute_nphy(pi
, wlc_rxhdr
);
2661 wlc_rxhdr
->rssi
= (s8
) rssi
;
2664 void wlc_phy_freqtrack_start(struct brcms_phy_pub
*pih
)
2669 void wlc_phy_freqtrack_end(struct brcms_phy_pub
*pih
)
2674 void wlc_phy_set_deaf(struct brcms_phy_pub
*ppi
, bool user_flag
)
2676 struct brcms_phy
*pi
;
2677 pi
= (struct brcms_phy
*) ppi
;
2680 wlc_lcnphy_deaf_mode(pi
, true);
2681 else if (ISNPHY(pi
))
2682 wlc_nphy_deaf_mode(pi
, true);
2685 void wlc_phy_watchdog(struct brcms_phy_pub
*pih
)
2687 struct brcms_phy
*pi
= (struct brcms_phy
*) pih
;
2688 bool delay_phy_cal
= false;
2691 if (!pi
->watchdog_override
)
2694 if (!(SCAN_RM_IN_PROGRESS(pi
) || PLT_INPROG_PHY(pi
)))
2695 wlc_phy_noise_sample_request((struct brcms_phy_pub
*) pi
,
2696 PHY_NOISE_SAMPLE_MON
,
2700 if (pi
->phynoise_state
&& (pi
->sh
->now
- pi
->phynoise_now
) > 5)
2701 pi
->phynoise_state
= 0;
2703 if ((!pi
->phycal_txpower
) ||
2704 ((pi
->sh
->now
- pi
->phycal_txpower
) >= pi
->sh
->fast_timer
)) {
2706 if (!SCAN_INPROG_PHY(pi
) && wlc_phy_cal_txpower_recalc_sw(pi
))
2707 pi
->phycal_txpower
= pi
->sh
->now
;
2710 if (NORADIO_ENAB(pi
->pubpi
))
2713 if ((SCAN_RM_IN_PROGRESS(pi
) || PLT_INPROG_PHY(pi
)
2714 || ASSOC_INPROG_PHY(pi
)))
2717 if (ISNPHY(pi
) && !pi
->disable_percal
&& !delay_phy_cal
) {
2719 if ((pi
->nphy_perical
!= PHY_PERICAL_DISABLE
) &&
2720 (pi
->nphy_perical
!= PHY_PERICAL_MANUAL
) &&
2721 ((pi
->sh
->now
- pi
->nphy_perical_last
) >=
2722 pi
->sh
->glacial_timer
))
2723 wlc_phy_cal_perical((struct brcms_phy_pub
*) pi
,
2724 PHY_PERICAL_WATCHDOG
);
2726 wlc_phy_txpwr_papd_cal_nphy(pi
);
2730 if (pi
->phy_forcecal
||
2731 ((pi
->sh
->now
- pi
->phy_lastcal
) >=
2732 pi
->sh
->glacial_timer
)) {
2733 if (!(SCAN_RM_IN_PROGRESS(pi
) || ASSOC_INPROG_PHY(pi
)))
2734 wlc_lcnphy_calib_modes(
2736 LCNPHY_PERICAL_TEMPBASED_TXPWRCTRL
);
2738 (SCAN_RM_IN_PROGRESS(pi
) || PLT_INPROG_PHY(pi
)
2739 || ASSOC_INPROG_PHY(pi
)
2740 || pi
->carrier_suppr_disable
2741 || pi
->disable_percal
))
2742 wlc_lcnphy_calib_modes(pi
,
2743 PHY_PERICAL_WATCHDOG
);
2748 void wlc_phy_BSSinit(struct brcms_phy_pub
*pih
, bool bonlyap
, int rssi
)
2750 struct brcms_phy
*pi
= (struct brcms_phy
*) pih
;
2754 for (i
= 0; i
< MA_WINDOW_SZ
; i
++)
2755 pi
->sh
->phy_noise_window
[i
] = (s8
) (rssi
& 0xff);
2757 for (i
= 0; i
< MA_WINDOW_SZ
; i
++)
2758 pi
->sh
->phy_noise_window
[i
] =
2759 PHY_NOISE_FIXED_VAL_LCNPHY
;
2761 pi
->sh
->phy_noise_index
= 0;
2763 for (i
= 0; i
< PHY_NOISE_WINDOW_SZ
; i
++) {
2764 for (k
= WL_ANT_IDX_1
; k
< WL_ANT_RX_MAX
; k
++)
2765 pi
->nphy_noise_win
[k
][i
] = PHY_NOISE_FIXED_VAL_NPHY
;
2767 pi
->nphy_noise_index
= 0;
2771 wlc_phy_papd_decode_epsilon(u32 epsilon
, s32
*eps_real
, s32
*eps_imag
)
2773 *eps_imag
= (epsilon
>> 13);
2774 if (*eps_imag
> 0xfff)
2775 *eps_imag
-= 0x2000;
2777 *eps_real
= (epsilon
& 0x1fff);
2778 if (*eps_real
> 0xfff)
2779 *eps_real
-= 0x2000;
2782 static const s32 AtanTbl
[] = {
2803 void wlc_phy_cordic(s32 theta
, struct cs32
*val
)
2810 val
[0].i
= CORDIC_AG
;
2814 signtheta
= (theta
< 0) ? -1 : 1;
2815 theta
= ((theta
+ FIXED(180) * signtheta
) % FIXED(360)) -
2816 FIXED(180) * signtheta
;
2818 if (FLOAT(theta
) > 90) {
2819 theta
-= FIXED(180);
2821 } else if (FLOAT(theta
) < -90) {
2822 theta
+= FIXED(180);
2826 for (iter
= 0; iter
< CORDIC_NI
; iter
++) {
2827 if (theta
> angle
) {
2828 valtmp
= val
[0].i
- (val
[0].q
>> iter
);
2829 val
[0].q
= (val
[0].i
>> iter
) + val
[0].q
;
2831 angle
+= AtanTbl
[iter
];
2833 valtmp
= val
[0].i
+ (val
[0].q
>> iter
);
2834 val
[0].q
= -(val
[0].i
>> iter
) + val
[0].q
;
2836 angle
-= AtanTbl
[iter
];
2840 val
[0].i
= val
[0].i
* signx
;
2841 val
[0].q
= val
[0].q
* signx
;
2844 void wlc_phy_cal_perical_mphase_reset(struct brcms_phy
*pi
)
2846 wlapi_del_timer(pi
->sh
->physhim
, pi
->phycal_timer
);
2848 pi
->cal_type_override
= PHY_PERICAL_AUTO
;
2849 pi
->mphase_cal_phase_id
= MPHASE_CAL_STATE_IDLE
;
2850 pi
->mphase_txcal_cmdidx
= 0;
2854 wlc_phy_cal_perical_mphase_schedule(struct brcms_phy
*pi
, uint delay
)
2857 if ((pi
->nphy_perical
!= PHY_PERICAL_MPHASE
) &&
2858 (pi
->nphy_perical
!= PHY_PERICAL_MANUAL
))
2861 wlapi_del_timer(pi
->sh
->physhim
, pi
->phycal_timer
);
2863 pi
->mphase_cal_phase_id
= MPHASE_CAL_STATE_INIT
;
2864 wlapi_add_timer(pi
->sh
->physhim
, pi
->phycal_timer
, delay
, 0);
2867 void wlc_phy_cal_perical(struct brcms_phy_pub
*pih
, u8 reason
)
2869 s16 nphy_currtemp
= 0;
2871 bool do_periodic_cal
= true;
2872 struct brcms_phy
*pi
= (struct brcms_phy
*) pih
;
2877 if ((pi
->nphy_perical
== PHY_PERICAL_DISABLE
) ||
2878 (pi
->nphy_perical
== PHY_PERICAL_MANUAL
))
2882 case PHY_PERICAL_DRIVERUP
:
2885 case PHY_PERICAL_PHYINIT
:
2886 if (pi
->nphy_perical
== PHY_PERICAL_MPHASE
) {
2887 if (PHY_PERICAL_MPHASE_PENDING(pi
))
2888 wlc_phy_cal_perical_mphase_reset(pi
);
2890 wlc_phy_cal_perical_mphase_schedule(
2892 PHY_PERICAL_INIT_DELAY
);
2896 case PHY_PERICAL_JOIN_BSS
:
2897 case PHY_PERICAL_START_IBSS
:
2898 case PHY_PERICAL_UP_BSS
:
2899 if ((pi
->nphy_perical
== PHY_PERICAL_MPHASE
) &&
2900 PHY_PERICAL_MPHASE_PENDING(pi
))
2901 wlc_phy_cal_perical_mphase_reset(pi
);
2903 pi
->first_cal_after_assoc
= true;
2905 pi
->cal_type_override
= PHY_PERICAL_FULL
;
2907 if (pi
->phycal_tempdelta
)
2908 pi
->nphy_lastcal_temp
= wlc_phy_tempsense_nphy(pi
);
2910 wlc_phy_cal_perical_nphy_run(pi
, PHY_PERICAL_FULL
);
2913 case PHY_PERICAL_WATCHDOG
:
2914 if (pi
->phycal_tempdelta
) {
2915 nphy_currtemp
= wlc_phy_tempsense_nphy(pi
);
2917 (nphy_currtemp
> pi
->nphy_lastcal_temp
) ?
2918 nphy_currtemp
- pi
->nphy_lastcal_temp
:
2919 pi
->nphy_lastcal_temp
- nphy_currtemp
;
2921 if ((delta_temp
< (s16
) pi
->phycal_tempdelta
) &&
2922 (pi
->nphy_txiqlocal_chanspec
==
2923 pi
->radio_chanspec
))
2924 do_periodic_cal
= false;
2926 pi
->nphy_lastcal_temp
= nphy_currtemp
;
2929 if (do_periodic_cal
) {
2930 if (pi
->nphy_perical
== PHY_PERICAL_MPHASE
) {
2931 if (!PHY_PERICAL_MPHASE_PENDING(pi
))
2932 wlc_phy_cal_perical_mphase_schedule(
2934 PHY_PERICAL_WDOG_DELAY
);
2935 } else if (pi
->nphy_perical
== PHY_PERICAL_SPHASE
)
2936 wlc_phy_cal_perical_nphy_run(pi
,
2945 void wlc_phy_cal_perical_mphase_restart(struct brcms_phy
*pi
)
2947 pi
->mphase_cal_phase_id
= MPHASE_CAL_STATE_INIT
;
2948 pi
->mphase_txcal_cmdidx
= 0;
2951 u8
wlc_phy_nbits(s32 value
)
2956 abs_val
= ABS(value
);
2957 while ((abs_val
>> nbits
) > 0)
2963 void wlc_phy_stf_chain_init(struct brcms_phy_pub
*pih
, u8 txchain
, u8 rxchain
)
2965 struct brcms_phy
*pi
= (struct brcms_phy
*) pih
;
2967 pi
->sh
->hw_phytxchain
= txchain
;
2968 pi
->sh
->hw_phyrxchain
= rxchain
;
2969 pi
->sh
->phytxchain
= txchain
;
2970 pi
->sh
->phyrxchain
= rxchain
;
2971 pi
->pubpi
.phy_corenum
= (u8
) PHY_BITSCNT(pi
->sh
->phyrxchain
);
2974 void wlc_phy_stf_chain_set(struct brcms_phy_pub
*pih
, u8 txchain
, u8 rxchain
)
2976 struct brcms_phy
*pi
= (struct brcms_phy
*) pih
;
2978 pi
->sh
->phytxchain
= txchain
;
2981 wlc_phy_rxcore_setstate_nphy(pih
, rxchain
);
2983 pi
->pubpi
.phy_corenum
= (u8
) PHY_BITSCNT(pi
->sh
->phyrxchain
);
2986 void wlc_phy_stf_chain_get(struct brcms_phy_pub
*pih
, u8
*txchain
, u8
*rxchain
)
2988 struct brcms_phy
*pi
= (struct brcms_phy
*) pih
;
2990 *txchain
= pi
->sh
->phytxchain
;
2991 *rxchain
= pi
->sh
->phyrxchain
;
2994 u8
wlc_phy_stf_chain_active_get(struct brcms_phy_pub
*pih
)
2998 struct brcms_phy
*pi
= (struct brcms_phy
*) pih
;
3000 active_bitmap
= (pi
->phy_txcore_heatedup
) ? 0x31 : 0x33;
3002 if (!pi
->watchdog_override
)
3003 return active_bitmap
;
3005 if (NREV_GE(pi
->pubpi
.phy_rev
, 6)) {
3006 wlapi_suspend_mac_and_wait(pi
->sh
->physhim
);
3007 nphy_currtemp
= wlc_phy_tempsense_nphy(pi
);
3008 wlapi_enable_mac(pi
->sh
->physhim
);
3010 if (!pi
->phy_txcore_heatedup
) {
3011 if (nphy_currtemp
>= pi
->phy_txcore_disable_temp
) {
3012 active_bitmap
&= 0xFD;
3013 pi
->phy_txcore_heatedup
= true;
3016 if (nphy_currtemp
<= pi
->phy_txcore_enable_temp
) {
3017 active_bitmap
|= 0x2;
3018 pi
->phy_txcore_heatedup
= false;
3023 return active_bitmap
;
3026 s8
wlc_phy_stf_ssmode_get(struct brcms_phy_pub
*pih
, u16 chanspec
)
3028 struct brcms_phy
*pi
= (struct brcms_phy
*) pih
;
3029 u8 siso_mcs_id
, cdd_mcs_id
;
3032 (CHSPEC_IS40(chanspec
)) ? TXP_FIRST_MCS_40_SISO
:
3033 TXP_FIRST_MCS_20_SISO
;
3035 (CHSPEC_IS40(chanspec
)) ? TXP_FIRST_MCS_40_CDD
:
3036 TXP_FIRST_MCS_20_CDD
;
3038 if (pi
->tx_power_target
[siso_mcs_id
] >
3039 (pi
->tx_power_target
[cdd_mcs_id
] + 12))
3040 return PHY_TXC1_MODE_SISO
;
3042 return PHY_TXC1_MODE_CDD
;
3045 const u8
*wlc_phy_get_ofdm_rate_lookup(void)
3047 return ofdm_rate_lookup
;
3050 void wlc_lcnphy_epa_switch(struct brcms_phy
*pi
, bool mode
)
3052 if ((pi
->sh
->chip
== BCM4313_CHIP_ID
) &&
3053 (pi
->sh
->boardflags
& BFL_FEM
)) {
3056 txant
= wlapi_bmac_get_txant(pi
->sh
->physhim
);
3058 mod_phy_reg(pi
, 0x44d, (0x1 << 2), (1) << 2);
3060 mod_phy_reg(pi
, 0x44c, (0x1 << 2), (1) << 2);
3063 ai_corereg(pi
->sh
->sih
, SI_CC_IDX
,
3064 offsetof(struct chipcregs
, gpiocontrol
),
3066 ai_corereg(pi
->sh
->sih
, SI_CC_IDX
,
3067 offsetof(struct chipcregs
, gpioout
), 0x40,
3069 ai_corereg(pi
->sh
->sih
, SI_CC_IDX
,
3070 offsetof(struct chipcregs
, gpioouten
), 0x40,
3073 mod_phy_reg(pi
, 0x44c, (0x1 << 2), (0) << 2);
3075 mod_phy_reg(pi
, 0x44d, (0x1 << 2), (0) << 2);
3077 ai_corereg(pi
->sh
->sih
, SI_CC_IDX
,
3078 offsetof(struct chipcregs
, gpioout
), 0x40,
3080 ai_corereg(pi
->sh
->sih
, SI_CC_IDX
,
3081 offsetof(struct chipcregs
, gpioouten
), 0x40,
3083 ai_corereg(pi
->sh
->sih
, SI_CC_IDX
,
3084 offsetof(struct chipcregs
, gpiocontrol
),
3091 wlc_user_txpwr_antport_to_rfport(struct brcms_phy
*pi
, uint chan
, u32 band
,
3096 if (!pi
->user_txpwr_at_rfport
)
3101 static s8
wlc_phy_env_measure_vbat(struct brcms_phy
*pi
)
3104 return wlc_lcnphy_vbatsense(pi
, 0);
3109 static s8
wlc_phy_env_measure_temperature(struct brcms_phy
*pi
)
3112 return wlc_lcnphy_tempsense_degree(pi
, 0);
3117 static void wlc_phy_upd_env_txpwr_rate_limits(struct brcms_phy
*pi
, u32 band
)
3122 for (i
= 0; i
< TXP_NUM_RATES
; i
++)
3123 pi
->txpwr_env_limit
[i
] = BRCMS_TXPWR_MAX
;
3125 vbat
= wlc_phy_env_measure_vbat(pi
);
3126 temp
= wlc_phy_env_measure_temperature(pi
);
3130 void wlc_phy_ldpc_override_set(struct brcms_phy_pub
*ppi
, bool ldpc
)
3136 wlc_phy_get_pwrdet_offsets(struct brcms_phy
*pi
, s8
*cckoffset
, s8
*ofdmoffset
)
3142 s8
wlc_phy_upd_rssi_offset(struct brcms_phy
*pi
, s8 rssi
, u16 chanspec
)
3148 bool wlc_phy_txpower_ipa_ison(struct brcms_phy_pub
*ppi
)
3150 struct brcms_phy
*pi
= (struct brcms_phy
*) ppi
;
3153 return wlc_phy_n_txpower_ipa_ison(pi
);