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/kernel.h>
18
#include <linux/string.h>
19
#include <linux/bitops.h>
20
#include <linux/delay.h>
23
#include <linux/pci.h>
30
#include <wlc_phy_radio.h>
31
#include <wlc_phy_int.h>
32
#include <wlc_phy_lcn.h>
33
#include <wlc_phytbl_lcn.h>
35
#define PLL_2064_NDIV 90
36
#define PLL_2064_LOW_END_VCO 3000
37
#define PLL_2064_LOW_END_KVCO 27
38
#define PLL_2064_HIGH_END_VCO 4200
39
#define PLL_2064_HIGH_END_KVCO 68
40
#define PLL_2064_LOOP_BW_DOUBLER 200
41
#define PLL_2064_D30_DOUBLER 10500
42
#define PLL_2064_LOOP_BW 260
43
#define PLL_2064_D30 8000
44
#define PLL_2064_CAL_REF_TO 8
45
#define PLL_2064_MHZ 1000000
46
#define PLL_2064_OPEN_LOOP_DELAY 5
51
#define NOISE_IF_UPD_CHK_INTERVAL 1
52
#define NOISE_IF_UPD_RST_INTERVAL 60
53
#define NOISE_IF_UPD_THRESHOLD_CNT 1
54
#define NOISE_IF_UPD_TRHRESHOLD 50
55
#define NOISE_IF_UPD_TIMEOUT 1000
56
#define NOISE_IF_OFF 0
57
#define NOISE_IF_CHK 1
60
#define PAPD_BLANKING_PROFILE 3
62
#define PAPD_CORR_NORM 0
63
#define PAPD_BLANKING_THRESHOLD 0
64
#define PAPD_STOP_AFTER_LAST_UPDATE 0
66
#define LCN_TARGET_PWR 60
68
#define LCN_VBAT_OFFSET_433X 34649679
69
#define LCN_VBAT_SLOPE_433X 8258032
71
#define LCN_VBAT_SCALE_NOM 53
72
#define LCN_VBAT_SCALE_DEN 432
74
#define LCN_TEMPSENSE_OFFSET 80812
75
#define LCN_TEMPSENSE_DEN 2647
77
#define LCNPHY_txgainctrlovrval1_pagain_ovr_val1_SHIFT \
79
#define LCNPHY_txgainctrlovrval1_pagain_ovr_val1_MASK \
80
(0x7f << LCNPHY_txgainctrlovrval1_pagain_ovr_val1_SHIFT)
82
#define LCNPHY_stxtxgainctrlovrval1_pagain_ovr_val1_SHIFT \
84
#define LCNPHY_stxtxgainctrlovrval1_pagain_ovr_val1_MASK \
85
(0x7f << LCNPHY_stxtxgainctrlovrval1_pagain_ovr_val1_SHIFT)
87
#define wlc_lcnphy_enable_tx_gain_override(pi) \
88
wlc_lcnphy_set_tx_gain_override(pi, true)
89
#define wlc_lcnphy_disable_tx_gain_override(pi) \
90
wlc_lcnphy_set_tx_gain_override(pi, false)
92
#define wlc_lcnphy_iqcal_active(pi) \
93
(read_phy_reg((pi), 0x451) & \
94
((0x1 << 15) | (0x1 << 14)))
96
#define txpwrctrl_off(pi) (0x7 != ((read_phy_reg(pi, 0x4a4) & 0xE000) >> 13))
97
#define wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi) \
98
(pi->temppwrctrl_capable)
99
#define wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi) \
100
(pi->hwpwrctrl_capable)
102
#define SWCTRL_BT_TX 0x18
103
#define SWCTRL_OVR_DISABLE 0x40
105
#define AFE_CLK_INIT_MODE_TXRX2X 1
106
#define AFE_CLK_INIT_MODE_PAPD 0
108
#define LCNPHY_TBL_ID_IQLOCAL 0x00
110
#define LCNPHY_TBL_ID_RFSEQ 0x08
111
#define LCNPHY_TBL_ID_GAIN_IDX 0x0d
112
#define LCNPHY_TBL_ID_SW_CTRL 0x0f
113
#define LCNPHY_TBL_ID_GAIN_TBL 0x12
114
#define LCNPHY_TBL_ID_SPUR 0x14
115
#define LCNPHY_TBL_ID_SAMPLEPLAY 0x15
116
#define LCNPHY_TBL_ID_SAMPLEPLAY1 0x16
118
#define LCNPHY_TX_PWR_CTRL_RATE_OFFSET 832
119
#define LCNPHY_TX_PWR_CTRL_MAC_OFFSET 128
120
#define LCNPHY_TX_PWR_CTRL_GAIN_OFFSET 192
121
#define LCNPHY_TX_PWR_CTRL_IQ_OFFSET 320
122
#define LCNPHY_TX_PWR_CTRL_LO_OFFSET 448
123
#define LCNPHY_TX_PWR_CTRL_PWR_OFFSET 576
125
#define LCNPHY_TX_PWR_CTRL_START_INDEX_2G_4313 140
127
#define LCNPHY_TX_PWR_CTRL_START_NPT 1
128
#define LCNPHY_TX_PWR_CTRL_MAX_NPT 7
130
#define LCNPHY_NOISE_SAMPLES_DEFAULT 5000
132
#define LCNPHY_ACI_DETECT_START 1
133
#define LCNPHY_ACI_DETECT_PROGRESS 2
134
#define LCNPHY_ACI_DETECT_STOP 3
136
#define LCNPHY_ACI_CRSHIFRMLO_TRSH 100
137
#define LCNPHY_ACI_GLITCH_TRSH 2000
138
#define LCNPHY_ACI_TMOUT 250
139
#define LCNPHY_ACI_DETECT_TIMEOUT 2
140
#define LCNPHY_ACI_START_DELAY 0
142
#define wlc_lcnphy_tx_gain_override_enabled(pi) \
143
(0 != (read_phy_reg((pi), 0x43b) & (0x1 << 6)))
145
#define wlc_lcnphy_total_tx_frames(pi) \
146
wlapi_bmac_read_shm((pi)->sh->physhim, M_UCODE_MACSTAT + offsetof(macstat_t, txallfrm))
164
lcnphy_txgains_t gains;
167
} lcnphy_txcalgains_t;
173
} lcnphy_rx_iqcomp_t;
183
} lcnphy_unsign16_struct;
199
} lcnphy_papd_cal_type_t;
201
typedef u16 iqcal_gain_params_lcnphy[9];
203
static const iqcal_gain_params_lcnphy tbl_iqcal_gainparams_lcnphy_2G[] = {
204
{0, 0, 0, 0, 0, 0, 0, 0, 0},
207
static const iqcal_gain_params_lcnphy *tbl_iqcal_gainparams_lcnphy[1] = {
208
tbl_iqcal_gainparams_lcnphy_2G,
211
static const u16 iqcal_gainparams_numgains_lcnphy[1] = {
212
sizeof(tbl_iqcal_gainparams_lcnphy_2G) /
213
sizeof(*tbl_iqcal_gainparams_lcnphy_2G),
216
static const lcnphy_sfo_cfg_t lcnphy_sfo_cfg[] = {
234
u16 lcnphy_iqcal_loft_gainladder[] = {
258
u16 lcnphy_iqcal_ir_gainladder[] = {
282
lcnphy_spb_tone_t lcnphy_spb_tone_3750[] = {
318
u16 iqlo_loopback_rf_regs[20] = {
342
u16 tempsense_phy_regs[14] = {
360
u16 rxiq_cal_rf_reg[11] = {
375
lcnphy_rx_iqcomp_t lcnphy_rx_iqcomp_table_rev0[] = {
429
static const u32 lcnphy_23bitgaincode_table[] = {
469
static const s8 lcnphy_gain_table[] = {
509
static const s8 lcnphy_gain_index_offset_for_rssi[] = {
550
extern const u8 spur_tbl_rev0[];
551
extern const u32 dot11lcnphytbl_rx_gain_info_sz_rev1;
552
extern const dot11lcnphytbl_info_t dot11lcnphytbl_rx_gain_info_rev1[];
553
extern const dot11lcnphytbl_info_t dot11lcn_sw_ctrl_tbl_info_4313_bt_epa;
554
extern const dot11lcnphytbl_info_t dot11lcn_sw_ctrl_tbl_info_4313_bt_epa_p250;
556
typedef struct _chan_info_2064_lcnphy {
561
u8 txrf_mix_tune_ctrl;
564
u8 pa_rxrf_lna1_freq_tune;
565
u8 pa_rxrf_lna2_freq_tune;
567
} chan_info_2064_lcnphy_t;
569
static chan_info_2064_lcnphy_t chan_info_2064_lcnphy[] = {
570
{1, 2412, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
571
{2, 2417, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
572
{3, 2422, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
573
{4, 2427, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
574
{5, 2432, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
575
{6, 2437, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
576
{7, 2442, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
577
{8, 2447, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
578
{9, 2452, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
579
{10, 2457, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
580
{11, 2462, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
581
{12, 2467, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
582
{13, 2472, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
583
{14, 2484, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
586
lcnphy_radio_regs_t lcnphy_radio_regs_2064[] = {
588
{0x01, 0x64, 0x64, 0, 0},
589
{0x02, 0x20, 0x20, 0, 0},
590
{0x03, 0x66, 0x66, 0, 0},
591
{0x04, 0xf8, 0xf8, 0, 0},
593
{0x06, 0x10, 0x10, 0, 0},
597
{0x0A, 0x37, 0x37, 0, 0},
598
{0x0B, 0x6, 0x6, 0, 0},
599
{0x0C, 0x55, 0x55, 0, 0},
600
{0x0D, 0x8b, 0x8b, 0, 0},
602
{0x0F, 0x5, 0x5, 0, 0},
604
{0x11, 0xe, 0xe, 0, 0},
606
{0x13, 0xb, 0xb, 0, 0},
607
{0x14, 0x2, 0x2, 0, 0},
608
{0x15, 0x12, 0x12, 0, 0},
609
{0x16, 0x12, 0x12, 0, 0},
610
{0x17, 0xc, 0xc, 0, 0},
611
{0x18, 0xc, 0xc, 0, 0},
612
{0x19, 0xc, 0xc, 0, 0},
613
{0x1A, 0x8, 0x8, 0, 0},
614
{0x1B, 0x2, 0x2, 0, 0},
616
{0x1D, 0x1, 0x1, 0, 0},
617
{0x1E, 0x12, 0x12, 0, 0},
618
{0x1F, 0x6e, 0x6e, 0, 0},
619
{0x20, 0x2, 0x2, 0, 0},
620
{0x21, 0x23, 0x23, 0, 0},
621
{0x22, 0x8, 0x8, 0, 0},
624
{0x25, 0xc, 0xc, 0, 0},
625
{0x26, 0x33, 0x33, 0, 0},
626
{0x27, 0x55, 0x55, 0, 0},
628
{0x29, 0x30, 0x30, 0, 0},
629
{0x2A, 0xb, 0xb, 0, 0},
630
{0x2B, 0x1b, 0x1b, 0, 0},
631
{0x2C, 0x3, 0x3, 0, 0},
632
{0x2D, 0x1b, 0x1b, 0, 0},
634
{0x2F, 0x20, 0x20, 0, 0},
635
{0x30, 0xa, 0xa, 0, 0},
637
{0x32, 0x62, 0x62, 0, 0},
638
{0x33, 0x19, 0x19, 0, 0},
639
{0x34, 0x33, 0x33, 0, 0},
640
{0x35, 0x77, 0x77, 0, 0},
642
{0x37, 0x70, 0x70, 0, 0},
643
{0x38, 0x3, 0x3, 0, 0},
644
{0x39, 0xf, 0xf, 0, 0},
645
{0x3A, 0x6, 0x6, 0, 0},
646
{0x3B, 0xcf, 0xcf, 0, 0},
647
{0x3C, 0x1a, 0x1a, 0, 0},
648
{0x3D, 0x6, 0x6, 0, 0},
649
{0x3E, 0x42, 0x42, 0, 0},
651
{0x40, 0xfb, 0xfb, 0, 0},
652
{0x41, 0x9a, 0x9a, 0, 0},
653
{0x42, 0x7a, 0x7a, 0, 0},
654
{0x43, 0x29, 0x29, 0, 0},
656
{0x45, 0x8, 0x8, 0, 0},
657
{0x46, 0xce, 0xce, 0, 0},
658
{0x47, 0x27, 0x27, 0, 0},
659
{0x48, 0x62, 0x62, 0, 0},
660
{0x49, 0x6, 0x6, 0, 0},
661
{0x4A, 0x58, 0x58, 0, 0},
662
{0x4B, 0xf7, 0xf7, 0, 0},
664
{0x4D, 0xb3, 0xb3, 0, 0},
666
{0x4F, 0x2, 0x2, 0, 0},
668
{0x51, 0x9, 0x9, 0, 0},
669
{0x52, 0x5, 0x5, 0, 0},
670
{0x53, 0x17, 0x17, 0, 0},
671
{0x54, 0x38, 0x38, 0, 0},
674
{0x57, 0xb, 0xb, 0, 0},
681
{0x5E, 0x88, 0x88, 0, 0},
682
{0x5F, 0xcc, 0xcc, 0, 0},
683
{0x60, 0x74, 0x74, 0, 0},
684
{0x61, 0x74, 0x74, 0, 0},
685
{0x62, 0x74, 0x74, 0, 0},
686
{0x63, 0x44, 0x44, 0, 0},
687
{0x64, 0x77, 0x77, 0, 0},
688
{0x65, 0x44, 0x44, 0, 0},
689
{0x66, 0x77, 0x77, 0, 0},
690
{0x67, 0x55, 0x55, 0, 0},
691
{0x68, 0x77, 0x77, 0, 0},
692
{0x69, 0x77, 0x77, 0, 0},
694
{0x6B, 0x7f, 0x7f, 0, 0},
695
{0x6C, 0x8, 0x8, 0, 0},
697
{0x6E, 0x88, 0x88, 0, 0},
698
{0x6F, 0x66, 0x66, 0, 0},
699
{0x70, 0x66, 0x66, 0, 0},
700
{0x71, 0x28, 0x28, 0, 0},
701
{0x72, 0x55, 0x55, 0, 0},
702
{0x73, 0x4, 0x4, 0, 0},
706
{0x77, 0x1, 0x1, 0, 0},
707
{0x78, 0xd6, 0xd6, 0, 0},
718
{0x83, 0xb4, 0xb4, 0, 0},
719
{0x84, 0x1, 0x1, 0, 0},
720
{0x85, 0x20, 0x20, 0, 0},
721
{0x86, 0x5, 0x5, 0, 0},
722
{0x87, 0xff, 0xff, 0, 0},
723
{0x88, 0x7, 0x7, 0, 0},
724
{0x89, 0x77, 0x77, 0, 0},
725
{0x8A, 0x77, 0x77, 0, 0},
726
{0x8B, 0x77, 0x77, 0, 0},
727
{0x8C, 0x77, 0x77, 0, 0},
728
{0x8D, 0x8, 0x8, 0, 0},
729
{0x8E, 0xa, 0xa, 0, 0},
730
{0x8F, 0x8, 0x8, 0, 0},
731
{0x90, 0x18, 0x18, 0, 0},
732
{0x91, 0x5, 0x5, 0, 0},
733
{0x92, 0x1f, 0x1f, 0, 0},
734
{0x93, 0x10, 0x10, 0, 0},
735
{0x94, 0x3, 0x3, 0, 0},
738
{0x97, 0xaa, 0xaa, 0, 0},
740
{0x99, 0x23, 0x23, 0, 0},
741
{0x9A, 0x7, 0x7, 0, 0},
742
{0x9B, 0xf, 0xf, 0, 0},
743
{0x9C, 0x10, 0x10, 0, 0},
744
{0x9D, 0x3, 0x3, 0, 0},
745
{0x9E, 0x4, 0x4, 0, 0},
746
{0x9F, 0x20, 0x20, 0, 0},
751
{0xA4, 0x1, 0x1, 0, 0},
752
{0xA5, 0x77, 0x77, 0, 0},
753
{0xA6, 0x77, 0x77, 0, 0},
754
{0xA7, 0x77, 0x77, 0, 0},
755
{0xA8, 0x77, 0x77, 0, 0},
756
{0xA9, 0x8c, 0x8c, 0, 0},
757
{0xAA, 0x88, 0x88, 0, 0},
758
{0xAB, 0x78, 0x78, 0, 0},
759
{0xAC, 0x57, 0x57, 0, 0},
760
{0xAD, 0x88, 0x88, 0, 0},
762
{0xAF, 0x8, 0x8, 0, 0},
763
{0xB0, 0x88, 0x88, 0, 0},
765
{0xB2, 0x1b, 0x1b, 0, 0},
766
{0xB3, 0x3, 0x3, 0, 0},
767
{0xB4, 0x24, 0x24, 0, 0},
768
{0xB5, 0x3, 0x3, 0, 0},
769
{0xB6, 0x1b, 0x1b, 0, 0},
770
{0xB7, 0x24, 0x24, 0, 0},
771
{0xB8, 0x3, 0x3, 0, 0},
773
{0xBA, 0xaa, 0xaa, 0, 0},
775
{0xBC, 0x4, 0x4, 0, 0},
777
{0xBE, 0x8, 0x8, 0, 0},
778
{0xBF, 0x11, 0x11, 0, 0},
781
{0xC2, 0x62, 0x62, 0, 0},
782
{0xC3, 0x1e, 0x1e, 0, 0},
783
{0xC4, 0x33, 0x33, 0, 0},
784
{0xC5, 0x37, 0x37, 0, 0},
786
{0xC7, 0x70, 0x70, 0, 0},
787
{0xC8, 0x1e, 0x1e, 0, 0},
788
{0xC9, 0x6, 0x6, 0, 0},
789
{0xCA, 0x4, 0x4, 0, 0},
790
{0xCB, 0x2f, 0x2f, 0, 0},
791
{0xCC, 0xf, 0xf, 0, 0},
793
{0xCE, 0xff, 0xff, 0, 0},
794
{0xCF, 0x8, 0x8, 0, 0},
795
{0xD0, 0x3f, 0x3f, 0, 0},
796
{0xD1, 0x3f, 0x3f, 0, 0},
797
{0xD2, 0x3f, 0x3f, 0, 0},
801
{0xD6, 0xcc, 0xcc, 0, 0},
803
{0xD8, 0x8, 0x8, 0, 0},
804
{0xD9, 0x8, 0x8, 0, 0},
805
{0xDA, 0x8, 0x8, 0, 0},
806
{0xDB, 0x11, 0x11, 0, 0},
808
{0xDD, 0x87, 0x87, 0, 0},
809
{0xDE, 0x88, 0x88, 0, 0},
810
{0xDF, 0x8, 0x8, 0, 0},
811
{0xE0, 0x8, 0x8, 0, 0},
812
{0xE1, 0x8, 0x8, 0, 0},
816
{0xE5, 0xf5, 0xf5, 0, 0},
817
{0xE6, 0x30, 0x30, 0, 0},
818
{0xE7, 0x1, 0x1, 0, 0},
820
{0xE9, 0xff, 0xff, 0, 0},
823
{0xEC, 0x22, 0x22, 0, 0},
827
{0xF0, 0x3, 0x3, 0, 0},
828
{0xF1, 0x1, 0x1, 0, 0},
834
{0xF7, 0x6, 0x6, 0, 0},
837
{0xFA, 0x40, 0x40, 0, 0},
839
{0xFC, 0x1, 0x1, 0, 0},
840
{0xFD, 0x80, 0x80, 0, 0},
841
{0xFE, 0x2, 0x2, 0, 0},
842
{0xFF, 0x10, 0x10, 0, 0},
843
{0x100, 0x2, 0x2, 0, 0},
844
{0x101, 0x1e, 0x1e, 0, 0},
845
{0x102, 0x1e, 0x1e, 0, 0},
847
{0x104, 0x1f, 0x1f, 0, 0},
848
{0x105, 0, 0x8, 0, 1},
849
{0x106, 0x2a, 0x2a, 0, 0},
850
{0x107, 0xf, 0xf, 0, 0},
871
{0x11C, 0x1, 0x1, 0, 0},
877
{0x122, 0x80, 0x80, 0, 0},
879
{0x124, 0xf8, 0xf8, 0, 0},
895
#define LCNPHY_NUM_DIG_FILT_COEFFS 16
896
#define LCNPHY_NUM_TX_DIG_FILTERS_CCK 13
899
LCNPHY_txdigfiltcoeffs_cck[LCNPHY_NUM_TX_DIG_FILTERS_CCK]
900
[LCNPHY_NUM_DIG_FILT_COEFFS + 1] = {
901
{0, 1, 415, 1874, 64, 128, 64, 792, 1656, 64, 128, 64, 778, 1582, 64,
903
{1, 1, 402, 1847, 259, 59, 259, 671, 1794, 68, 54, 68, 608, 1863, 93,
905
{2, 1, 415, 1874, 64, 128, 64, 792, 1656, 192, 384, 192, 778, 1582, 64,
907
{3, 1, 302, 1841, 129, 258, 129, 658, 1720, 205, 410, 205, 754, 1760,
909
{20, 1, 360, 1884, 242, 1734, 242, 752, 1720, 205, 1845, 205, 767, 1760,
911
{21, 1, 360, 1884, 149, 1874, 149, 752, 1720, 205, 1883, 205, 767, 1760,
913
{22, 1, 360, 1884, 98, 1948, 98, 752, 1720, 205, 1924, 205, 767, 1760,
915
{23, 1, 350, 1884, 116, 1966, 116, 752, 1720, 205, 2008, 205, 767, 1760,
917
{24, 1, 325, 1884, 32, 40, 32, 756, 1720, 256, 471, 256, 766, 1760, 256,
919
{25, 1, 299, 1884, 51, 64, 51, 736, 1720, 256, 471, 256, 765, 1760, 256,
921
{26, 1, 277, 1943, 39, 117, 88, 637, 1838, 64, 192, 144, 614, 1864, 128,
923
{27, 1, 245, 1943, 49, 147, 110, 626, 1838, 256, 768, 576, 613, 1864,
925
{30, 1, 302, 1841, 61, 122, 61, 658, 1720, 205, 410, 205, 754, 1760,
929
#define LCNPHY_NUM_TX_DIG_FILTERS_OFDM 3
931
LCNPHY_txdigfiltcoeffs_ofdm[LCNPHY_NUM_TX_DIG_FILTERS_OFDM]
932
[LCNPHY_NUM_DIG_FILT_COEFFS + 1] = {
933
{0, 0, 0xa2, 0x0, 0x100, 0x100, 0x0, 0x0, 0x0, 0x100, 0x0, 0x0,
934
0x278, 0xfea0, 0x80, 0x100, 0x80,},
935
{1, 0, 374, 0xFF79, 16, 32, 16, 799, 0xFE74, 50, 32, 50,
936
750, 0xFE2B, 212, 0xFFCE, 212,},
937
{2, 0, 375, 0xFF16, 37, 76, 37, 799, 0xFE74, 32, 20, 32, 748,
938
0xFEF2, 128, 0xFFE2, 128}
941
#define wlc_lcnphy_set_start_tx_pwr_idx(pi, idx) \
942
mod_phy_reg(pi, 0x4a4, \
946
#define wlc_lcnphy_set_tx_pwr_npt(pi, npt) \
947
mod_phy_reg(pi, 0x4a5, \
951
#define wlc_lcnphy_get_tx_pwr_ctrl(pi) \
952
(read_phy_reg((pi), 0x4a4) & \
957
#define wlc_lcnphy_get_tx_pwr_npt(pi) \
958
((read_phy_reg(pi, 0x4a5) & \
962
#define wlc_lcnphy_get_current_tx_pwr_idx_if_pwrctrl_on(pi) \
963
(read_phy_reg(pi, 0x473) & 0x1ff)
965
#define wlc_lcnphy_get_target_tx_pwr(pi) \
966
((read_phy_reg(pi, 0x4a7) & \
970
#define wlc_lcnphy_set_target_tx_pwr(pi, target) \
971
mod_phy_reg(pi, 0x4a7, \
975
#define wlc_radio_2064_rcal_done(pi) (0 != (read_radio_reg(pi, RADIO_2064_REG05C) & 0x20))
976
#define tempsense_done(pi) (0x8000 == (read_phy_reg(pi, 0x476) & 0x8000))
978
#define LCNPHY_IQLOCC_READ(val) ((u8)(-(s8)(((val) & 0xf0) >> 4) + (s8)((val) & 0x0f)))
979
#define FIXED_TXPWR 78
980
#define LCNPHY_TEMPSENSE(val) ((s16)((val > 255) ? (val - 512) : val))
982
static u32 wlc_lcnphy_qdiv_roundup(u32 divident, u32 divisor,
984
static void wlc_lcnphy_set_rx_gain_by_distribution(phy_info_t *pi,
985
u16 ext_lna, u16 trsw,
989
static void wlc_lcnphy_clear_tx_power_offsets(phy_info_t *pi);
990
static void wlc_lcnphy_set_pa_gain(phy_info_t *pi, u16 gain);
991
static void wlc_lcnphy_set_trsw_override(phy_info_t *pi, bool tx, bool rx);
992
static void wlc_lcnphy_set_bbmult(phy_info_t *pi, u8 m0);
993
static u8 wlc_lcnphy_get_bbmult(phy_info_t *pi);
994
static void wlc_lcnphy_get_tx_gain(phy_info_t *pi, lcnphy_txgains_t *gains);
995
static void wlc_lcnphy_set_tx_gain_override(phy_info_t *pi, bool bEnable);
996
static void wlc_lcnphy_toggle_afe_pwdn(phy_info_t *pi);
997
static void wlc_lcnphy_rx_gain_override_enable(phy_info_t *pi, bool enable);
998
static void wlc_lcnphy_set_tx_gain(phy_info_t *pi,
999
lcnphy_txgains_t *target_gains);
1000
static bool wlc_lcnphy_rx_iq_est(phy_info_t *pi, u16 num_samps,
1001
u8 wait_time, lcnphy_iq_est_t *iq_est);
1002
static bool wlc_lcnphy_calc_rx_iq_comp(phy_info_t *pi, u16 num_samps);
1003
static u16 wlc_lcnphy_get_pa_gain(phy_info_t *pi);
1004
static void wlc_lcnphy_afe_clk_init(phy_info_t *pi, u8 mode);
1005
extern void wlc_lcnphy_tx_pwr_ctrl_init(wlc_phy_t *ppi);
1006
static void wlc_lcnphy_radio_2064_channel_tune_4313(phy_info_t *pi,
1009
static void wlc_lcnphy_load_tx_gain_table(phy_info_t *pi,
1010
const lcnphy_tx_gain_tbl_entry *g);
1012
static void wlc_lcnphy_samp_cap(phy_info_t *pi, int clip_detect_algo,
1013
u16 thresh, s16 *ptr, int mode);
1014
static int wlc_lcnphy_calc_floor(s16 coeff, int type);
1015
static void wlc_lcnphy_tx_iqlo_loopback(phy_info_t *pi,
1016
u16 *values_to_save);
1017
static void wlc_lcnphy_tx_iqlo_loopback_cleanup(phy_info_t *pi,
1018
u16 *values_to_save);
1019
static void wlc_lcnphy_set_cc(phy_info_t *pi, int cal_type, s16 coeff_x,
1021
static lcnphy_unsign16_struct wlc_lcnphy_get_cc(phy_info_t *pi, int cal_type);
1022
static void wlc_lcnphy_a1(phy_info_t *pi, int cal_type,
1023
int num_levels, int step_size_lg2);
1024
static void wlc_lcnphy_tx_iqlo_soft_cal_full(phy_info_t *pi);
1026
static void wlc_lcnphy_set_chanspec_tweaks(phy_info_t *pi,
1027
chanspec_t chanspec);
1028
static void wlc_lcnphy_agc_temp_init(phy_info_t *pi);
1029
static void wlc_lcnphy_temp_adj(phy_info_t *pi);
1030
static void wlc_lcnphy_clear_papd_comptable(phy_info_t *pi);
1031
static void wlc_lcnphy_baseband_init(phy_info_t *pi);
1032
static void wlc_lcnphy_radio_init(phy_info_t *pi);
1033
static void wlc_lcnphy_rc_cal(phy_info_t *pi);
1034
static void wlc_lcnphy_rcal(phy_info_t *pi);
1035
static void wlc_lcnphy_txrx_spur_avoidance_mode(phy_info_t *pi, bool enable);
1036
static int wlc_lcnphy_load_tx_iir_filter(phy_info_t *pi, bool is_ofdm,
1038
static void wlc_lcnphy_set_rx_iq_comp(phy_info_t *pi, u16 a, u16 b);
1040
void wlc_lcnphy_write_table(phy_info_t *pi, const phytbl_info_t *pti)
1042
wlc_phy_write_table(pi, pti, 0x455, 0x457, 0x456);
1045
void wlc_lcnphy_read_table(phy_info_t *pi, phytbl_info_t *pti)
1047
wlc_phy_read_table(pi, pti, 0x455, 0x457, 0x456);
1051
wlc_lcnphy_common_read_table(phy_info_t *pi, u32 tbl_id,
1052
const void *tbl_ptr, u32 tbl_len,
1053
u32 tbl_width, u32 tbl_offset)
1056
tab.tbl_id = tbl_id;
1057
tab.tbl_ptr = tbl_ptr;
1058
tab.tbl_len = tbl_len;
1059
tab.tbl_width = tbl_width;
1060
tab.tbl_offset = tbl_offset;
1061
wlc_lcnphy_read_table(pi, &tab);
1065
wlc_lcnphy_common_write_table(phy_info_t *pi, u32 tbl_id,
1066
const void *tbl_ptr, u32 tbl_len,
1067
u32 tbl_width, u32 tbl_offset)
1071
tab.tbl_id = tbl_id;
1072
tab.tbl_ptr = tbl_ptr;
1073
tab.tbl_len = tbl_len;
1074
tab.tbl_width = tbl_width;
1075
tab.tbl_offset = tbl_offset;
1076
wlc_lcnphy_write_table(pi, &tab);
1080
wlc_lcnphy_qdiv_roundup(u32 dividend, u32 divisor, u8 precision)
1082
u32 quotient, remainder, roundup, rbit;
1086
quotient = dividend / divisor;
1087
remainder = dividend % divisor;
1089
roundup = (divisor >> 1) + rbit;
1091
while (precision--) {
1093
if (remainder >= roundup) {
1095
remainder = ((remainder - roundup) << 1) + rbit;
1101
if (remainder >= roundup)
1107
static int wlc_lcnphy_calc_floor(s16 coeff_x, int type)
1113
k = (coeff_x - 1) / 2;
1119
if ((coeff_x + 1) < 0)
1122
k = (coeff_x + 1) / 2;
1127
s8 wlc_lcnphy_get_current_tx_pwr_idx(phy_info_t *pi)
1130
phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
1132
if (txpwrctrl_off(pi))
1133
index = pi_lcn->lcnphy_current_index;
1134
else if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi))
1136
(s8) (wlc_lcnphy_get_current_tx_pwr_idx_if_pwrctrl_on(pi)
1139
index = pi_lcn->lcnphy_current_index;
1143
static u32 wlc_lcnphy_measure_digital_power(phy_info_t *pi, u16 nsamples)
1145
lcnphy_iq_est_t iq_est = { 0, 0, 0 };
1147
if (!wlc_lcnphy_rx_iq_est(pi, nsamples, 32, &iq_est))
1149
return (iq_est.i_pwr + iq_est.q_pwr) / nsamples;
1152
void wlc_lcnphy_crsuprs(phy_info_t *pi, int channel)
1154
u16 afectrlovr, afectrlovrval;
1155
afectrlovr = read_phy_reg(pi, 0x43b);
1156
afectrlovrval = read_phy_reg(pi, 0x43c);
1158
mod_phy_reg(pi, 0x43b, (0x1 << 1), (1) << 1);
1160
mod_phy_reg(pi, 0x43c, (0x1 << 1), (0) << 1);
1162
mod_phy_reg(pi, 0x43b, (0x1 << 4), (1) << 4);
1164
mod_phy_reg(pi, 0x43c, (0x1 << 6), (0) << 6);
1166
write_phy_reg(pi, 0x44b, 0xffff);
1167
wlc_lcnphy_tx_pu(pi, 1);
1169
mod_phy_reg(pi, 0x634, (0xff << 8), (0) << 8);
1171
or_phy_reg(pi, 0x6da, 0x0080);
1173
or_phy_reg(pi, 0x00a, 0x228);
1175
and_phy_reg(pi, 0x00a, ~(0x228));
1177
and_phy_reg(pi, 0x6da, 0xFF7F);
1178
write_phy_reg(pi, 0x43b, afectrlovr);
1179
write_phy_reg(pi, 0x43c, afectrlovrval);
1183
static void wlc_lcnphy_toggle_afe_pwdn(phy_info_t *pi)
1185
u16 save_AfeCtrlOvrVal, save_AfeCtrlOvr;
1187
save_AfeCtrlOvrVal = read_phy_reg(pi, 0x43c);
1188
save_AfeCtrlOvr = read_phy_reg(pi, 0x43b);
1190
write_phy_reg(pi, 0x43c, save_AfeCtrlOvrVal | 0x1);
1191
write_phy_reg(pi, 0x43b, save_AfeCtrlOvr | 0x1);
1193
write_phy_reg(pi, 0x43c, save_AfeCtrlOvrVal & 0xfffe);
1194
write_phy_reg(pi, 0x43b, save_AfeCtrlOvr & 0xfffe);
1196
write_phy_reg(pi, 0x43c, save_AfeCtrlOvrVal);
1197
write_phy_reg(pi, 0x43b, save_AfeCtrlOvr);
1200
static void wlc_lcnphy_txrx_spur_avoidance_mode(phy_info_t *pi, bool enable)
1203
write_phy_reg(pi, 0x942, 0x7);
1204
write_phy_reg(pi, 0x93b, ((1 << 13) + 23));
1205
write_phy_reg(pi, 0x93c, ((1 << 13) + 1989));
1207
write_phy_reg(pi, 0x44a, 0x084);
1208
write_phy_reg(pi, 0x44a, 0x080);
1209
write_phy_reg(pi, 0x6d3, 0x2222);
1210
write_phy_reg(pi, 0x6d3, 0x2220);
1212
write_phy_reg(pi, 0x942, 0x0);
1213
write_phy_reg(pi, 0x93b, ((0 << 13) + 23));
1214
write_phy_reg(pi, 0x93c, ((0 << 13) + 1989));
1216
wlapi_switch_macfreq(pi->sh->physhim, enable);
1219
void wlc_phy_chanspec_set_lcnphy(phy_info_t *pi, chanspec_t chanspec)
1221
u8 channel = CHSPEC_CHANNEL(chanspec);
1223
wlc_phy_chanspec_radio_set((wlc_phy_t *) pi, chanspec);
1225
wlc_lcnphy_set_chanspec_tweaks(pi, pi->radio_chanspec);
1227
or_phy_reg(pi, 0x44a, 0x44);
1228
write_phy_reg(pi, 0x44a, 0x80);
1230
if (!NORADIO_ENAB(pi->pubpi)) {
1231
wlc_lcnphy_radio_2064_channel_tune_4313(pi, channel);
1235
wlc_lcnphy_toggle_afe_pwdn(pi);
1237
write_phy_reg(pi, 0x657, lcnphy_sfo_cfg[channel - 1].ptcentreTs20);
1238
write_phy_reg(pi, 0x658, lcnphy_sfo_cfg[channel - 1].ptcentreFactor);
1240
if (CHSPEC_CHANNEL(pi->radio_chanspec) == 14) {
1241
mod_phy_reg(pi, 0x448, (0x3 << 8), (2) << 8);
1243
wlc_lcnphy_load_tx_iir_filter(pi, false, 3);
1245
mod_phy_reg(pi, 0x448, (0x3 << 8), (1) << 8);
1247
wlc_lcnphy_load_tx_iir_filter(pi, false, 2);
1250
wlc_lcnphy_load_tx_iir_filter(pi, true, 0);
1252
mod_phy_reg(pi, 0x4eb, (0x7 << 3), (1) << 3);
1256
static void wlc_lcnphy_set_dac_gain(phy_info_t *pi, u16 dac_gain)
1260
dac_ctrl = (read_phy_reg(pi, 0x439) >> 0);
1261
dac_ctrl = dac_ctrl & 0xc7f;
1262
dac_ctrl = dac_ctrl | (dac_gain << 7);
1263
mod_phy_reg(pi, 0x439, (0xfff << 0), (dac_ctrl) << 0);
1267
static void wlc_lcnphy_set_tx_gain_override(phy_info_t *pi, bool bEnable)
1269
u16 bit = bEnable ? 1 : 0;
1271
mod_phy_reg(pi, 0x4b0, (0x1 << 7), bit << 7);
1273
mod_phy_reg(pi, 0x4b0, (0x1 << 14), bit << 14);
1275
mod_phy_reg(pi, 0x43b, (0x1 << 6), bit << 6);
1278
static u16 wlc_lcnphy_get_pa_gain(phy_info_t *pi)
1282
pa_gain = (read_phy_reg(pi, 0x4fb) &
1283
LCNPHY_txgainctrlovrval1_pagain_ovr_val1_MASK) >>
1284
LCNPHY_txgainctrlovrval1_pagain_ovr_val1_SHIFT;
1290
wlc_lcnphy_set_tx_gain(phy_info_t *pi, lcnphy_txgains_t *target_gains)
1292
u16 pa_gain = wlc_lcnphy_get_pa_gain(pi);
1294
mod_phy_reg(pi, 0x4b5,
1296
((target_gains->gm_gain) | (target_gains->pga_gain << 8)) <<
1298
mod_phy_reg(pi, 0x4fb,
1300
((target_gains->pad_gain) | (pa_gain << 8)) << 0);
1302
mod_phy_reg(pi, 0x4fc,
1304
((target_gains->gm_gain) | (target_gains->pga_gain << 8)) <<
1306
mod_phy_reg(pi, 0x4fd,
1308
((target_gains->pad_gain) | (pa_gain << 8)) << 0);
1310
wlc_lcnphy_set_dac_gain(pi, target_gains->dac_gain);
1312
wlc_lcnphy_enable_tx_gain_override(pi);
1315
static void wlc_lcnphy_set_bbmult(phy_info_t *pi, u8 m0)
1317
u16 m0m1 = (u16) m0 << 8;
1320
tab.tbl_ptr = &m0m1;
1322
tab.tbl_id = LCNPHY_TBL_ID_IQLOCAL;
1323
tab.tbl_offset = 87;
1325
wlc_lcnphy_write_table(pi, &tab);
1328
static void wlc_lcnphy_clear_tx_power_offsets(phy_info_t *pi)
1333
memset(data_buf, 0, sizeof(data_buf));
1335
tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
1337
tab.tbl_ptr = data_buf;
1339
if (!wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) {
1342
tab.tbl_offset = LCNPHY_TX_PWR_CTRL_RATE_OFFSET;
1343
wlc_lcnphy_write_table(pi, &tab);
1347
tab.tbl_offset = LCNPHY_TX_PWR_CTRL_MAC_OFFSET;
1348
wlc_lcnphy_write_table(pi, &tab);
1353
LCNPHY_TSSI_POST_PA,
1355
} lcnphy_tssi_mode_t;
1357
static void wlc_lcnphy_set_tssi_mux(phy_info_t *pi, lcnphy_tssi_mode_t pos)
1359
mod_phy_reg(pi, 0x4d7, (0x1 << 0), (0x1) << 0);
1361
mod_phy_reg(pi, 0x4d7, (0x1 << 6), (1) << 6);
1363
if (LCNPHY_TSSI_POST_PA == pos) {
1364
mod_phy_reg(pi, 0x4d9, (0x1 << 2), (0) << 2);
1366
mod_phy_reg(pi, 0x4d9, (0x1 << 3), (1) << 3);
1368
if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
1369
mod_radio_reg(pi, RADIO_2064_REG086, 0x4, 0x4);
1371
mod_radio_reg(pi, RADIO_2064_REG03A, 1, 0x1);
1372
mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 0x8);
1375
mod_phy_reg(pi, 0x4d9, (0x1 << 2), (0x1) << 2);
1377
mod_phy_reg(pi, 0x4d9, (0x1 << 3), (0) << 3);
1379
if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
1380
mod_radio_reg(pi, RADIO_2064_REG086, 0x4, 0x4);
1382
mod_radio_reg(pi, RADIO_2064_REG03A, 1, 0);
1383
mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 0x8);
1386
mod_phy_reg(pi, 0x637, (0x3 << 14), (0) << 14);
1388
if (LCNPHY_TSSI_EXT == pos) {
1389
write_radio_reg(pi, RADIO_2064_REG07F, 1);
1390
mod_radio_reg(pi, RADIO_2064_REG005, 0x7, 0x2);
1391
mod_radio_reg(pi, RADIO_2064_REG112, 0x80, 0x1 << 7);
1392
mod_radio_reg(pi, RADIO_2064_REG028, 0x1f, 0x3);
1396
static u16 wlc_lcnphy_rfseq_tbl_adc_pwrup(phy_info_t *pi)
1398
u16 N1, N2, N3, N4, N5, N6, N;
1399
N1 = ((read_phy_reg(pi, 0x4a5) & (0xff << 0))
1401
N2 = 1 << ((read_phy_reg(pi, 0x4a5) & (0x7 << 12))
1403
N3 = ((read_phy_reg(pi, 0x40d) & (0xff << 0))
1405
N4 = 1 << ((read_phy_reg(pi, 0x40d) & (0x7 << 8))
1407
N5 = ((read_phy_reg(pi, 0x4a2) & (0xff << 0))
1409
N6 = 1 << ((read_phy_reg(pi, 0x4a2) & (0x7 << 8))
1411
N = 2 * (N1 + N2 + N3 + N4 + 2 * (N5 + N6)) + 80;
1417
static void wlc_lcnphy_pwrctrl_rssiparams(phy_info_t *pi)
1419
u16 auxpga_vmid, auxpga_vmid_temp, auxpga_gain_temp;
1420
phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
1423
(2 << 8) | (pi_lcn->lcnphy_rssi_vc << 4) | pi_lcn->lcnphy_rssi_vf;
1424
auxpga_vmid_temp = (2 << 8) | (8 << 4) | 4;
1425
auxpga_gain_temp = 2;
1427
mod_phy_reg(pi, 0x4d8, (0x1 << 0), (0) << 0);
1429
mod_phy_reg(pi, 0x4d8, (0x1 << 1), (0) << 1);
1431
mod_phy_reg(pi, 0x4d7, (0x1 << 3), (0) << 3);
1433
mod_phy_reg(pi, 0x4db,
1436
(auxpga_vmid << 0) | (pi_lcn->lcnphy_rssi_gs << 12));
1438
mod_phy_reg(pi, 0x4dc,
1441
(auxpga_vmid << 0) | (pi_lcn->lcnphy_rssi_gs << 12));
1443
mod_phy_reg(pi, 0x40a,
1446
(auxpga_vmid << 0) | (pi_lcn->lcnphy_rssi_gs << 12));
1448
mod_phy_reg(pi, 0x40b,
1451
(auxpga_vmid_temp << 0) | (auxpga_gain_temp << 12));
1453
mod_phy_reg(pi, 0x40c,
1456
(auxpga_vmid_temp << 0) | (auxpga_gain_temp << 12));
1458
mod_radio_reg(pi, RADIO_2064_REG082, (1 << 5), (1 << 5));
1461
static void wlc_lcnphy_tssi_setup(phy_info_t *pi)
1466
tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
1471
for (ind = 0; ind < 128; ind++) {
1472
wlc_lcnphy_write_table(pi, &tab);
1475
tab.tbl_offset = 704;
1476
for (ind = 0; ind < 128; ind++) {
1477
wlc_lcnphy_write_table(pi, &tab);
1480
mod_phy_reg(pi, 0x503, (0x1 << 0), (0) << 0);
1482
mod_phy_reg(pi, 0x503, (0x1 << 2), (0) << 2);
1484
mod_phy_reg(pi, 0x503, (0x1 << 4), (1) << 4);
1486
wlc_lcnphy_set_tssi_mux(pi, LCNPHY_TSSI_EXT);
1487
mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0) << 14);
1489
mod_phy_reg(pi, 0x4a4, (0x1 << 15), (1) << 15);
1491
mod_phy_reg(pi, 0x4d0, (0x1 << 5), (0) << 5);
1493
mod_phy_reg(pi, 0x4a4, (0x1ff << 0), (0) << 0);
1495
mod_phy_reg(pi, 0x4a5, (0xff << 0), (255) << 0);
1497
mod_phy_reg(pi, 0x4a5, (0x7 << 12), (5) << 12);
1499
mod_phy_reg(pi, 0x4a5, (0x7 << 8), (0) << 8);
1501
mod_phy_reg(pi, 0x40d, (0xff << 0), (64) << 0);
1503
mod_phy_reg(pi, 0x40d, (0x7 << 8), (4) << 8);
1505
mod_phy_reg(pi, 0x4a2, (0xff << 0), (64) << 0);
1507
mod_phy_reg(pi, 0x4a2, (0x7 << 8), (4) << 8);
1509
mod_phy_reg(pi, 0x4d0, (0x1ff << 6), (0) << 6);
1511
mod_phy_reg(pi, 0x4a8, (0xff << 0), (0x1) << 0);
1513
wlc_lcnphy_clear_tx_power_offsets(pi);
1515
mod_phy_reg(pi, 0x4a6, (0x1 << 15), (1) << 15);
1517
mod_phy_reg(pi, 0x4a6, (0x1ff << 0), (0xff) << 0);
1519
mod_phy_reg(pi, 0x49a, (0x1ff << 0), (0xff) << 0);
1521
if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
1522
mod_radio_reg(pi, RADIO_2064_REG028, 0xf, 0xe);
1523
mod_radio_reg(pi, RADIO_2064_REG086, 0x4, 0x4);
1525
mod_radio_reg(pi, RADIO_2064_REG03A, 0x1, 1);
1526
mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 1 << 3);
1529
write_radio_reg(pi, RADIO_2064_REG025, 0xc);
1531
if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
1532
mod_radio_reg(pi, RADIO_2064_REG03A, 0x1, 1);
1534
if (CHSPEC_IS2G(pi->radio_chanspec))
1535
mod_radio_reg(pi, RADIO_2064_REG03A, 0x2, 1 << 1);
1537
mod_radio_reg(pi, RADIO_2064_REG03A, 0x2, 0 << 1);
1540
if (LCNREV_IS(pi->pubpi.phy_rev, 2))
1541
mod_radio_reg(pi, RADIO_2064_REG03A, 0x2, 1 << 1);
1543
mod_radio_reg(pi, RADIO_2064_REG03A, 0x4, 1 << 2);
1545
mod_radio_reg(pi, RADIO_2064_REG11A, 0x1, 1 << 0);
1547
mod_radio_reg(pi, RADIO_2064_REG005, 0x8, 1 << 3);
1549
if (!wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) {
1550
mod_phy_reg(pi, 0x4d7,
1551
(0x1 << 3) | (0x7 << 12), 0 << 3 | 2 << 12);
1554
rfseq = wlc_lcnphy_rfseq_tbl_adc_pwrup(pi);
1555
tab.tbl_id = LCNPHY_TBL_ID_RFSEQ;
1557
tab.tbl_ptr = &rfseq;
1560
wlc_lcnphy_write_table(pi, &tab);
1562
mod_phy_reg(pi, 0x938, (0x1 << 2), (1) << 2);
1564
mod_phy_reg(pi, 0x939, (0x1 << 2), (1) << 2);
1566
mod_phy_reg(pi, 0x4a4, (0x1 << 12), (1) << 12);
1568
mod_phy_reg(pi, 0x4d7, (0x1 << 2), (1) << 2);
1570
mod_phy_reg(pi, 0x4d7, (0xf << 8), (0) << 8);
1572
wlc_lcnphy_pwrctrl_rssiparams(pi);
1575
void wlc_lcnphy_tx_pwr_update_npt(phy_info_t *pi)
1577
u16 tx_cnt, tx_total, npt;
1578
phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
1580
tx_total = wlc_lcnphy_total_tx_frames(pi);
1581
tx_cnt = tx_total - pi_lcn->lcnphy_tssi_tx_cnt;
1582
npt = wlc_lcnphy_get_tx_pwr_npt(pi);
1584
if (tx_cnt > (1 << npt)) {
1586
pi_lcn->lcnphy_tssi_tx_cnt = tx_total;
1588
pi_lcn->lcnphy_tssi_idx = wlc_lcnphy_get_current_tx_pwr_idx(pi);
1589
pi_lcn->lcnphy_tssi_npt = npt;
1594
s32 wlc_lcnphy_tssi2dbm(s32 tssi, s32 a1, s32 b0, s32 b1)
1598
a = 32768 + (a1 * tssi);
1599
b = (1024 * b0) + (64 * b1 * tssi);
1600
p = ((2 * b) + a) / (2 * a);
1605
static void wlc_lcnphy_txpower_reset_npt(phy_info_t *pi)
1607
phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
1608
if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi))
1611
pi_lcn->lcnphy_tssi_idx = LCNPHY_TX_PWR_CTRL_START_INDEX_2G_4313;
1612
pi_lcn->lcnphy_tssi_npt = LCNPHY_TX_PWR_CTRL_START_NPT;
1615
void wlc_lcnphy_txpower_recalc_target(phy_info_t *pi)
1618
u32 rate_table[WLC_NUM_RATES_CCK + WLC_NUM_RATES_OFDM +
1619
WLC_NUM_RATES_MCS_1_STREAM];
1621
if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi))
1624
for (i = 0, j = 0; i < ARRAY_SIZE(rate_table); i++, j++) {
1626
if (i == WLC_NUM_RATES_CCK + WLC_NUM_RATES_OFDM)
1627
j = TXP_FIRST_MCS_20_SISO;
1629
rate_table[i] = (u32) ((s32) (-pi->tx_power_offset[j]));
1632
tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
1634
tab.tbl_len = ARRAY_SIZE(rate_table);
1635
tab.tbl_ptr = rate_table;
1636
tab.tbl_offset = LCNPHY_TX_PWR_CTRL_RATE_OFFSET;
1637
wlc_lcnphy_write_table(pi, &tab);
1639
if (wlc_lcnphy_get_target_tx_pwr(pi) != pi->tx_power_min) {
1640
wlc_lcnphy_set_target_tx_pwr(pi, pi->tx_power_min);
1642
wlc_lcnphy_txpower_reset_npt(pi);
1646
static void wlc_lcnphy_set_tx_pwr_soft_ctrl(phy_info_t *pi, s8 index)
1648
u32 cck_offset[4] = { 22, 22, 22, 22 };
1649
u32 ofdm_offset, reg_offset_cck;
1654
if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi))
1657
mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0x1) << 14);
1659
mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0x0) << 14);
1661
or_phy_reg(pi, 0x6da, 0x0040);
1664
for (i = 0; i < 4; i++)
1665
cck_offset[i] -= reg_offset_cck;
1666
tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
1669
tab.tbl_ptr = cck_offset;
1670
tab.tbl_offset = LCNPHY_TX_PWR_CTRL_RATE_OFFSET;
1671
wlc_lcnphy_write_table(pi, &tab);
1674
tab.tbl_ptr = &ofdm_offset;
1675
for (i = 836; i < 862; i++) {
1677
wlc_lcnphy_write_table(pi, &tab);
1680
mod_phy_reg(pi, 0x4a4, (0x1 << 15), (0x1) << 15);
1682
mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0x1) << 14);
1684
mod_phy_reg(pi, 0x4a4, (0x1 << 13), (0x1) << 13);
1686
mod_phy_reg(pi, 0x4b0, (0x1 << 7), (0) << 7);
1688
mod_phy_reg(pi, 0x43b, (0x1 << 6), (0) << 6);
1690
mod_phy_reg(pi, 0x4a9, (0x1 << 15), (1) << 15);
1692
index2 = (u16) (index * 2);
1693
mod_phy_reg(pi, 0x4a9, (0x1ff << 0), (index2) << 0);
1695
mod_phy_reg(pi, 0x6a3, (0x1 << 4), (0) << 4);
1699
static s8 wlc_lcnphy_tempcompensated_txpwrctrl(phy_info_t *pi)
1701
s8 index, delta_brd, delta_temp, new_index, tempcorrx;
1702
s16 manp, meas_temp, temp_diff;
1705
phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
1707
if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi))
1708
return pi_lcn->lcnphy_current_index;
1710
index = FIXED_TXPWR;
1712
if (NORADIO_ENAB(pi->pubpi))
1715
if (pi_lcn->lcnphy_tempsense_slope == 0) {
1718
temp = (u16) wlc_lcnphy_tempsense(pi, 0);
1719
meas_temp = LCNPHY_TEMPSENSE(temp);
1721
if (pi->tx_power_min != 0) {
1722
delta_brd = (pi_lcn->lcnphy_measPower - pi->tx_power_min);
1727
manp = LCNPHY_TEMPSENSE(pi_lcn->lcnphy_rawtempsense);
1728
temp_diff = manp - meas_temp;
1729
if (temp_diff < 0) {
1733
temp_diff = -temp_diff;
1736
delta_temp = (s8) wlc_lcnphy_qdiv_roundup((u32) (temp_diff * 192),
1738
lcnphy_tempsense_slope
1741
delta_temp = -delta_temp;
1743
if (pi_lcn->lcnphy_tempsense_option == 3
1744
&& LCNREV_IS(pi->pubpi.phy_rev, 0))
1746
if (pi_lcn->lcnphy_tempcorrx > 31)
1747
tempcorrx = (s8) (pi_lcn->lcnphy_tempcorrx - 64);
1749
tempcorrx = (s8) pi_lcn->lcnphy_tempcorrx;
1750
if (LCNREV_IS(pi->pubpi.phy_rev, 1))
1753
index + delta_brd + delta_temp - pi_lcn->lcnphy_bandedge_corr;
1754
new_index += tempcorrx;
1756
if (LCNREV_IS(pi->pubpi.phy_rev, 1))
1758
if (new_index < 0 || new_index > 126) {
1764
static u16 wlc_lcnphy_set_tx_pwr_ctrl_mode(phy_info_t *pi, u16 mode)
1767
u16 current_mode = mode;
1768
if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi) &&
1769
mode == LCNPHY_TX_PWR_CTRL_HW)
1770
current_mode = LCNPHY_TX_PWR_CTRL_TEMPBASED;
1771
if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi) &&
1772
mode == LCNPHY_TX_PWR_CTRL_TEMPBASED)
1773
current_mode = LCNPHY_TX_PWR_CTRL_HW;
1774
return current_mode;
1777
void wlc_lcnphy_set_tx_pwr_ctrl(phy_info_t *pi, u16 mode)
1779
u16 old_mode = wlc_lcnphy_get_tx_pwr_ctrl(pi);
1781
phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
1783
ASSERT((LCNPHY_TX_PWR_CTRL_OFF == mode) ||
1784
(LCNPHY_TX_PWR_CTRL_SW == mode) ||
1785
(LCNPHY_TX_PWR_CTRL_HW == mode) ||
1786
(LCNPHY_TX_PWR_CTRL_TEMPBASED == mode));
1788
mode = wlc_lcnphy_set_tx_pwr_ctrl_mode(pi, mode);
1789
old_mode = wlc_lcnphy_set_tx_pwr_ctrl_mode(pi, old_mode);
1791
mod_phy_reg(pi, 0x6da, (0x1 << 6),
1792
((LCNPHY_TX_PWR_CTRL_HW == mode) ? 1 : 0) << 6);
1794
mod_phy_reg(pi, 0x6a3, (0x1 << 4),
1795
((LCNPHY_TX_PWR_CTRL_HW == mode) ? 0 : 1) << 4);
1797
if (old_mode != mode) {
1798
if (LCNPHY_TX_PWR_CTRL_HW == old_mode) {
1800
wlc_lcnphy_tx_pwr_update_npt(pi);
1802
wlc_lcnphy_clear_tx_power_offsets(pi);
1804
if (LCNPHY_TX_PWR_CTRL_HW == mode) {
1806
wlc_lcnphy_txpower_recalc_target(pi);
1808
wlc_lcnphy_set_start_tx_pwr_idx(pi,
1811
wlc_lcnphy_set_tx_pwr_npt(pi, pi_lcn->lcnphy_tssi_npt);
1812
mod_radio_reg(pi, RADIO_2064_REG11F, 0x4, 0);
1814
pi_lcn->lcnphy_tssi_tx_cnt =
1815
wlc_lcnphy_total_tx_frames(pi);
1817
wlc_lcnphy_disable_tx_gain_override(pi);
1818
pi_lcn->lcnphy_tx_power_idx_override = -1;
1820
wlc_lcnphy_enable_tx_gain_override(pi);
1822
mod_phy_reg(pi, 0x4a4,
1823
((0x1 << 15) | (0x1 << 14) | (0x1 << 13)), mode);
1824
if (mode == LCNPHY_TX_PWR_CTRL_TEMPBASED) {
1825
index = wlc_lcnphy_tempcompensated_txpwrctrl(pi);
1826
wlc_lcnphy_set_tx_pwr_soft_ctrl(pi, index);
1827
pi_lcn->lcnphy_current_index = (s8)
1828
((read_phy_reg(pi, 0x4a9) & 0xFF) / 2);
1833
static bool wlc_lcnphy_iqcal_wait(phy_info_t *pi)
1835
uint delay_count = 0;
1837
while (wlc_lcnphy_iqcal_active(pi)) {
1841
if (delay_count > (10 * 500))
1845
return (0 == wlc_lcnphy_iqcal_active(pi));
1849
wlc_lcnphy_tx_iqlo_cal(phy_info_t *pi,
1850
lcnphy_txgains_t *target_gains,
1851
lcnphy_cal_mode_t cal_mode, bool keep_tone)
1854
lcnphy_txgains_t cal_gains, temp_gains;
1858
u16 ncorr_override[5];
1859
u16 syst_coeffs[] = { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1860
0x0000, 0x0000, 0x0000, 0x0000, 0x0000
1863
u16 commands_fullcal[] = {
1864
0x8434, 0x8334, 0x8084, 0x8267, 0x8056, 0x8234 };
1866
u16 commands_recal[] = {
1867
0x8434, 0x8334, 0x8084, 0x8267, 0x8056, 0x8234 };
1869
u16 command_nums_fullcal[] = {
1870
0x7a97, 0x7a97, 0x7a97, 0x7a87, 0x7a87, 0x7b97 };
1872
u16 command_nums_recal[] = {
1873
0x7a97, 0x7a97, 0x7a97, 0x7a87, 0x7a87, 0x7b97 };
1874
u16 *command_nums = command_nums_fullcal;
1876
u16 *start_coeffs = NULL, *cal_cmds = NULL, cal_type, diq_start;
1877
u16 tx_pwr_ctrl_old, save_txpwrctrlrfctrl2;
1878
u16 save_sslpnCalibClkEnCtrl, save_sslpnRxFeClkEnCtrl;
1879
bool tx_gain_override_old;
1880
lcnphy_txgains_t old_gains;
1881
uint i, n_cal_cmds = 0, n_cal_start = 0;
1882
u16 *values_to_save;
1883
phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
1885
if (NORADIO_ENAB(pi->pubpi))
1888
values_to_save = kmalloc(sizeof(u16) * 20, GFP_ATOMIC);
1889
if (NULL == values_to_save) {
1893
save_sslpnRxFeClkEnCtrl = read_phy_reg(pi, 0x6db);
1894
save_sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da);
1896
or_phy_reg(pi, 0x6da, 0x40);
1897
or_phy_reg(pi, 0x6db, 0x3);
1900
case LCNPHY_CAL_FULL:
1901
start_coeffs = syst_coeffs;
1902
cal_cmds = commands_fullcal;
1903
n_cal_cmds = ARRAY_SIZE(commands_fullcal);
1906
case LCNPHY_CAL_RECAL:
1907
ASSERT(pi_lcn->lcnphy_cal_results.txiqlocal_bestcoeffs_valid);
1909
start_coeffs = syst_coeffs;
1911
cal_cmds = commands_recal;
1912
n_cal_cmds = ARRAY_SIZE(commands_recal);
1913
command_nums = command_nums_recal;
1919
wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
1920
start_coeffs, 11, 16, 64);
1922
write_phy_reg(pi, 0x6da, 0xffff);
1923
mod_phy_reg(pi, 0x503, (0x1 << 3), (1) << 3);
1925
tx_pwr_ctrl_old = wlc_lcnphy_get_tx_pwr_ctrl(pi);
1927
mod_phy_reg(pi, 0x4a4, (0x1 << 12), (1) << 12);
1929
wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
1931
save_txpwrctrlrfctrl2 = read_phy_reg(pi, 0x4db);
1933
mod_phy_reg(pi, 0x4db, (0x3ff << 0), (0x2a6) << 0);
1935
mod_phy_reg(pi, 0x4db, (0x7 << 12), (2) << 12);
1937
wlc_lcnphy_tx_iqlo_loopback(pi, values_to_save);
1939
tx_gain_override_old = wlc_lcnphy_tx_gain_override_enabled(pi);
1940
if (tx_gain_override_old)
1941
wlc_lcnphy_get_tx_gain(pi, &old_gains);
1943
if (!target_gains) {
1944
if (!tx_gain_override_old)
1945
wlc_lcnphy_set_tx_pwr_by_index(pi,
1946
pi_lcn->lcnphy_tssi_idx);
1947
wlc_lcnphy_get_tx_gain(pi, &temp_gains);
1948
target_gains = &temp_gains;
1951
hash = (target_gains->gm_gain << 8) |
1952
(target_gains->pga_gain << 4) | (target_gains->pad_gain);
1954
band_idx = (CHSPEC_IS5G(pi->radio_chanspec) ? 1 : 0);
1956
cal_gains = *target_gains;
1957
memset(ncorr_override, 0, sizeof(ncorr_override));
1958
for (j = 0; j < iqcal_gainparams_numgains_lcnphy[band_idx]; j++) {
1959
if (hash == tbl_iqcal_gainparams_lcnphy[band_idx][j][0]) {
1961
tbl_iqcal_gainparams_lcnphy[band_idx][j][1];
1962
cal_gains.pga_gain =
1963
tbl_iqcal_gainparams_lcnphy[band_idx][j][2];
1964
cal_gains.pad_gain =
1965
tbl_iqcal_gainparams_lcnphy[band_idx][j][3];
1966
memcpy(ncorr_override,
1967
&tbl_iqcal_gainparams_lcnphy[band_idx][j][3],
1968
sizeof(ncorr_override));
1973
wlc_lcnphy_set_tx_gain(pi, &cal_gains);
1975
write_phy_reg(pi, 0x453, 0xaa9);
1976
write_phy_reg(pi, 0x93d, 0xc0);
1978
wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
1980
lcnphy_iqcal_loft_gainladder,
1981
ARRAY_SIZE(lcnphy_iqcal_loft_gainladder),
1984
wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
1985
(const void *)lcnphy_iqcal_ir_gainladder,
1986
ARRAY_SIZE(lcnphy_iqcal_ir_gainladder), 16,
1989
if (pi->phy_tx_tone_freq) {
1991
wlc_lcnphy_stop_tx_tone(pi);
1993
wlc_lcnphy_start_tx_tone(pi, 3750, 88, 1);
1995
wlc_lcnphy_start_tx_tone(pi, 3750, 88, 1);
1998
write_phy_reg(pi, 0x6da, 0xffff);
2000
for (i = n_cal_start; i < n_cal_cmds; i++) {
2002
u16 best_coeffs[11];
2005
cal_type = (cal_cmds[i] & 0x0f00) >> 8;
2007
command_num = command_nums[i];
2008
if (ncorr_override[cal_type])
2010
ncorr_override[cal_type] << 8 | (command_num &
2013
write_phy_reg(pi, 0x452, command_num);
2015
if ((cal_type == 3) || (cal_type == 4)) {
2017
wlc_lcnphy_common_read_table(pi, LCNPHY_TBL_ID_IQLOCAL,
2018
&diq_start, 1, 16, 69);
2020
wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
2021
&zero_diq, 1, 16, 69);
2024
write_phy_reg(pi, 0x451, cal_cmds[i]);
2026
if (!wlc_lcnphy_iqcal_wait(pi)) {
2031
wlc_lcnphy_common_read_table(pi, LCNPHY_TBL_ID_IQLOCAL,
2033
ARRAY_SIZE(best_coeffs), 16, 96);
2034
wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
2036
ARRAY_SIZE(best_coeffs), 16, 64);
2038
if ((cal_type == 3) || (cal_type == 4)) {
2039
wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
2040
&diq_start, 1, 16, 69);
2042
wlc_lcnphy_common_read_table(pi, LCNPHY_TBL_ID_IQLOCAL,
2043
pi_lcn->lcnphy_cal_results.
2044
txiqlocal_bestcoeffs,
2047
txiqlocal_bestcoeffs),
2051
wlc_lcnphy_common_read_table(pi, LCNPHY_TBL_ID_IQLOCAL,
2052
pi_lcn->lcnphy_cal_results.
2053
txiqlocal_bestcoeffs,
2054
ARRAY_SIZE(pi_lcn->lcnphy_cal_results.
2055
txiqlocal_bestcoeffs), 16, 96);
2056
pi_lcn->lcnphy_cal_results.txiqlocal_bestcoeffs_valid = true;
2058
wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
2059
&pi_lcn->lcnphy_cal_results.
2060
txiqlocal_bestcoeffs[0], 4, 16, 80);
2062
wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
2063
&pi_lcn->lcnphy_cal_results.
2064
txiqlocal_bestcoeffs[5], 2, 16, 85);
2067
wlc_lcnphy_tx_iqlo_loopback_cleanup(pi, values_to_save);
2068
kfree(values_to_save);
2071
wlc_lcnphy_stop_tx_tone(pi);
2073
write_phy_reg(pi, 0x4db, save_txpwrctrlrfctrl2);
2075
write_phy_reg(pi, 0x453, 0);
2077
if (tx_gain_override_old)
2078
wlc_lcnphy_set_tx_gain(pi, &old_gains);
2079
wlc_lcnphy_set_tx_pwr_ctrl(pi, tx_pwr_ctrl_old);
2081
write_phy_reg(pi, 0x6da, save_sslpnCalibClkEnCtrl);
2082
write_phy_reg(pi, 0x6db, save_sslpnRxFeClkEnCtrl);
2086
static void wlc_lcnphy_idle_tssi_est(wlc_phy_t *ppi)
2088
bool suspend, tx_gain_override_old;
2089
lcnphy_txgains_t old_gains;
2090
phy_info_t *pi = (phy_info_t *) ppi;
2091
u16 idleTssi, idleTssi0_2C, idleTssi0_OB, idleTssi0_regvalue_OB,
2092
idleTssi0_regvalue_2C;
2093
u16 SAVE_txpwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
2094
u16 SAVE_lpfgain = read_radio_reg(pi, RADIO_2064_REG112);
2095
u16 SAVE_jtag_bb_afe_switch =
2096
read_radio_reg(pi, RADIO_2064_REG007) & 1;
2097
u16 SAVE_jtag_auxpga = read_radio_reg(pi, RADIO_2064_REG0FF) & 0x10;
2098
u16 SAVE_iqadc_aux_en = read_radio_reg(pi, RADIO_2064_REG11F) & 4;
2099
idleTssi = read_phy_reg(pi, 0x4ab);
2102
(R_REG(&((phy_info_t *) pi)->regs->maccontrol) &
2105
wlapi_suspend_mac_and_wait(pi->sh->physhim);
2106
wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
2108
tx_gain_override_old = wlc_lcnphy_tx_gain_override_enabled(pi);
2109
wlc_lcnphy_get_tx_gain(pi, &old_gains);
2111
wlc_lcnphy_enable_tx_gain_override(pi);
2112
wlc_lcnphy_set_tx_pwr_by_index(pi, 127);
2113
write_radio_reg(pi, RADIO_2064_REG112, 0x6);
2114
mod_radio_reg(pi, RADIO_2064_REG007, 0x1, 1);
2115
mod_radio_reg(pi, RADIO_2064_REG0FF, 0x10, 1 << 4);
2116
mod_radio_reg(pi, RADIO_2064_REG11F, 0x4, 1 << 2);
2117
wlc_lcnphy_tssi_setup(pi);
2118
wlc_phy_do_dummy_tx(pi, true, OFF);
2119
idleTssi = ((read_phy_reg(pi, 0x4ab) & (0x1ff << 0))
2122
idleTssi0_2C = ((read_phy_reg(pi, 0x63e) & (0x1ff << 0))
2125
if (idleTssi0_2C >= 256)
2126
idleTssi0_OB = idleTssi0_2C - 256;
2128
idleTssi0_OB = idleTssi0_2C + 256;
2130
idleTssi0_regvalue_OB = idleTssi0_OB;
2131
if (idleTssi0_regvalue_OB >= 256)
2132
idleTssi0_regvalue_2C = idleTssi0_regvalue_OB - 256;
2134
idleTssi0_regvalue_2C = idleTssi0_regvalue_OB + 256;
2135
mod_phy_reg(pi, 0x4a6, (0x1ff << 0), (idleTssi0_regvalue_2C) << 0);
2137
mod_phy_reg(pi, 0x44c, (0x1 << 12), (0) << 12);
2139
wlc_lcnphy_set_tx_gain_override(pi, tx_gain_override_old);
2140
wlc_lcnphy_set_tx_gain(pi, &old_gains);
2141
wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_txpwrctrl);
2143
write_radio_reg(pi, RADIO_2064_REG112, SAVE_lpfgain);
2144
mod_radio_reg(pi, RADIO_2064_REG007, 0x1, SAVE_jtag_bb_afe_switch);
2145
mod_radio_reg(pi, RADIO_2064_REG0FF, 0x10, SAVE_jtag_auxpga);
2146
mod_radio_reg(pi, RADIO_2064_REG11F, 0x4, SAVE_iqadc_aux_en);
2147
mod_radio_reg(pi, RADIO_2064_REG112, 0x80, 1 << 7);
2149
wlapi_enable_mac(pi->sh->physhim);
2152
static void wlc_lcnphy_vbat_temp_sense_setup(phy_info_t *pi, u8 mode)
2155
u16 save_txpwrCtrlEn;
2156
u8 auxpga_vmidcourse, auxpga_vmidfine, auxpga_gain;
2160
u8 save_reg007, save_reg0FF, save_reg11F, save_reg005, save_reg025,
2162
u16 values_to_save[14];
2165
phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
2168
save_reg007 = (u8) read_radio_reg(pi, RADIO_2064_REG007);
2169
save_reg0FF = (u8) read_radio_reg(pi, RADIO_2064_REG0FF);
2170
save_reg11F = (u8) read_radio_reg(pi, RADIO_2064_REG11F);
2171
save_reg005 = (u8) read_radio_reg(pi, RADIO_2064_REG005);
2172
save_reg025 = (u8) read_radio_reg(pi, RADIO_2064_REG025);
2173
save_reg112 = (u8) read_radio_reg(pi, RADIO_2064_REG112);
2175
for (i = 0; i < 14; i++)
2176
values_to_save[i] = read_phy_reg(pi, tempsense_phy_regs[i]);
2178
(0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
2180
wlapi_suspend_mac_and_wait(pi->sh->physhim);
2181
save_txpwrCtrlEn = read_radio_reg(pi, 0x4a4);
2183
wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
2184
index = pi_lcn->lcnphy_current_index;
2185
wlc_lcnphy_set_tx_pwr_by_index(pi, 127);
2186
mod_radio_reg(pi, RADIO_2064_REG007, 0x1, 0x1);
2187
mod_radio_reg(pi, RADIO_2064_REG0FF, 0x10, 0x1 << 4);
2188
mod_radio_reg(pi, RADIO_2064_REG11F, 0x4, 0x1 << 2);
2189
mod_phy_reg(pi, 0x503, (0x1 << 0), (0) << 0);
2191
mod_phy_reg(pi, 0x503, (0x1 << 2), (0) << 2);
2193
mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0) << 14);
2195
mod_phy_reg(pi, 0x4a4, (0x1 << 15), (0) << 15);
2197
mod_phy_reg(pi, 0x4d0, (0x1 << 5), (0) << 5);
2199
mod_phy_reg(pi, 0x4a5, (0xff << 0), (255) << 0);
2201
mod_phy_reg(pi, 0x4a5, (0x7 << 12), (5) << 12);
2203
mod_phy_reg(pi, 0x4a5, (0x7 << 8), (0) << 8);
2205
mod_phy_reg(pi, 0x40d, (0xff << 0), (64) << 0);
2207
mod_phy_reg(pi, 0x40d, (0x7 << 8), (6) << 8);
2209
mod_phy_reg(pi, 0x4a2, (0xff << 0), (64) << 0);
2211
mod_phy_reg(pi, 0x4a2, (0x7 << 8), (6) << 8);
2213
mod_phy_reg(pi, 0x4d9, (0x7 << 4), (2) << 4);
2215
mod_phy_reg(pi, 0x4d9, (0x7 << 8), (3) << 8);
2217
mod_phy_reg(pi, 0x4d9, (0x7 << 12), (1) << 12);
2219
mod_phy_reg(pi, 0x4da, (0x1 << 12), (0) << 12);
2221
mod_phy_reg(pi, 0x4da, (0x1 << 13), (1) << 13);
2223
mod_phy_reg(pi, 0x4a6, (0x1 << 15), (1) << 15);
2225
write_radio_reg(pi, RADIO_2064_REG025, 0xC);
2227
mod_radio_reg(pi, RADIO_2064_REG005, 0x8, 0x1 << 3);
2229
mod_phy_reg(pi, 0x938, (0x1 << 2), (1) << 2);
2231
mod_phy_reg(pi, 0x939, (0x1 << 2), (1) << 2);
2233
mod_phy_reg(pi, 0x4a4, (0x1 << 12), (1) << 12);
2235
val = wlc_lcnphy_rfseq_tbl_adc_pwrup(pi);
2236
tab.tbl_id = LCNPHY_TBL_ID_RFSEQ;
2241
wlc_lcnphy_write_table(pi, &tab);
2242
if (mode == TEMPSENSE) {
2243
mod_phy_reg(pi, 0x4d7, (0x1 << 3), (1) << 3);
2245
mod_phy_reg(pi, 0x4d7, (0x7 << 12), (1) << 12);
2247
auxpga_vmidcourse = 8;
2248
auxpga_vmidfine = 0x4;
2250
mod_radio_reg(pi, RADIO_2064_REG082, 0x20, 1 << 5);
2252
mod_phy_reg(pi, 0x4d7, (0x1 << 3), (1) << 3);
2254
mod_phy_reg(pi, 0x4d7, (0x7 << 12), (3) << 12);
2256
auxpga_vmidcourse = 7;
2257
auxpga_vmidfine = 0xa;
2261
(u16) ((2 << 8) | (auxpga_vmidcourse << 4) | auxpga_vmidfine);
2262
mod_phy_reg(pi, 0x4d8, (0x1 << 0), (1) << 0);
2264
mod_phy_reg(pi, 0x4d8, (0x3ff << 2), (auxpga_vmid) << 2);
2266
mod_phy_reg(pi, 0x4d8, (0x1 << 1), (1) << 1);
2268
mod_phy_reg(pi, 0x4d8, (0x7 << 12), (auxpga_gain) << 12);
2270
mod_phy_reg(pi, 0x4d0, (0x1 << 5), (1) << 5);
2272
write_radio_reg(pi, RADIO_2064_REG112, 0x6);
2274
wlc_phy_do_dummy_tx(pi, true, OFF);
2275
if (!tempsense_done(pi))
2278
write_radio_reg(pi, RADIO_2064_REG007, (u16) save_reg007);
2279
write_radio_reg(pi, RADIO_2064_REG0FF, (u16) save_reg0FF);
2280
write_radio_reg(pi, RADIO_2064_REG11F, (u16) save_reg11F);
2281
write_radio_reg(pi, RADIO_2064_REG005, (u16) save_reg005);
2282
write_radio_reg(pi, RADIO_2064_REG025, (u16) save_reg025);
2283
write_radio_reg(pi, RADIO_2064_REG112, (u16) save_reg112);
2284
for (i = 0; i < 14; i++)
2285
write_phy_reg(pi, tempsense_phy_regs[i], values_to_save[i]);
2286
wlc_lcnphy_set_tx_pwr_by_index(pi, (int)index);
2288
write_radio_reg(pi, 0x4a4, save_txpwrCtrlEn);
2290
wlapi_enable_mac(pi->sh->physhim);
2294
void WLBANDINITFN(wlc_lcnphy_tx_pwr_ctrl_init) (wlc_phy_t *ppi)
2296
lcnphy_txgains_t tx_gains;
2300
s32 tssi, pwr, maxtargetpwr, mintargetpwr;
2302
phy_info_t *pi = (phy_info_t *) ppi;
2305
(0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
2307
wlapi_suspend_mac_and_wait(pi->sh->physhim);
2309
if (NORADIO_ENAB(pi->pubpi)) {
2310
wlc_lcnphy_set_bbmult(pi, 0x30);
2312
wlapi_enable_mac(pi->sh->physhim);
2316
if (!pi->hwpwrctrl_capable) {
2317
if (CHSPEC_IS2G(pi->radio_chanspec)) {
2318
tx_gains.gm_gain = 4;
2319
tx_gains.pga_gain = 12;
2320
tx_gains.pad_gain = 12;
2321
tx_gains.dac_gain = 0;
2325
tx_gains.gm_gain = 7;
2326
tx_gains.pga_gain = 15;
2327
tx_gains.pad_gain = 14;
2328
tx_gains.dac_gain = 0;
2332
wlc_lcnphy_set_tx_gain(pi, &tx_gains);
2333
wlc_lcnphy_set_bbmult(pi, bbmult);
2334
wlc_lcnphy_vbat_temp_sense_setup(pi, TEMPSENSE);
2337
wlc_lcnphy_idle_tssi_est(ppi);
2339
wlc_lcnphy_clear_tx_power_offsets(pi);
2341
b0 = pi->txpa_2g[0];
2342
b1 = pi->txpa_2g[1];
2343
a1 = pi->txpa_2g[2];
2344
maxtargetpwr = wlc_lcnphy_tssi2dbm(10, a1, b0, b1);
2345
mintargetpwr = wlc_lcnphy_tssi2dbm(125, a1, b0, b1);
2347
tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
2352
for (tssi = 0; tssi < 128; tssi++) {
2353
pwr = wlc_lcnphy_tssi2dbm(tssi, a1, b0, b1);
2355
pwr = (pwr < mintargetpwr) ? mintargetpwr : pwr;
2356
wlc_lcnphy_write_table(pi, &tab);
2360
mod_phy_reg(pi, 0x410, (0x1 << 7), (0) << 7);
2362
write_phy_reg(pi, 0x4a8, 10);
2364
wlc_lcnphy_set_target_tx_pwr(pi, LCN_TARGET_PWR);
2366
wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_HW);
2369
wlapi_enable_mac(pi->sh->physhim);
2372
static u8 wlc_lcnphy_get_bbmult(phy_info_t *pi)
2377
tab.tbl_ptr = &m0m1;
2379
tab.tbl_id = LCNPHY_TBL_ID_IQLOCAL;
2380
tab.tbl_offset = 87;
2382
wlc_lcnphy_read_table(pi, &tab);
2384
return (u8) ((m0m1 & 0xff00) >> 8);
2387
static void wlc_lcnphy_set_pa_gain(phy_info_t *pi, u16 gain)
2389
mod_phy_reg(pi, 0x4fb,
2390
LCNPHY_txgainctrlovrval1_pagain_ovr_val1_MASK,
2391
gain << LCNPHY_txgainctrlovrval1_pagain_ovr_val1_SHIFT);
2392
mod_phy_reg(pi, 0x4fd,
2393
LCNPHY_stxtxgainctrlovrval1_pagain_ovr_val1_MASK,
2394
gain << LCNPHY_stxtxgainctrlovrval1_pagain_ovr_val1_SHIFT);
2398
wlc_lcnphy_get_radio_loft(phy_info_t *pi,
2399
u8 *ei0, u8 *eq0, u8 *fi0, u8 *fq0)
2401
*ei0 = LCNPHY_IQLOCC_READ(read_radio_reg(pi, RADIO_2064_REG089));
2402
*eq0 = LCNPHY_IQLOCC_READ(read_radio_reg(pi, RADIO_2064_REG08A));
2403
*fi0 = LCNPHY_IQLOCC_READ(read_radio_reg(pi, RADIO_2064_REG08B));
2404
*fq0 = LCNPHY_IQLOCC_READ(read_radio_reg(pi, RADIO_2064_REG08C));
2407
static void wlc_lcnphy_get_tx_gain(phy_info_t *pi, lcnphy_txgains_t *gains)
2411
dac_gain = read_phy_reg(pi, 0x439) >> 0;
2412
gains->dac_gain = (dac_gain & 0x380) >> 7;
2415
u16 rfgain0, rfgain1;
2417
rfgain0 = (read_phy_reg(pi, 0x4b5) & (0xffff << 0)) >> 0;
2418
rfgain1 = (read_phy_reg(pi, 0x4fb) & (0x7fff << 0)) >> 0;
2420
gains->gm_gain = rfgain0 & 0xff;
2421
gains->pga_gain = (rfgain0 >> 8) & 0xff;
2422
gains->pad_gain = rfgain1 & 0xff;
2426
void wlc_lcnphy_set_tx_iqcc(phy_info_t *pi, u16 a, u16 b)
2434
tab.tbl_id = LCNPHY_TBL_ID_IQLOCAL;
2438
tab.tbl_offset = 80;
2439
wlc_lcnphy_write_table(pi, &tab);
2442
void wlc_lcnphy_set_tx_locc(phy_info_t *pi, u16 didq)
2446
tab.tbl_id = LCNPHY_TBL_ID_IQLOCAL;
2448
tab.tbl_ptr = &didq;
2450
tab.tbl_offset = 85;
2451
wlc_lcnphy_write_table(pi, &tab);
2454
void wlc_lcnphy_set_tx_pwr_by_index(phy_info_t *pi, int index)
2459
u32 bbmultiqcomp, txgain, locoeffs, rfpower;
2460
lcnphy_txgains_t gains;
2461
phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
2463
ASSERT(index <= LCNPHY_MAX_TX_POWER_INDEX);
2465
pi_lcn->lcnphy_tx_power_idx_override = (s8) index;
2466
pi_lcn->lcnphy_current_index = (u8) index;
2468
tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
2472
wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
2474
tab.tbl_offset = LCNPHY_TX_PWR_CTRL_IQ_OFFSET + index;
2475
tab.tbl_ptr = &bbmultiqcomp;
2476
wlc_lcnphy_read_table(pi, &tab);
2478
tab.tbl_offset = LCNPHY_TX_PWR_CTRL_GAIN_OFFSET + index;
2480
tab.tbl_ptr = &txgain;
2481
wlc_lcnphy_read_table(pi, &tab);
2483
gains.gm_gain = (u16) (txgain & 0xff);
2484
gains.pga_gain = (u16) (txgain >> 8) & 0xff;
2485
gains.pad_gain = (u16) (txgain >> 16) & 0xff;
2486
gains.dac_gain = (u16) (bbmultiqcomp >> 28) & 0x07;
2487
wlc_lcnphy_set_tx_gain(pi, &gains);
2488
wlc_lcnphy_set_pa_gain(pi, (u16) (txgain >> 24) & 0x7f);
2490
bb_mult = (u8) ((bbmultiqcomp >> 20) & 0xff);
2491
wlc_lcnphy_set_bbmult(pi, bb_mult);
2493
wlc_lcnphy_enable_tx_gain_override(pi);
2495
if (!wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) {
2497
a = (u16) ((bbmultiqcomp >> 10) & 0x3ff);
2498
b = (u16) (bbmultiqcomp & 0x3ff);
2499
wlc_lcnphy_set_tx_iqcc(pi, a, b);
2501
tab.tbl_offset = LCNPHY_TX_PWR_CTRL_LO_OFFSET + index;
2502
tab.tbl_ptr = &locoeffs;
2503
wlc_lcnphy_read_table(pi, &tab);
2505
wlc_lcnphy_set_tx_locc(pi, (u16) locoeffs);
2507
tab.tbl_offset = LCNPHY_TX_PWR_CTRL_PWR_OFFSET + index;
2508
tab.tbl_ptr = &rfpower;
2509
wlc_lcnphy_read_table(pi, &tab);
2510
mod_phy_reg(pi, 0x6a6, (0x1fff << 0), (rfpower * 8) << 0);
2515
static void wlc_lcnphy_set_trsw_override(phy_info_t *pi, bool tx, bool rx)
2518
mod_phy_reg(pi, 0x44d,
2520
(0x1 << 0), (tx ? (0x1 << 1) : 0) | (rx ? (0x1 << 0) : 0));
2522
or_phy_reg(pi, 0x44c, (0x1 << 1) | (0x1 << 0));
2525
static void wlc_lcnphy_clear_papd_comptable(phy_info_t *pi)
2529
u32 temp_offset[128];
2530
tab.tbl_ptr = temp_offset;
2532
tab.tbl_id = LCNPHY_TBL_ID_PAPDCOMPDELTATBL;
2536
memset(temp_offset, 0, sizeof(temp_offset));
2537
for (j = 1; j < 128; j += 2)
2538
temp_offset[j] = 0x80000;
2540
wlc_lcnphy_write_table(pi, &tab);
2545
wlc_lcnphy_set_rx_gain_by_distribution(phy_info_t *pi,
2550
u16 tia, u16 lna2, u16 lna1)
2552
u16 gain0_15, gain16_19;
2554
gain16_19 = biq2 & 0xf;
2555
gain0_15 = ((biq1 & 0xf) << 12) |
2556
((tia & 0xf) << 8) |
2557
((lna2 & 0x3) << 6) |
2558
((lna2 & 0x3) << 4) | ((lna1 & 0x3) << 2) | ((lna1 & 0x3) << 0);
2560
mod_phy_reg(pi, 0x4b6, (0xffff << 0), gain0_15 << 0);
2561
mod_phy_reg(pi, 0x4b7, (0xf << 0), gain16_19 << 0);
2562
mod_phy_reg(pi, 0x4b1, (0x3 << 11), lna1 << 11);
2564
if (LCNREV_LT(pi->pubpi.phy_rev, 2)) {
2565
mod_phy_reg(pi, 0x4b1, (0x1 << 9), ext_lna << 9);
2566
mod_phy_reg(pi, 0x4b1, (0x1 << 10), ext_lna << 10);
2568
mod_phy_reg(pi, 0x4b1, (0x1 << 10), 0 << 10);
2570
mod_phy_reg(pi, 0x4b1, (0x1 << 15), 0 << 15);
2572
mod_phy_reg(pi, 0x4b1, (0x1 << 9), ext_lna << 9);
2575
mod_phy_reg(pi, 0x44d, (0x1 << 0), (!trsw) << 0);
2579
static void wlc_lcnphy_rx_gain_override_enable(phy_info_t *pi, bool enable)
2581
u16 ebit = enable ? 1 : 0;
2583
mod_phy_reg(pi, 0x4b0, (0x1 << 8), ebit << 8);
2585
mod_phy_reg(pi, 0x44c, (0x1 << 0), ebit << 0);
2587
if (LCNREV_LT(pi->pubpi.phy_rev, 2)) {
2588
mod_phy_reg(pi, 0x44c, (0x1 << 4), ebit << 4);
2589
mod_phy_reg(pi, 0x44c, (0x1 << 6), ebit << 6);
2590
mod_phy_reg(pi, 0x4b0, (0x1 << 5), ebit << 5);
2591
mod_phy_reg(pi, 0x4b0, (0x1 << 6), ebit << 6);
2593
mod_phy_reg(pi, 0x4b0, (0x1 << 12), ebit << 12);
2594
mod_phy_reg(pi, 0x4b0, (0x1 << 13), ebit << 13);
2595
mod_phy_reg(pi, 0x4b0, (0x1 << 5), ebit << 5);
2598
if (CHSPEC_IS2G(pi->radio_chanspec)) {
2599
mod_phy_reg(pi, 0x4b0, (0x1 << 10), ebit << 10);
2600
mod_phy_reg(pi, 0x4e5, (0x1 << 3), ebit << 3);
2604
void wlc_lcnphy_tx_pu(phy_info_t *pi, bool bEnable)
2608
and_phy_reg(pi, 0x43b, ~(u16) ((0x1 << 1) | (0x1 << 4)));
2610
mod_phy_reg(pi, 0x43c, (0x1 << 1), 1 << 1);
2612
and_phy_reg(pi, 0x44c,
2613
~(u16) ((0x1 << 3) |
2616
(0x1 << 0) | (0x1 << 1) | (0x1 << 2)));
2618
and_phy_reg(pi, 0x44d,
2619
~(u16) ((0x1 << 3) | (0x1 << 5) | (0x1 << 14)));
2620
mod_phy_reg(pi, 0x44d, (0x1 << 2), 1 << 2);
2622
mod_phy_reg(pi, 0x44d, (0x1 << 1) | (0x1 << 0), (0x1 << 0));
2624
and_phy_reg(pi, 0x4f9,
2625
~(u16) ((0x1 << 0) | (0x1 << 1) | (0x1 << 2)));
2627
and_phy_reg(pi, 0x4fa,
2628
~(u16) ((0x1 << 0) | (0x1 << 1) | (0x1 << 2)));
2631
mod_phy_reg(pi, 0x43b, (0x1 << 1), 1 << 1);
2632
mod_phy_reg(pi, 0x43c, (0x1 << 1), 0 << 1);
2634
mod_phy_reg(pi, 0x43b, (0x1 << 4), 1 << 4);
2635
mod_phy_reg(pi, 0x43c, (0x1 << 6), 0 << 6);
2637
mod_phy_reg(pi, 0x44c, (0x1 << 12), 1 << 12);
2638
mod_phy_reg(pi, 0x44d, (0x1 << 14), 1 << 14);
2640
wlc_lcnphy_set_trsw_override(pi, true, false);
2642
mod_phy_reg(pi, 0x44d, (0x1 << 2), 0 << 2);
2643
mod_phy_reg(pi, 0x44c, (0x1 << 2), 1 << 2);
2645
if (CHSPEC_IS2G(pi->radio_chanspec)) {
2647
mod_phy_reg(pi, 0x44c, (0x1 << 3), 1 << 3);
2648
mod_phy_reg(pi, 0x44d, (0x1 << 3), 1 << 3);
2650
mod_phy_reg(pi, 0x44c, (0x1 << 5), 1 << 5);
2651
mod_phy_reg(pi, 0x44d, (0x1 << 5), 0 << 5);
2653
mod_phy_reg(pi, 0x4f9, (0x1 << 1), 1 << 1);
2654
mod_phy_reg(pi, 0x4fa, (0x1 << 1), 1 << 1);
2656
mod_phy_reg(pi, 0x4f9, (0x1 << 2), 1 << 2);
2657
mod_phy_reg(pi, 0x4fa, (0x1 << 2), 1 << 2);
2659
mod_phy_reg(pi, 0x4f9, (0x1 << 0), 1 << 0);
2660
mod_phy_reg(pi, 0x4fa, (0x1 << 0), 1 << 0);
2663
mod_phy_reg(pi, 0x44c, (0x1 << 3), 1 << 3);
2664
mod_phy_reg(pi, 0x44d, (0x1 << 3), 0 << 3);
2666
mod_phy_reg(pi, 0x44c, (0x1 << 5), 1 << 5);
2667
mod_phy_reg(pi, 0x44d, (0x1 << 5), 1 << 5);
2669
mod_phy_reg(pi, 0x4f9, (0x1 << 1), 1 << 1);
2670
mod_phy_reg(pi, 0x4fa, (0x1 << 1), 0 << 1);
2672
mod_phy_reg(pi, 0x4f9, (0x1 << 2), 1 << 2);
2673
mod_phy_reg(pi, 0x4fa, (0x1 << 2), 0 << 2);
2675
mod_phy_reg(pi, 0x4f9, (0x1 << 0), 1 << 0);
2676
mod_phy_reg(pi, 0x4fa, (0x1 << 0), 0 << 0);
2682
wlc_lcnphy_run_samples(phy_info_t *pi,
2684
u16 num_loops, u16 wait, bool iqcalmode)
2687
or_phy_reg(pi, 0x6da, 0x8080);
2689
mod_phy_reg(pi, 0x642, (0x7f << 0), (num_samps - 1) << 0);
2690
if (num_loops != 0xffff)
2692
mod_phy_reg(pi, 0x640, (0xffff << 0), num_loops << 0);
2694
mod_phy_reg(pi, 0x641, (0xffff << 0), wait << 0);
2698
and_phy_reg(pi, 0x453, (u16) ~(0x1 << 15));
2699
or_phy_reg(pi, 0x453, (0x1 << 15));
2701
write_phy_reg(pi, 0x63f, 1);
2702
wlc_lcnphy_tx_pu(pi, 1);
2705
or_radio_reg(pi, RADIO_2064_REG112, 0x6);
2708
void wlc_lcnphy_deaf_mode(phy_info_t *pi, bool mode)
2712
phybw40 = CHSPEC_IS40(pi->radio_chanspec);
2714
if (LCNREV_LT(pi->pubpi.phy_rev, 2)) {
2715
mod_phy_reg(pi, 0x4b0, (0x1 << 5), (mode) << 5);
2716
mod_phy_reg(pi, 0x4b1, (0x1 << 9), 0 << 9);
2718
mod_phy_reg(pi, 0x4b0, (0x1 << 5), (mode) << 5);
2719
mod_phy_reg(pi, 0x4b1, (0x1 << 9), 0 << 9);
2723
mod_phy_reg((pi), 0x410,
2726
((CHSPEC_IS2G(pi->radio_chanspec)) ? (!mode) : 0) <<
2728
mod_phy_reg(pi, 0x410, (0x1 << 7), (mode) << 7);
2733
wlc_lcnphy_start_tx_tone(phy_info_t *pi, s32 f_kHz, u16 max_val,
2737
u16 num_samps, t, k;
2739
fixed theta = 0, rot = 0;
2744
phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
2746
pi->phy_tx_tone_freq = f_kHz;
2748
wlc_lcnphy_deaf_mode(pi, true);
2751
if (pi_lcn->lcnphy_spurmod) {
2752
write_phy_reg(pi, 0x942, 0x2);
2753
write_phy_reg(pi, 0x93b, 0x0);
2754
write_phy_reg(pi, 0x93c, 0x0);
2755
wlc_lcnphy_txrx_spur_avoidance_mode(pi, false);
2761
bw = phy_bw * 1000 * k;
2762
num_samps = bw / ABS(f_kHz);
2763
ASSERT(num_samps <= ARRAY_SIZE(data_buf));
2765
} while ((num_samps * (u32) (ABS(f_kHz))) != bw);
2769
rot = FIXED((f_kHz * 36) / phy_bw) / 100;
2772
for (t = 0; t < num_samps; t++) {
2774
wlc_phy_cordic(theta, &tone_samp);
2778
i_samp = (u16) (FLOAT(tone_samp.i * max_val) & 0x3ff);
2779
q_samp = (u16) (FLOAT(tone_samp.q * max_val) & 0x3ff);
2780
data_buf[t] = (i_samp << 10) | q_samp;
2783
mod_phy_reg(pi, 0x6d6, (0x3 << 0), 0 << 0);
2785
mod_phy_reg(pi, 0x6da, (0x1 << 3), 1 << 3);
2787
tab.tbl_ptr = data_buf;
2788
tab.tbl_len = num_samps;
2789
tab.tbl_id = LCNPHY_TBL_ID_SAMPLEPLAY;
2792
wlc_lcnphy_write_table(pi, &tab);
2794
wlc_lcnphy_run_samples(pi, num_samps, 0xffff, 0, iqcalmode);
2797
void wlc_lcnphy_stop_tx_tone(phy_info_t *pi)
2799
s16 playback_status;
2800
phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
2802
pi->phy_tx_tone_freq = 0;
2803
if (pi_lcn->lcnphy_spurmod) {
2804
write_phy_reg(pi, 0x942, 0x7);
2805
write_phy_reg(pi, 0x93b, 0x2017);
2806
write_phy_reg(pi, 0x93c, 0x27c5);
2807
wlc_lcnphy_txrx_spur_avoidance_mode(pi, true);
2810
playback_status = read_phy_reg(pi, 0x644);
2811
if (playback_status & (0x1 << 0)) {
2812
wlc_lcnphy_tx_pu(pi, 0);
2813
mod_phy_reg(pi, 0x63f, (0x1 << 1), 1 << 1);
2814
} else if (playback_status & (0x1 << 1))
2815
mod_phy_reg(pi, 0x453, (0x1 << 15), 0 << 15);
2817
mod_phy_reg(pi, 0x6d6, (0x3 << 0), 1 << 0);
2819
mod_phy_reg(pi, 0x6da, (0x1 << 3), 0 << 3);
2821
mod_phy_reg(pi, 0x6da, (0x1 << 7), 0 << 7);
2823
and_radio_reg(pi, RADIO_2064_REG112, 0xFFF9);
2825
wlc_lcnphy_deaf_mode(pi, false);
2828
static void wlc_lcnphy_clear_trsw_override(phy_info_t *pi)
2831
and_phy_reg(pi, 0x44c, (u16) ~((0x1 << 1) | (0x1 << 0)));
2834
void wlc_lcnphy_get_tx_iqcc(phy_info_t *pi, u16 *a, u16 *b)
2842
tab.tbl_offset = 80;
2844
wlc_lcnphy_read_table(pi, &tab);
2850
u16 wlc_lcnphy_get_tx_locc(phy_info_t *pi)
2857
tab.tbl_ptr = &didq;
2859
tab.tbl_offset = 85;
2860
wlc_lcnphy_read_table(pi, &tab);
2865
static void wlc_lcnphy_txpwrtbl_iqlo_cal(phy_info_t *pi)
2868
lcnphy_txgains_t target_gains, old_gains;
2870
u16 a, b, didq, save_pa_gain = 0;
2871
uint idx, SAVE_txpwrindex = 0xFF;
2873
u16 SAVE_txpwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
2875
u8 ei0, eq0, fi0, fq0;
2876
phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
2878
wlc_lcnphy_get_tx_gain(pi, &old_gains);
2879
save_pa_gain = wlc_lcnphy_get_pa_gain(pi);
2881
save_bb_mult = wlc_lcnphy_get_bbmult(pi);
2883
if (SAVE_txpwrctrl == LCNPHY_TX_PWR_CTRL_OFF)
2884
SAVE_txpwrindex = wlc_lcnphy_get_current_tx_pwr_idx(pi);
2886
wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
2888
target_gains.gm_gain = 7;
2889
target_gains.pga_gain = 0;
2890
target_gains.pad_gain = 21;
2891
target_gains.dac_gain = 0;
2892
wlc_lcnphy_set_tx_gain(pi, &target_gains);
2893
wlc_lcnphy_set_tx_pwr_by_index(pi, 16);
2895
if (LCNREV_IS(pi->pubpi.phy_rev, 1) || pi_lcn->lcnphy_hw_iqcal_en) {
2897
wlc_lcnphy_set_tx_pwr_by_index(pi, 30);
2899
wlc_lcnphy_tx_iqlo_cal(pi, &target_gains,
2901
lcnphy_recal ? LCNPHY_CAL_RECAL :
2902
LCNPHY_CAL_FULL), false);
2905
wlc_lcnphy_tx_iqlo_soft_cal_full(pi);
2908
wlc_lcnphy_get_radio_loft(pi, &ei0, &eq0, &fi0, &fq0);
2909
if ((ABS((s8) fi0) == 15) && (ABS((s8) fq0) == 15)) {
2910
if (CHSPEC_IS5G(pi->radio_chanspec)) {
2911
target_gains.gm_gain = 255;
2912
target_gains.pga_gain = 255;
2913
target_gains.pad_gain = 0xf0;
2914
target_gains.dac_gain = 0;
2916
target_gains.gm_gain = 7;
2917
target_gains.pga_gain = 45;
2918
target_gains.pad_gain = 186;
2919
target_gains.dac_gain = 0;
2922
if (LCNREV_IS(pi->pubpi.phy_rev, 1)
2923
|| pi_lcn->lcnphy_hw_iqcal_en) {
2925
target_gains.pga_gain = 0;
2926
target_gains.pad_gain = 30;
2927
wlc_lcnphy_set_tx_pwr_by_index(pi, 16);
2928
wlc_lcnphy_tx_iqlo_cal(pi, &target_gains,
2929
LCNPHY_CAL_FULL, false);
2932
wlc_lcnphy_tx_iqlo_soft_cal_full(pi);
2937
wlc_lcnphy_get_tx_iqcc(pi, &a, &b);
2939
didq = wlc_lcnphy_get_tx_locc(pi);
2941
tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
2946
tab.tbl_offset = LCNPHY_TX_PWR_CTRL_RATE_OFFSET;
2948
for (idx = 0; idx < 128; idx++) {
2949
tab.tbl_offset = LCNPHY_TX_PWR_CTRL_IQ_OFFSET + idx;
2951
wlc_lcnphy_read_table(pi, &tab);
2952
val = (val & 0xfff00000) |
2953
((u32) (a & 0x3FF) << 10) | (b & 0x3ff);
2954
wlc_lcnphy_write_table(pi, &tab);
2957
tab.tbl_offset = LCNPHY_TX_PWR_CTRL_LO_OFFSET + idx;
2958
wlc_lcnphy_write_table(pi, &tab);
2961
pi_lcn->lcnphy_cal_results.txiqlocal_a = a;
2962
pi_lcn->lcnphy_cal_results.txiqlocal_b = b;
2963
pi_lcn->lcnphy_cal_results.txiqlocal_didq = didq;
2964
pi_lcn->lcnphy_cal_results.txiqlocal_ei0 = ei0;
2965
pi_lcn->lcnphy_cal_results.txiqlocal_eq0 = eq0;
2966
pi_lcn->lcnphy_cal_results.txiqlocal_fi0 = fi0;
2967
pi_lcn->lcnphy_cal_results.txiqlocal_fq0 = fq0;
2969
wlc_lcnphy_set_bbmult(pi, save_bb_mult);
2970
wlc_lcnphy_set_pa_gain(pi, save_pa_gain);
2971
wlc_lcnphy_set_tx_gain(pi, &old_gains);
2973
if (SAVE_txpwrctrl != LCNPHY_TX_PWR_CTRL_OFF)
2974
wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_txpwrctrl);
2976
wlc_lcnphy_set_tx_pwr_by_index(pi, SAVE_txpwrindex);
2979
s16 wlc_lcnphy_tempsense_new(phy_info_t *pi, bool mode)
2981
u16 tempsenseval1, tempsenseval2;
2985
if (NORADIO_ENAB(pi->pubpi))
2991
(R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
2993
wlapi_suspend_mac_and_wait(pi->sh->physhim);
2994
wlc_lcnphy_vbat_temp_sense_setup(pi, TEMPSENSE);
2996
tempsenseval1 = read_phy_reg(pi, 0x476) & 0x1FF;
2997
tempsenseval2 = read_phy_reg(pi, 0x477) & 0x1FF;
2999
if (tempsenseval1 > 255)
3000
avg = (s16) (tempsenseval1 - 512);
3002
avg = (s16) tempsenseval1;
3004
if (tempsenseval2 > 255)
3005
avg += (s16) (tempsenseval2 - 512);
3007
avg += (s16) tempsenseval2;
3013
mod_phy_reg(pi, 0x448, (0x1 << 14), (1) << 14);
3016
mod_phy_reg(pi, 0x448, (0x1 << 14), (0) << 14);
3019
wlapi_enable_mac(pi->sh->physhim);
3024
u16 wlc_lcnphy_tempsense(phy_info_t *pi, bool mode)
3026
u16 tempsenseval1, tempsenseval2;
3029
u16 SAVE_txpwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
3030
phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
3032
if (NORADIO_ENAB(pi->pubpi))
3038
(R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
3040
wlapi_suspend_mac_and_wait(pi->sh->physhim);
3041
wlc_lcnphy_vbat_temp_sense_setup(pi, TEMPSENSE);
3043
tempsenseval1 = read_phy_reg(pi, 0x476) & 0x1FF;
3044
tempsenseval2 = read_phy_reg(pi, 0x477) & 0x1FF;
3046
if (tempsenseval1 > 255)
3047
avg = (int)(tempsenseval1 - 512);
3049
avg = (int)tempsenseval1;
3051
if (pi_lcn->lcnphy_tempsense_option == 1 || pi->hwpwrctrl_capable) {
3052
if (tempsenseval2 > 255)
3053
avg = (int)(avg - tempsenseval2 + 512);
3055
avg = (int)(avg - tempsenseval2);
3057
if (tempsenseval2 > 255)
3058
avg = (int)(avg + tempsenseval2 - 512);
3060
avg = (int)(avg + tempsenseval2);
3066
if (pi_lcn->lcnphy_tempsense_option == 2)
3067
avg = tempsenseval1;
3070
wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_txpwrctrl);
3074
mod_phy_reg(pi, 0x448, (0x1 << 14), (1) << 14);
3077
mod_phy_reg(pi, 0x448, (0x1 << 14), (0) << 14);
3080
wlapi_enable_mac(pi->sh->physhim);
3085
s8 wlc_lcnphy_tempsense_degree(phy_info_t *pi, bool mode)
3087
s32 degree = wlc_lcnphy_tempsense_new(pi, mode);
3089
((degree << 10) + LCN_TEMPSENSE_OFFSET + (LCN_TEMPSENSE_DEN >> 1))
3090
/ LCN_TEMPSENSE_DEN;
3094
s8 wlc_lcnphy_vbatsense(phy_info_t *pi, bool mode)
3100
if (NORADIO_ENAB(pi->pubpi))
3106
(R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
3108
wlapi_suspend_mac_and_wait(pi->sh->physhim);
3109
wlc_lcnphy_vbat_temp_sense_setup(pi, VBATSENSE);
3112
vbatsenseval = read_phy_reg(pi, 0x475) & 0x1FF;
3114
if (vbatsenseval > 255)
3115
avg = (s32) (vbatsenseval - 512);
3117
avg = (s32) vbatsenseval;
3120
(avg * LCN_VBAT_SCALE_NOM +
3121
(LCN_VBAT_SCALE_DEN >> 1)) / LCN_VBAT_SCALE_DEN;
3125
wlapi_enable_mac(pi->sh->physhim);
3130
static void wlc_lcnphy_afe_clk_init(phy_info_t *pi, u8 mode)
3133
phybw40 = CHSPEC_IS40(pi->radio_chanspec);
3135
mod_phy_reg(pi, 0x6d1, (0x1 << 7), (1) << 7);
3137
if (((mode == AFE_CLK_INIT_MODE_PAPD) && (phybw40 == 0)) ||
3138
(mode == AFE_CLK_INIT_MODE_TXRX2X))
3139
write_phy_reg(pi, 0x6d0, 0x7);
3141
wlc_lcnphy_toggle_afe_pwdn(pi);
3145
wlc_lcnphy_rx_iq_est(phy_info_t *pi,
3147
u8 wait_time, lcnphy_iq_est_t *iq_est)
3152
phybw40 = CHSPEC_IS40(pi->radio_chanspec);
3154
mod_phy_reg(pi, 0x6da, (0x1 << 5), (1) << 5);
3156
mod_phy_reg(pi, 0x410, (0x1 << 3), (0) << 3);
3158
mod_phy_reg(pi, 0x482, (0xffff << 0), (num_samps) << 0);
3160
mod_phy_reg(pi, 0x481, (0xff << 0), ((u16) wait_time) << 0);
3162
mod_phy_reg(pi, 0x481, (0x1 << 8), (0) << 8);
3164
mod_phy_reg(pi, 0x481, (0x1 << 9), (1) << 9);
3166
while (read_phy_reg(pi, 0x481) & (0x1 << 9)) {
3168
if (wait_count > (10 * 500)) {
3176
iq_est->iq_prod = ((u32) read_phy_reg(pi, 0x483) << 16) |
3177
(u32) read_phy_reg(pi, 0x484);
3178
iq_est->i_pwr = ((u32) read_phy_reg(pi, 0x485) << 16) |
3179
(u32) read_phy_reg(pi, 0x486);
3180
iq_est->q_pwr = ((u32) read_phy_reg(pi, 0x487) << 16) |
3181
(u32) read_phy_reg(pi, 0x488);
3184
mod_phy_reg(pi, 0x410, (0x1 << 3), (1) << 3);
3186
mod_phy_reg(pi, 0x6da, (0x1 << 5), (0) << 5);
3191
static bool wlc_lcnphy_calc_rx_iq_comp(phy_info_t *pi, u16 num_samps)
3193
#define LCNPHY_MIN_RXIQ_PWR 2
3196
lcnphy_iq_est_t iq_est = { 0, 0, 0 };
3198
s16 iq_nbits, qq_nbits, arsh, brsh;
3201
phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
3203
a0_new = ((read_phy_reg(pi, 0x645) & (0x3ff << 0)) >> 0);
3204
b0_new = ((read_phy_reg(pi, 0x646) & (0x3ff << 0)) >> 0);
3205
mod_phy_reg(pi, 0x6d1, (0x1 << 2), (0) << 2);
3207
mod_phy_reg(pi, 0x64b, (0x1 << 6), (1) << 6);
3209
wlc_lcnphy_set_rx_iq_comp(pi, 0, 0);
3211
result = wlc_lcnphy_rx_iq_est(pi, num_samps, 32, &iq_est);
3215
iq = (s32) iq_est.iq_prod;
3219
if ((ii + qq) < LCNPHY_MIN_RXIQ_PWR) {
3224
iq_nbits = wlc_phy_nbits(iq);
3225
qq_nbits = wlc_phy_nbits(qq);
3227
arsh = 10 - (30 - iq_nbits);
3229
a = (-(iq << (30 - iq_nbits)) + (ii >> (1 + arsh)));
3230
temp = (s32) (ii >> arsh);
3235
a = (-(iq << (30 - iq_nbits)) + (ii << (-1 - arsh)));
3236
temp = (s32) (ii << -arsh);
3242
brsh = qq_nbits - 31 + 20;
3244
b = (qq << (31 - qq_nbits));
3245
temp = (s32) (ii >> brsh);
3250
b = (qq << (31 - qq_nbits));
3251
temp = (s32) (ii << -brsh);
3258
b = (s32) wlc_phy_sqrt_int((u32) b);
3260
a0_new = (u16) (a & 0x3ff);
3261
b0_new = (u16) (b & 0x3ff);
3264
wlc_lcnphy_set_rx_iq_comp(pi, a0_new, b0_new);
3266
mod_phy_reg(pi, 0x64b, (0x1 << 0), (1) << 0);
3268
mod_phy_reg(pi, 0x64b, (0x1 << 3), (1) << 3);
3270
pi_lcn->lcnphy_cal_results.rxiqcal_coeff_a0 = a0_new;
3271
pi_lcn->lcnphy_cal_results.rxiqcal_coeff_b0 = b0_new;
3277
wlc_lcnphy_rx_iq_cal(phy_info_t *pi, const lcnphy_rx_iqcomp_t *iqcomp,
3278
int iqcomp_sz, bool tx_switch, bool rx_switch, int module,
3281
lcnphy_txgains_t old_gains;
3283
u8 tx_gain_index_old = 0;
3284
bool result = false, tx_gain_override_old = false;
3285
u16 i, Core1TxControl_old, RFOverride0_old,
3286
RFOverrideVal0_old, rfoverride2_old, rfoverride2val_old,
3287
rfoverride3_old, rfoverride3val_old, rfoverride4_old,
3288
rfoverride4val_old, afectrlovr_old, afectrlovrval_old;
3290
u32 received_power, rx_pwr_threshold;
3291
u16 old_sslpnCalibClkEnCtrl, old_sslpnRxFeClkEnCtrl;
3292
u16 values_to_save[11];
3294
phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
3296
ptr = kmalloc(sizeof(s16) * 131, GFP_ATOMIC);
3303
while (iqcomp_sz--) {
3304
if (iqcomp[iqcomp_sz].chan ==
3305
CHSPEC_CHANNEL(pi->radio_chanspec)) {
3307
wlc_lcnphy_set_rx_iq_comp(pi,
3309
iqcomp[iqcomp_sz].a,
3311
iqcomp[iqcomp_sz].b);
3322
tx_pwr_ctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
3323
wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
3325
for (i = 0; i < 11; i++) {
3327
read_radio_reg(pi, rxiq_cal_rf_reg[i]);
3329
Core1TxControl_old = read_phy_reg(pi, 0x631);
3331
or_phy_reg(pi, 0x631, 0x0015);
3333
RFOverride0_old = read_phy_reg(pi, 0x44c);
3334
RFOverrideVal0_old = read_phy_reg(pi, 0x44d);
3335
rfoverride2_old = read_phy_reg(pi, 0x4b0);
3336
rfoverride2val_old = read_phy_reg(pi, 0x4b1);
3337
rfoverride3_old = read_phy_reg(pi, 0x4f9);
3338
rfoverride3val_old = read_phy_reg(pi, 0x4fa);
3339
rfoverride4_old = read_phy_reg(pi, 0x938);
3340
rfoverride4val_old = read_phy_reg(pi, 0x939);
3341
afectrlovr_old = read_phy_reg(pi, 0x43b);
3342
afectrlovrval_old = read_phy_reg(pi, 0x43c);
3343
old_sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da);
3344
old_sslpnRxFeClkEnCtrl = read_phy_reg(pi, 0x6db);
3346
tx_gain_override_old = wlc_lcnphy_tx_gain_override_enabled(pi);
3347
if (tx_gain_override_old) {
3348
wlc_lcnphy_get_tx_gain(pi, &old_gains);
3349
tx_gain_index_old = pi_lcn->lcnphy_current_index;
3352
wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_idx);
3354
mod_phy_reg(pi, 0x4f9, (0x1 << 0), 1 << 0);
3355
mod_phy_reg(pi, 0x4fa, (0x1 << 0), 0 << 0);
3357
mod_phy_reg(pi, 0x43b, (0x1 << 1), 1 << 1);
3358
mod_phy_reg(pi, 0x43c, (0x1 << 1), 0 << 1);
3360
write_radio_reg(pi, RADIO_2064_REG116, 0x06);
3361
write_radio_reg(pi, RADIO_2064_REG12C, 0x07);
3362
write_radio_reg(pi, RADIO_2064_REG06A, 0xd3);
3363
write_radio_reg(pi, RADIO_2064_REG098, 0x03);
3364
write_radio_reg(pi, RADIO_2064_REG00B, 0x7);
3365
mod_radio_reg(pi, RADIO_2064_REG113, 1 << 4, 1 << 4);
3366
write_radio_reg(pi, RADIO_2064_REG01D, 0x01);
3367
write_radio_reg(pi, RADIO_2064_REG114, 0x01);
3368
write_radio_reg(pi, RADIO_2064_REG02E, 0x10);
3369
write_radio_reg(pi, RADIO_2064_REG12A, 0x08);
3371
mod_phy_reg(pi, 0x938, (0x1 << 0), 1 << 0);
3372
mod_phy_reg(pi, 0x939, (0x1 << 0), 0 << 0);
3373
mod_phy_reg(pi, 0x938, (0x1 << 1), 1 << 1);
3374
mod_phy_reg(pi, 0x939, (0x1 << 1), 1 << 1);
3375
mod_phy_reg(pi, 0x938, (0x1 << 2), 1 << 2);
3376
mod_phy_reg(pi, 0x939, (0x1 << 2), 1 << 2);
3377
mod_phy_reg(pi, 0x938, (0x1 << 3), 1 << 3);
3378
mod_phy_reg(pi, 0x939, (0x1 << 3), 1 << 3);
3379
mod_phy_reg(pi, 0x938, (0x1 << 5), 1 << 5);
3380
mod_phy_reg(pi, 0x939, (0x1 << 5), 0 << 5);
3382
mod_phy_reg(pi, 0x43b, (0x1 << 0), 1 << 0);
3383
mod_phy_reg(pi, 0x43c, (0x1 << 0), 0 << 0);
3385
wlc_lcnphy_start_tx_tone(pi, 2000, 120, 0);
3386
write_phy_reg(pi, 0x6da, 0xffff);
3387
or_phy_reg(pi, 0x6db, 0x3);
3388
wlc_lcnphy_set_trsw_override(pi, tx_switch, rx_switch);
3389
wlc_lcnphy_rx_gain_override_enable(pi, true);
3392
rx_pwr_threshold = 950;
3393
while (tia_gain > 0) {
3395
wlc_lcnphy_set_rx_gain_by_distribution(pi,
3402
wlc_lcnphy_measure_digital_power(pi, 2000);
3403
if (received_power < rx_pwr_threshold)
3406
result = wlc_lcnphy_calc_rx_iq_comp(pi, 0xffff);
3408
wlc_lcnphy_stop_tx_tone(pi);
3410
write_phy_reg(pi, 0x631, Core1TxControl_old);
3412
write_phy_reg(pi, 0x44c, RFOverrideVal0_old);
3413
write_phy_reg(pi, 0x44d, RFOverrideVal0_old);
3414
write_phy_reg(pi, 0x4b0, rfoverride2_old);
3415
write_phy_reg(pi, 0x4b1, rfoverride2val_old);
3416
write_phy_reg(pi, 0x4f9, rfoverride3_old);
3417
write_phy_reg(pi, 0x4fa, rfoverride3val_old);
3418
write_phy_reg(pi, 0x938, rfoverride4_old);
3419
write_phy_reg(pi, 0x939, rfoverride4val_old);
3420
write_phy_reg(pi, 0x43b, afectrlovr_old);
3421
write_phy_reg(pi, 0x43c, afectrlovrval_old);
3422
write_phy_reg(pi, 0x6da, old_sslpnCalibClkEnCtrl);
3423
write_phy_reg(pi, 0x6db, old_sslpnRxFeClkEnCtrl);
3425
wlc_lcnphy_clear_trsw_override(pi);
3427
mod_phy_reg(pi, 0x44c, (0x1 << 2), 0 << 2);
3429
for (i = 0; i < 11; i++) {
3430
write_radio_reg(pi, rxiq_cal_rf_reg[i],
3434
if (tx_gain_override_old) {
3435
wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_index_old);
3437
wlc_lcnphy_disable_tx_gain_override(pi);
3438
wlc_lcnphy_set_tx_pwr_ctrl(pi, tx_pwr_ctrl);
3440
wlc_lcnphy_rx_gain_override_enable(pi, false);
3448
static void wlc_lcnphy_temp_adj(phy_info_t *pi)
3450
if (NORADIO_ENAB(pi->pubpi))
3454
static void wlc_lcnphy_glacial_timer_based_cal(phy_info_t *pi)
3458
u16 SAVE_pwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
3459
phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
3461
(0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
3463
wlapi_suspend_mac_and_wait(pi->sh->physhim);
3464
wlc_lcnphy_deaf_mode(pi, true);
3465
pi->phy_lastcal = pi->sh->now;
3466
pi->phy_forcecal = false;
3467
index = pi_lcn->lcnphy_current_index;
3469
wlc_lcnphy_txpwrtbl_iqlo_cal(pi);
3471
wlc_lcnphy_set_tx_pwr_by_index(pi, index);
3472
wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_pwrctrl);
3473
wlc_lcnphy_deaf_mode(pi, false);
3475
wlapi_enable_mac(pi->sh->physhim);
3479
static void wlc_lcnphy_periodic_cal(phy_info_t *pi)
3481
bool suspend, full_cal;
3482
const lcnphy_rx_iqcomp_t *rx_iqcomp;
3484
u16 SAVE_pwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
3488
s32 tssi, pwr, maxtargetpwr, mintargetpwr;
3489
phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
3491
if (NORADIO_ENAB(pi->pubpi))
3494
pi->phy_lastcal = pi->sh->now;
3495
pi->phy_forcecal = false;
3497
(pi_lcn->lcnphy_full_cal_channel !=
3498
CHSPEC_CHANNEL(pi->radio_chanspec));
3499
pi_lcn->lcnphy_full_cal_channel = CHSPEC_CHANNEL(pi->radio_chanspec);
3500
index = pi_lcn->lcnphy_current_index;
3503
(0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
3506
wlapi_bmac_write_shm(pi->sh->physhim, M_CTS_DURATION, 10000);
3507
wlapi_suspend_mac_and_wait(pi->sh->physhim);
3509
wlc_lcnphy_deaf_mode(pi, true);
3511
wlc_lcnphy_txpwrtbl_iqlo_cal(pi);
3513
rx_iqcomp = lcnphy_rx_iqcomp_table_rev0;
3514
rx_iqcomp_sz = ARRAY_SIZE(lcnphy_rx_iqcomp_table_rev0);
3516
if (LCNREV_IS(pi->pubpi.phy_rev, 1))
3517
wlc_lcnphy_rx_iq_cal(pi, NULL, 0, true, false, 1, 40);
3519
wlc_lcnphy_rx_iq_cal(pi, NULL, 0, true, false, 1, 127);
3521
if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi)) {
3523
wlc_lcnphy_idle_tssi_est((wlc_phy_t *) pi);
3525
b0 = pi->txpa_2g[0];
3526
b1 = pi->txpa_2g[1];
3527
a1 = pi->txpa_2g[2];
3528
maxtargetpwr = wlc_lcnphy_tssi2dbm(10, a1, b0, b1);
3529
mintargetpwr = wlc_lcnphy_tssi2dbm(125, a1, b0, b1);
3531
tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
3536
for (tssi = 0; tssi < 128; tssi++) {
3537
pwr = wlc_lcnphy_tssi2dbm(tssi, a1, b0, b1);
3538
pwr = (pwr < mintargetpwr) ? mintargetpwr : pwr;
3539
wlc_lcnphy_write_table(pi, &tab);
3544
wlc_lcnphy_set_tx_pwr_by_index(pi, index);
3545
wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_pwrctrl);
3546
wlc_lcnphy_deaf_mode(pi, false);
3548
wlapi_enable_mac(pi->sh->physhim);
3551
void wlc_lcnphy_calib_modes(phy_info_t *pi, uint mode)
3554
int temp1, temp2, temp_diff;
3555
phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
3558
case PHY_PERICAL_CHAN:
3562
wlc_lcnphy_periodic_cal(pi);
3564
case PHY_PERICAL_PHYINIT:
3565
wlc_lcnphy_periodic_cal(pi);
3567
case PHY_PERICAL_WATCHDOG:
3568
if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) {
3569
temp_new = wlc_lcnphy_tempsense(pi, 0);
3570
temp1 = LCNPHY_TEMPSENSE(temp_new);
3571
temp2 = LCNPHY_TEMPSENSE(pi_lcn->lcnphy_cal_temper);
3572
temp_diff = temp1 - temp2;
3573
if ((pi_lcn->lcnphy_cal_counter > 90) ||
3574
(temp_diff > 60) || (temp_diff < -60)) {
3575
wlc_lcnphy_glacial_timer_based_cal(pi);
3576
wlc_2064_vco_cal(pi);
3577
pi_lcn->lcnphy_cal_temper = temp_new;
3578
pi_lcn->lcnphy_cal_counter = 0;
3580
pi_lcn->lcnphy_cal_counter++;
3583
case LCNPHY_PERICAL_TEMPBASED_TXPWRCTRL:
3584
if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi))
3585
wlc_lcnphy_tx_power_adjustment((wlc_phy_t *) pi);
3593
void wlc_lcnphy_get_tssi(phy_info_t *pi, s8 *ofdm_pwr, s8 *cck_pwr)
3597
status = (read_phy_reg(pi, 0x4ab));
3598
if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi) &&
3599
(status & (0x1 << 15))) {
3600
*ofdm_pwr = (s8) (((read_phy_reg(pi, 0x4ab) & (0x1ff << 0))
3603
if (wlc_phy_tpc_isenabled_lcnphy(pi))
3604
cck_offset = pi->tx_power_offset[TXP_FIRST_CCK];
3608
*cck_pwr = *ofdm_pwr + cck_offset;
3615
void WLBANDINITFN(wlc_phy_cal_init_lcnphy) (phy_info_t *pi)
3621
static void wlc_lcnphy_set_chanspec_tweaks(phy_info_t *pi, chanspec_t chanspec)
3623
u8 channel = CHSPEC_CHANNEL(chanspec);
3624
phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
3626
if (NORADIO_ENAB(pi->pubpi))
3629
if (channel == 14) {
3630
mod_phy_reg(pi, 0x448, (0x3 << 8), (2) << 8);
3633
mod_phy_reg(pi, 0x448, (0x3 << 8), (1) << 8);
3636
pi_lcn->lcnphy_bandedge_corr = 2;
3638
pi_lcn->lcnphy_bandedge_corr = 4;
3640
if (channel == 1 || channel == 2 || channel == 3 ||
3641
channel == 4 || channel == 9 ||
3642
channel == 10 || channel == 11 || channel == 12) {
3643
si_pmu_pllcontrol(pi->sh->sih, 0x2, 0xffffffff, 0x03000c04);
3644
si_pmu_pllcontrol(pi->sh->sih, 0x3, 0xffffff, 0x0);
3645
si_pmu_pllcontrol(pi->sh->sih, 0x4, 0xffffffff, 0x200005c0);
3647
si_pmu_pllupd(pi->sh->sih);
3648
write_phy_reg(pi, 0x942, 0);
3649
wlc_lcnphy_txrx_spur_avoidance_mode(pi, false);
3650
pi_lcn->lcnphy_spurmod = 0;
3651
mod_phy_reg(pi, 0x424, (0xff << 8), (0x1b) << 8);
3653
write_phy_reg(pi, 0x425, 0x5907);
3655
si_pmu_pllcontrol(pi->sh->sih, 0x2, 0xffffffff, 0x03140c04);
3656
si_pmu_pllcontrol(pi->sh->sih, 0x3, 0xffffff, 0x333333);
3657
si_pmu_pllcontrol(pi->sh->sih, 0x4, 0xffffffff, 0x202c2820);
3659
si_pmu_pllupd(pi->sh->sih);
3660
write_phy_reg(pi, 0x942, 0);
3661
wlc_lcnphy_txrx_spur_avoidance_mode(pi, true);
3663
pi_lcn->lcnphy_spurmod = 0;
3664
mod_phy_reg(pi, 0x424, (0xff << 8), (0x1f) << 8);
3666
write_phy_reg(pi, 0x425, 0x590a);
3669
or_phy_reg(pi, 0x44a, 0x44);
3670
write_phy_reg(pi, 0x44a, 0x80);
3673
void wlc_lcnphy_tx_power_adjustment(wlc_phy_t *ppi)
3677
phy_info_t *pi = (phy_info_t *) ppi;
3678
phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
3679
u16 SAVE_txpwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
3680
if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi) && SAVE_txpwrctrl) {
3681
index = wlc_lcnphy_tempcompensated_txpwrctrl(pi);
3682
index2 = (u16) (index * 2);
3683
mod_phy_reg(pi, 0x4a9, (0x1ff << 0), (index2) << 0);
3685
pi_lcn->lcnphy_current_index = (s8)
3686
((read_phy_reg(pi, 0x4a9) & 0xFF) / 2);
3690
static void wlc_lcnphy_set_rx_iq_comp(phy_info_t *pi, u16 a, u16 b)
3692
mod_phy_reg(pi, 0x645, (0x3ff << 0), (a) << 0);
3694
mod_phy_reg(pi, 0x646, (0x3ff << 0), (b) << 0);
3696
mod_phy_reg(pi, 0x647, (0x3ff << 0), (a) << 0);
3698
mod_phy_reg(pi, 0x648, (0x3ff << 0), (b) << 0);
3700
mod_phy_reg(pi, 0x649, (0x3ff << 0), (a) << 0);
3702
mod_phy_reg(pi, 0x64a, (0x3ff << 0), (b) << 0);
3706
void WLBANDINITFN(wlc_phy_init_lcnphy) (phy_info_t *pi)
3709
phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
3710
phybw40 = CHSPEC_IS40(pi->radio_chanspec);
3712
pi_lcn->lcnphy_cal_counter = 0;
3713
pi_lcn->lcnphy_cal_temper = pi_lcn->lcnphy_rawtempsense;
3715
or_phy_reg(pi, 0x44a, 0x80);
3716
and_phy_reg(pi, 0x44a, 0x7f);
3718
wlc_lcnphy_afe_clk_init(pi, AFE_CLK_INIT_MODE_TXRX2X);
3720
write_phy_reg(pi, 0x60a, 160);
3722
write_phy_reg(pi, 0x46a, 25);
3724
wlc_lcnphy_baseband_init(pi);
3726
wlc_lcnphy_radio_init(pi);
3728
if (CHSPEC_IS2G(pi->radio_chanspec))
3729
wlc_lcnphy_tx_pwr_ctrl_init((wlc_phy_t *) pi);
3731
wlc_phy_chanspec_set((wlc_phy_t *) pi, pi->radio_chanspec);
3733
si_pmu_regcontrol(pi->sh->sih, 0, 0xf, 0x9);
3735
si_pmu_chipcontrol(pi->sh->sih, 0, 0xffffffff, 0x03CDDDDD);
3737
if ((pi->sh->boardflags & BFL_FEM)
3738
&& wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi))
3739
wlc_lcnphy_set_tx_pwr_by_index(pi, FIXED_TXPWR);
3741
wlc_lcnphy_agc_temp_init(pi);
3743
wlc_lcnphy_temp_adj(pi);
3745
mod_phy_reg(pi, 0x448, (0x1 << 14), (1) << 14);
3748
mod_phy_reg(pi, 0x448, (0x1 << 14), (0) << 14);
3750
wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_HW);
3751
pi_lcn->lcnphy_noise_samples = LCNPHY_NOISE_SAMPLES_DEFAULT;
3752
wlc_lcnphy_calib_modes(pi, PHY_PERICAL_PHYINIT);
3756
wlc_lcnphy_tx_iqlo_loopback(phy_info_t *pi, u16 *values_to_save)
3760
for (i = 0; i < 20; i++) {
3762
read_radio_reg(pi, iqlo_loopback_rf_regs[i]);
3765
mod_phy_reg(pi, 0x44c, (0x1 << 12), 1 << 12);
3766
mod_phy_reg(pi, 0x44d, (0x1 << 14), 1 << 14);
3768
mod_phy_reg(pi, 0x44c, (0x1 << 11), 1 << 11);
3769
mod_phy_reg(pi, 0x44d, (0x1 << 13), 0 << 13);
3771
mod_phy_reg(pi, 0x43b, (0x1 << 1), 1 << 1);
3772
mod_phy_reg(pi, 0x43c, (0x1 << 1), 0 << 1);
3774
mod_phy_reg(pi, 0x43b, (0x1 << 0), 1 << 0);
3775
mod_phy_reg(pi, 0x43c, (0x1 << 0), 0 << 0);
3777
if (LCNREV_IS(pi->pubpi.phy_rev, 2))
3778
and_radio_reg(pi, RADIO_2064_REG03A, 0xFD);
3780
and_radio_reg(pi, RADIO_2064_REG03A, 0xF9);
3781
or_radio_reg(pi, RADIO_2064_REG11A, 0x1);
3783
or_radio_reg(pi, RADIO_2064_REG036, 0x01);
3784
or_radio_reg(pi, RADIO_2064_REG11A, 0x18);
3787
if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
3788
if (CHSPEC_IS5G(pi->radio_chanspec))
3789
mod_radio_reg(pi, RADIO_2064_REG03A, 1, 0);
3791
or_radio_reg(pi, RADIO_2064_REG03A, 1);
3793
if (CHSPEC_IS5G(pi->radio_chanspec))
3794
mod_radio_reg(pi, RADIO_2064_REG03A, 3, 1);
3796
or_radio_reg(pi, RADIO_2064_REG03A, 0x3);
3801
write_radio_reg(pi, RADIO_2064_REG025, 0xF);
3802
if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
3803
if (CHSPEC_IS5G(pi->radio_chanspec))
3804
mod_radio_reg(pi, RADIO_2064_REG028, 0xF, 0x4);
3806
mod_radio_reg(pi, RADIO_2064_REG028, 0xF, 0x6);
3808
if (CHSPEC_IS5G(pi->radio_chanspec))
3809
mod_radio_reg(pi, RADIO_2064_REG028, 0x1e, 0x4 << 1);
3811
mod_radio_reg(pi, RADIO_2064_REG028, 0x1e, 0x6 << 1);
3816
write_radio_reg(pi, RADIO_2064_REG005, 0x8);
3817
or_radio_reg(pi, RADIO_2064_REG112, 0x80);
3820
or_radio_reg(pi, RADIO_2064_REG0FF, 0x10);
3821
or_radio_reg(pi, RADIO_2064_REG11F, 0x44);
3824
or_radio_reg(pi, RADIO_2064_REG00B, 0x7);
3825
or_radio_reg(pi, RADIO_2064_REG113, 0x10);
3828
write_radio_reg(pi, RADIO_2064_REG007, 0x1);
3832
mod_radio_reg(pi, RADIO_2064_REG0FC, 0x3 << 0, (vmid >> 8) & 0x3);
3833
write_radio_reg(pi, RADIO_2064_REG0FD, (vmid & 0xff));
3834
or_radio_reg(pi, RADIO_2064_REG11F, 0x44);
3837
or_radio_reg(pi, RADIO_2064_REG0FF, 0x10);
3839
write_radio_reg(pi, RADIO_2064_REG012, 0x02);
3840
or_radio_reg(pi, RADIO_2064_REG112, 0x06);
3841
write_radio_reg(pi, RADIO_2064_REG036, 0x11);
3842
write_radio_reg(pi, RADIO_2064_REG059, 0xcc);
3843
write_radio_reg(pi, RADIO_2064_REG05C, 0x2e);
3844
write_radio_reg(pi, RADIO_2064_REG078, 0xd7);
3845
write_radio_reg(pi, RADIO_2064_REG092, 0x15);
3849
wlc_lcnphy_samp_cap(phy_info_t *pi, int clip_detect_algo, u16 thresh,
3852
u32 curval1, curval2, stpptr, curptr, strptr, val;
3853
u16 sslpnCalibClkEnCtrl, timer;
3854
u16 old_sslpnCalibClkEnCtrl;
3856
phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
3859
old_sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da);
3861
curval1 = R_REG(&pi->regs->psm_corectlsts);
3863
W_REG(&pi->regs->psm_corectlsts, ((1 << 6) | curval1));
3865
W_REG(&pi->regs->smpl_clct_strptr, 0x7E00);
3866
W_REG(&pi->regs->smpl_clct_stpptr, 0x8000);
3868
curval2 = R_REG(&pi->regs->psm_phy_hdr_param);
3869
W_REG(&pi->regs->psm_phy_hdr_param, curval2 | 0x30);
3871
write_phy_reg(pi, 0x555, 0x0);
3872
write_phy_reg(pi, 0x5a6, 0x5);
3874
write_phy_reg(pi, 0x5a2, (u16) (mode | mode << 6));
3875
write_phy_reg(pi, 0x5cf, 3);
3876
write_phy_reg(pi, 0x5a5, 0x3);
3877
write_phy_reg(pi, 0x583, 0x0);
3878
write_phy_reg(pi, 0x584, 0x0);
3879
write_phy_reg(pi, 0x585, 0x0fff);
3880
write_phy_reg(pi, 0x586, 0x0000);
3882
write_phy_reg(pi, 0x580, 0x4501);
3884
sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da);
3885
write_phy_reg(pi, 0x6da, (u32) (sslpnCalibClkEnCtrl | 0x2008));
3886
stpptr = R_REG(&pi->regs->smpl_clct_stpptr);
3887
curptr = R_REG(&pi->regs->smpl_clct_curptr);
3890
curptr = R_REG(&pi->regs->smpl_clct_curptr);
3892
} while ((curptr != stpptr) && (timer < 500));
3894
W_REG(&pi->regs->psm_phy_hdr_param, 0x2);
3896
W_REG(&pi->regs->tplatewrptr, strptr);
3897
while (strptr < 0x8000) {
3898
val = R_REG(&pi->regs->tplatewrdata);
3899
imag = ((val >> 16) & 0x3ff);
3900
real = ((val) & 0x3ff);
3907
if (pi_lcn->lcnphy_iqcal_swp_dis)
3908
ptr[(strptr - 0x7E00) / 4] = real;
3910
ptr[(strptr - 0x7E00) / 4] = imag;
3911
if (clip_detect_algo) {
3912
if (imag > thresh || imag < -thresh) {
3920
write_phy_reg(pi, 0x6da, old_sslpnCalibClkEnCtrl);
3921
W_REG(&pi->regs->psm_phy_hdr_param, curval2);
3922
W_REG(&pi->regs->psm_corectlsts, curval1);
3925
static void wlc_lcnphy_tx_iqlo_soft_cal_full(phy_info_t *pi)
3927
lcnphy_unsign16_struct iqcc0, locc2, locc3, locc4;
3929
wlc_lcnphy_set_cc(pi, 0, 0, 0);
3930
wlc_lcnphy_set_cc(pi, 2, 0, 0);
3931
wlc_lcnphy_set_cc(pi, 3, 0, 0);
3932
wlc_lcnphy_set_cc(pi, 4, 0, 0);
3934
wlc_lcnphy_a1(pi, 4, 0, 0);
3935
wlc_lcnphy_a1(pi, 3, 0, 0);
3936
wlc_lcnphy_a1(pi, 2, 3, 2);
3937
wlc_lcnphy_a1(pi, 0, 5, 8);
3938
wlc_lcnphy_a1(pi, 2, 2, 1);
3939
wlc_lcnphy_a1(pi, 0, 4, 3);
3941
iqcc0 = wlc_lcnphy_get_cc(pi, 0);
3942
locc2 = wlc_lcnphy_get_cc(pi, 2);
3943
locc3 = wlc_lcnphy_get_cc(pi, 3);
3944
locc4 = wlc_lcnphy_get_cc(pi, 4);
3948
wlc_lcnphy_set_cc(phy_info_t *pi, int cal_type, s16 coeff_x, s16 coeff_y)
3955
wlc_lcnphy_set_tx_iqcc(pi, coeff_x, coeff_y);
3958
di0dq0 = (coeff_x & 0xff) << 8 | (coeff_y & 0xff);
3959
wlc_lcnphy_set_tx_locc(pi, di0dq0);
3962
k = wlc_lcnphy_calc_floor(coeff_x, 0);
3964
k = wlc_lcnphy_calc_floor(coeff_x, 1);
3966
data_rf = (x * 16 + y);
3967
write_radio_reg(pi, RADIO_2064_REG089, data_rf);
3968
k = wlc_lcnphy_calc_floor(coeff_y, 0);
3970
k = wlc_lcnphy_calc_floor(coeff_y, 1);
3972
data_rf = (x * 16 + y);
3973
write_radio_reg(pi, RADIO_2064_REG08A, data_rf);
3976
k = wlc_lcnphy_calc_floor(coeff_x, 0);
3978
k = wlc_lcnphy_calc_floor(coeff_x, 1);
3980
data_rf = (x * 16 + y);
3981
write_radio_reg(pi, RADIO_2064_REG08B, data_rf);
3982
k = wlc_lcnphy_calc_floor(coeff_y, 0);
3984
k = wlc_lcnphy_calc_floor(coeff_y, 1);
3986
data_rf = (x * 16 + y);
3987
write_radio_reg(pi, RADIO_2064_REG08C, data_rf);
3992
static lcnphy_unsign16_struct wlc_lcnphy_get_cc(phy_info_t *pi, int cal_type)
3995
u8 di0, dq0, ei, eq, fi, fq;
3996
lcnphy_unsign16_struct cc;
4001
wlc_lcnphy_get_tx_iqcc(pi, &a, &b);
4006
didq = wlc_lcnphy_get_tx_locc(pi);
4007
di0 = (((didq & 0xff00) << 16) >> 24);
4008
dq0 = (((didq & 0x00ff) << 24) >> 24);
4013
wlc_lcnphy_get_radio_loft(pi, &ei, &eq, &fi, &fq);
4018
wlc_lcnphy_get_radio_loft(pi, &ei, &eq, &fi, &fq);
4027
wlc_lcnphy_a1(phy_info_t *pi, int cal_type, int num_levels, int step_size_lg2)
4029
const lcnphy_spb_tone_t *phy_c1;
4030
lcnphy_spb_tone_t phy_c2;
4031
lcnphy_unsign16_struct phy_c3;
4032
int phy_c4, phy_c5, k, l, j, phy_c6;
4033
u16 phy_c7, phy_c8, phy_c9;
4034
s16 phy_c10, phy_c11, phy_c12, phy_c13, phy_c14, phy_c15, phy_c16;
4036
s32 phy_c18, phy_c19;
4037
u32 phy_c20, phy_c21;
4038
bool phy_c22, phy_c23, phy_c24, phy_c25;
4039
u16 phy_c26, phy_c27;
4040
u16 phy_c28, phy_c29, phy_c30;
4044
phy_c10 = phy_c13 = phy_c14 = phy_c8 = 0;
4045
ptr = kmalloc(sizeof(s16) * 131, GFP_ATOMIC);
4050
phy_c32 = kmalloc(sizeof(u16) * 20, GFP_ATOMIC);
4051
if (NULL == phy_c32) {
4055
phy_c26 = read_phy_reg(pi, 0x6da);
4056
phy_c27 = read_phy_reg(pi, 0x6db);
4057
phy_c31 = read_radio_reg(pi, RADIO_2064_REG026);
4058
write_phy_reg(pi, 0x93d, 0xC0);
4060
wlc_lcnphy_start_tx_tone(pi, 3750, 88, 0);
4061
write_phy_reg(pi, 0x6da, 0xffff);
4062
or_phy_reg(pi, 0x6db, 0x3);
4064
wlc_lcnphy_tx_iqlo_loopback(pi, phy_c32);
4066
phy_c28 = read_phy_reg(pi, 0x938);
4067
phy_c29 = read_phy_reg(pi, 0x4d7);
4068
phy_c30 = read_phy_reg(pi, 0x4d8);
4069
or_phy_reg(pi, 0x938, 0x1 << 2);
4070
or_phy_reg(pi, 0x4d7, 0x1 << 2);
4071
or_phy_reg(pi, 0x4d7, 0x1 << 3);
4072
mod_phy_reg(pi, 0x4d7, (0x7 << 12), 0x2 << 12);
4073
or_phy_reg(pi, 0x4d8, 1 << 0);
4074
or_phy_reg(pi, 0x4d8, 1 << 1);
4075
mod_phy_reg(pi, 0x4d8, (0x3ff << 2), 0x23A << 2);
4076
mod_phy_reg(pi, 0x4d8, (0x7 << 12), 0x7 << 12);
4077
phy_c1 = &lcnphy_spb_tone_3750[0];
4080
if (num_levels == 0) {
4081
if (cal_type != 0) {
4087
if (step_size_lg2 == 0) {
4088
if (cal_type != 0) {
4095
phy_c7 = (1 << step_size_lg2);
4096
phy_c3 = wlc_lcnphy_get_cc(pi, cal_type);
4097
phy_c15 = (s16) phy_c3.re;
4098
phy_c16 = (s16) phy_c3.im;
4099
if (cal_type == 2) {
4100
if (phy_c3.re > 127)
4101
phy_c15 = phy_c3.re - 256;
4102
if (phy_c3.im > 127)
4103
phy_c16 = phy_c3.im - 256;
4105
wlc_lcnphy_set_cc(pi, cal_type, phy_c15, phy_c16);
4107
for (phy_c8 = 0; phy_c7 != 0 && phy_c8 < num_levels; phy_c8++) {
4125
phy_c9 = read_phy_reg(pi, 0x93d);
4126
phy_c9 = 2 * phy_c9;
4131
write_radio_reg(pi, RADIO_2064_REG026,
4132
(phy_c5 & 0x7) | ((phy_c5 & 0x7) << 4));
4136
wlc_lcnphy_samp_cap(pi, 1, phy_c9, &ptr[0], 2);
4141
if ((phy_c22 != phy_c24) && (!phy_c25))
4145
if (phy_c5 <= 0 || phy_c5 >= 7)
4153
else if (phy_c5 > 7)
4156
for (k = -phy_c7; k <= phy_c7; k += phy_c7) {
4157
for (l = -phy_c7; l <= phy_c7; l += phy_c7) {
4158
phy_c11 = phy_c15 + k;
4159
phy_c12 = phy_c16 + l;
4161
if (phy_c11 < -phy_c10)
4163
else if (phy_c11 > phy_c10)
4165
if (phy_c12 < -phy_c10)
4167
else if (phy_c12 > phy_c10)
4169
wlc_lcnphy_set_cc(pi, cal_type, phy_c11,
4172
wlc_lcnphy_samp_cap(pi, 0, 0, ptr, 2);
4176
for (j = 0; j < 128; j++) {
4177
if (cal_type != 0) {
4178
phy_c6 = j % phy_c4;
4180
phy_c6 = (2 * j) % phy_c4;
4182
phy_c2.re = phy_c1[phy_c6].re;
4183
phy_c2.im = phy_c1[phy_c6].im;
4185
phy_c18 = phy_c18 + phy_c17 * phy_c2.re;
4186
phy_c19 = phy_c19 + phy_c17 * phy_c2.im;
4189
phy_c18 = phy_c18 >> 10;
4190
phy_c19 = phy_c19 >> 10;
4192
((phy_c18 * phy_c18) + (phy_c19 * phy_c19));
4194
if (phy_c23 || phy_c20 < phy_c21) {
4205
phy_c7 = phy_c7 >> 1;
4206
wlc_lcnphy_set_cc(pi, cal_type, phy_c15, phy_c16);
4211
wlc_lcnphy_tx_iqlo_loopback_cleanup(pi, phy_c32);
4212
wlc_lcnphy_stop_tx_tone(pi);
4213
write_phy_reg(pi, 0x6da, phy_c26);
4214
write_phy_reg(pi, 0x6db, phy_c27);
4215
write_phy_reg(pi, 0x938, phy_c28);
4216
write_phy_reg(pi, 0x4d7, phy_c29);
4217
write_phy_reg(pi, 0x4d8, phy_c30);
4218
write_radio_reg(pi, RADIO_2064_REG026, phy_c31);
4225
wlc_lcnphy_tx_iqlo_loopback_cleanup(phy_info_t *pi, u16 *values_to_save)
4229
and_phy_reg(pi, 0x44c, 0x0 >> 11);
4231
and_phy_reg(pi, 0x43b, 0xC);
4233
for (i = 0; i < 20; i++) {
4234
write_radio_reg(pi, iqlo_loopback_rf_regs[i],
4240
WLBANDINITFN(wlc_lcnphy_load_tx_gain_table) (phy_info_t *pi,
4241
const lcnphy_tx_gain_tbl_entry *
4249
if (CHSPEC_IS5G(pi->radio_chanspec))
4254
if (pi->sh->boardflags & BFL_FEM)
4256
tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
4261
for (j = 0; j < 128; j++) {
4262
gm_gain = gain_table[j].gm;
4263
val = (((u32) pa_gain << 24) |
4264
(gain_table[j].pad << 16) |
4265
(gain_table[j].pga << 8) | gm_gain);
4267
tab.tbl_offset = LCNPHY_TX_PWR_CTRL_GAIN_OFFSET + j;
4268
wlc_lcnphy_write_table(pi, &tab);
4270
val = (gain_table[j].dac << 28) | (gain_table[j].bb_mult << 20);
4271
tab.tbl_offset = LCNPHY_TX_PWR_CTRL_IQ_OFFSET + j;
4272
wlc_lcnphy_write_table(pi, &tab);
4276
static void wlc_lcnphy_load_rfpower(phy_info_t *pi)
4279
u32 val, bbmult, rfgain;
4281
u8 scale_factor = 1;
4282
s16 temp, temp1, temp2, qQ, qQ1, qQ2, shift;
4284
tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
4288
for (index = 0; index < 128; index++) {
4289
tab.tbl_ptr = &bbmult;
4290
tab.tbl_offset = LCNPHY_TX_PWR_CTRL_IQ_OFFSET + index;
4291
wlc_lcnphy_read_table(pi, &tab);
4292
bbmult = bbmult >> 20;
4294
tab.tbl_ptr = &rfgain;
4295
tab.tbl_offset = LCNPHY_TX_PWR_CTRL_GAIN_OFFSET + index;
4296
wlc_lcnphy_read_table(pi, &tab);
4298
qm_log10((s32) (bbmult), 0, &temp1, &qQ1);
4299
qm_log10((s32) (1 << 6), 0, &temp2, &qQ2);
4302
temp2 = qm_shr16(temp2, qQ2 - qQ1);
4305
temp1 = qm_shr16(temp1, qQ1 - qQ2);
4308
temp = qm_sub16(temp1, temp2);
4315
val = (((index << shift) + (5 * temp) +
4316
(1 << (scale_factor + shift - 3))) >> (scale_factor +
4320
tab.tbl_offset = LCNPHY_TX_PWR_CTRL_PWR_OFFSET + index;
4321
wlc_lcnphy_write_table(pi, &tab);
4325
static void WLBANDINITFN(wlc_lcnphy_tbl_init) (phy_info_t *pi)
4332
phybw40 = CHSPEC_IS40(pi->radio_chanspec);
4334
for (idx = 0; idx < dot11lcnphytbl_info_sz_rev0; idx++) {
4335
wlc_lcnphy_write_table(pi, &dot11lcnphytbl_info_rev0[idx]);
4338
if (pi->sh->boardflags & BFL_FEM_BT) {
4339
tab.tbl_id = LCNPHY_TBL_ID_RFSEQ;
4345
wlc_lcnphy_write_table(pi, &tab);
4348
tab.tbl_id = LCNPHY_TBL_ID_RFSEQ;
4355
wlc_lcnphy_write_table(pi, &tab);
4359
wlc_lcnphy_write_table(pi, &tab);
4363
wlc_lcnphy_write_table(pi, &tab);
4365
if (CHSPEC_IS2G(pi->radio_chanspec)) {
4366
if (pi->sh->boardflags & BFL_FEM)
4367
wlc_lcnphy_load_tx_gain_table(pi,
4368
dot11lcnphy_2GHz_extPA_gaintable_rev0);
4370
wlc_lcnphy_load_tx_gain_table(pi,
4371
dot11lcnphy_2GHz_gaintable_rev0);
4374
if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
4375
if (CHSPEC_IS2G(pi->radio_chanspec)) {
4377
idx < dot11lcnphytbl_rx_gain_info_2G_rev2_sz;
4379
if (pi->sh->boardflags & BFL_EXTLNA)
4380
wlc_lcnphy_write_table(pi,
4381
&dot11lcnphytbl_rx_gain_info_extlna_2G_rev2
4384
wlc_lcnphy_write_table(pi,
4385
&dot11lcnphytbl_rx_gain_info_2G_rev2
4389
idx < dot11lcnphytbl_rx_gain_info_5G_rev2_sz;
4391
if (pi->sh->boardflags & BFL_EXTLNA_5GHz)
4392
wlc_lcnphy_write_table(pi,
4393
&dot11lcnphytbl_rx_gain_info_extlna_5G_rev2
4396
wlc_lcnphy_write_table(pi,
4397
&dot11lcnphytbl_rx_gain_info_5G_rev2
4402
if ((pi->sh->boardflags & BFL_FEM)
4403
&& !(pi->sh->boardflags & BFL_FEM_BT))
4404
wlc_lcnphy_write_table(pi, &dot11lcn_sw_ctrl_tbl_info_4313_epa);
4405
else if (pi->sh->boardflags & BFL_FEM_BT) {
4406
if (pi->sh->boardrev < 0x1250)
4407
wlc_lcnphy_write_table(pi,
4408
&dot11lcn_sw_ctrl_tbl_info_4313_bt_epa);
4410
wlc_lcnphy_write_table(pi,
4411
&dot11lcn_sw_ctrl_tbl_info_4313_bt_epa_p250);
4413
wlc_lcnphy_write_table(pi, &dot11lcn_sw_ctrl_tbl_info_4313);
4415
wlc_lcnphy_load_rfpower(pi);
4417
wlc_lcnphy_clear_papd_comptable(pi);
4420
static void WLBANDINITFN(wlc_lcnphy_rev0_baseband_init) (phy_info_t *pi)
4423
phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
4425
write_radio_reg(pi, RADIO_2064_REG11C, 0x0);
4427
write_phy_reg(pi, 0x43b, 0x0);
4428
write_phy_reg(pi, 0x43c, 0x0);
4429
write_phy_reg(pi, 0x44c, 0x0);
4430
write_phy_reg(pi, 0x4e6, 0x0);
4431
write_phy_reg(pi, 0x4f9, 0x0);
4432
write_phy_reg(pi, 0x4b0, 0x0);
4433
write_phy_reg(pi, 0x938, 0x0);
4434
write_phy_reg(pi, 0x4b0, 0x0);
4435
write_phy_reg(pi, 0x44e, 0);
4437
or_phy_reg(pi, 0x567, 0x03);
4439
or_phy_reg(pi, 0x44a, 0x44);
4440
write_phy_reg(pi, 0x44a, 0x80);
4442
if (!(pi->sh->boardflags & BFL_FEM))
4443
wlc_lcnphy_set_tx_pwr_by_index(pi, 52);
4447
afectrl1 = (u16) ((pi_lcn->lcnphy_rssi_vf) |
4448
(pi_lcn->lcnphy_rssi_vc << 4) | (pi_lcn->
4451
write_phy_reg(pi, 0x43e, afectrl1);
4454
mod_phy_reg(pi, 0x634, (0xff << 0), 0xC << 0);
4455
if (pi->sh->boardflags & BFL_FEM) {
4456
mod_phy_reg(pi, 0x634, (0xff << 0), 0xA << 0);
4458
write_phy_reg(pi, 0x910, 0x1);
4461
mod_phy_reg(pi, 0x448, (0x3 << 8), 1 << 8);
4462
mod_phy_reg(pi, 0x608, (0xff << 0), 0x17 << 0);
4463
mod_phy_reg(pi, 0x604, (0x7ff << 0), 0x3EA << 0);
4467
static void WLBANDINITFN(wlc_lcnphy_rev2_baseband_init) (phy_info_t *pi)
4469
if (CHSPEC_IS5G(pi->radio_chanspec)) {
4470
mod_phy_reg(pi, 0x416, (0xff << 0), 80 << 0);
4472
mod_phy_reg(pi, 0x416, (0xff << 8), 80 << 8);
4476
static void wlc_lcnphy_agc_temp_init(phy_info_t *pi)
4481
phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
4483
if (NORADIO_ENAB(pi->pubpi))
4486
temp = (s16) read_phy_reg(pi, 0x4df);
4487
pi_lcn->lcnphy_ofdmgainidxtableoffset = (temp & (0xff << 0)) >> 0;
4489
if (pi_lcn->lcnphy_ofdmgainidxtableoffset > 127)
4490
pi_lcn->lcnphy_ofdmgainidxtableoffset -= 256;
4492
pi_lcn->lcnphy_dsssgainidxtableoffset = (temp & (0xff << 8)) >> 8;
4494
if (pi_lcn->lcnphy_dsssgainidxtableoffset > 127)
4495
pi_lcn->lcnphy_dsssgainidxtableoffset -= 256;
4497
tab.tbl_ptr = tableBuffer;
4500
tab.tbl_offset = 59;
4502
wlc_lcnphy_read_table(pi, &tab);
4504
if (tableBuffer[0] > 63)
4505
tableBuffer[0] -= 128;
4506
pi_lcn->lcnphy_tr_R_gain_val = tableBuffer[0];
4508
if (tableBuffer[1] > 63)
4509
tableBuffer[1] -= 128;
4510
pi_lcn->lcnphy_tr_T_gain_val = tableBuffer[1];
4512
temp = (s16) (read_phy_reg(pi, 0x434)
4516
pi_lcn->lcnphy_input_pwr_offset_db = (s8) temp;
4518
pi_lcn->lcnphy_Med_Low_Gain_db = (read_phy_reg(pi, 0x424)
4521
pi_lcn->lcnphy_Very_Low_Gain_db = (read_phy_reg(pi, 0x425)
4525
tab.tbl_ptr = tableBuffer;
4527
tab.tbl_id = LCNPHY_TBL_ID_GAIN_IDX;
4528
tab.tbl_offset = 28;
4530
wlc_lcnphy_read_table(pi, &tab);
4532
pi_lcn->lcnphy_gain_idx_14_lowword = tableBuffer[0];
4533
pi_lcn->lcnphy_gain_idx_14_hiword = tableBuffer[1];
4537
static void WLBANDINITFN(wlc_lcnphy_bu_tweaks) (phy_info_t *pi)
4539
if (NORADIO_ENAB(pi->pubpi))
4542
or_phy_reg(pi, 0x805, 0x1);
4544
mod_phy_reg(pi, 0x42f, (0x7 << 0), (0x3) << 0);
4546
mod_phy_reg(pi, 0x030, (0x7 << 0), (0x3) << 0);
4548
write_phy_reg(pi, 0x414, 0x1e10);
4549
write_phy_reg(pi, 0x415, 0x0640);
4551
mod_phy_reg(pi, 0x4df, (0xff << 8), -9 << 8);
4553
or_phy_reg(pi, 0x44a, 0x44);
4554
write_phy_reg(pi, 0x44a, 0x80);
4555
mod_phy_reg(pi, 0x434, (0xff << 0), (0xFD) << 0);
4557
mod_phy_reg(pi, 0x420, (0xff << 0), (16) << 0);
4559
if (!(pi->sh->boardrev < 0x1204))
4560
mod_radio_reg(pi, RADIO_2064_REG09B, 0xF0, 0xF0);
4562
write_phy_reg(pi, 0x7d6, 0x0902);
4563
mod_phy_reg(pi, 0x429, (0xf << 0), (0x9) << 0);
4565
mod_phy_reg(pi, 0x429, (0x3f << 4), (0xe) << 4);
4567
if (LCNREV_IS(pi->pubpi.phy_rev, 1)) {
4568
mod_phy_reg(pi, 0x423, (0xff << 0), (0x46) << 0);
4570
mod_phy_reg(pi, 0x411, (0xff << 0), (1) << 0);
4572
mod_phy_reg(pi, 0x434, (0xff << 0), (0xFF) << 0);
4574
mod_phy_reg(pi, 0x656, (0xf << 0), (2) << 0);
4576
mod_phy_reg(pi, 0x44d, (0x1 << 2), (1) << 2);
4578
mod_radio_reg(pi, RADIO_2064_REG0F7, 0x4, 0x4);
4579
mod_radio_reg(pi, RADIO_2064_REG0F1, 0x3, 0);
4580
mod_radio_reg(pi, RADIO_2064_REG0F2, 0xF8, 0x90);
4581
mod_radio_reg(pi, RADIO_2064_REG0F3, 0x3, 0x2);
4582
mod_radio_reg(pi, RADIO_2064_REG0F3, 0xf0, 0xa0);
4584
mod_radio_reg(pi, RADIO_2064_REG11F, 0x2, 0x2);
4586
wlc_lcnphy_clear_tx_power_offsets(pi);
4587
mod_phy_reg(pi, 0x4d0, (0x1ff << 6), (10) << 6);
4592
static void WLBANDINITFN(wlc_lcnphy_baseband_init) (phy_info_t *pi)
4595
wlc_lcnphy_tbl_init(pi);
4596
wlc_lcnphy_rev0_baseband_init(pi);
4597
if (LCNREV_IS(pi->pubpi.phy_rev, 2))
4598
wlc_lcnphy_rev2_baseband_init(pi);
4599
wlc_lcnphy_bu_tweaks(pi);
4602
static void WLBANDINITFN(wlc_radio_2064_init) (phy_info_t *pi)
4605
lcnphy_radio_regs_t *lcnphyregs = NULL;
4607
lcnphyregs = lcnphy_radio_regs_2064;
4609
for (i = 0; lcnphyregs[i].address != 0xffff; i++)
4610
if (CHSPEC_IS5G(pi->radio_chanspec) && lcnphyregs[i].do_init_a)
4612
((lcnphyregs[i].address & 0x3fff) |
4613
RADIO_DEFAULT_CORE),
4614
(u16) lcnphyregs[i].init_a);
4615
else if (lcnphyregs[i].do_init_g)
4617
((lcnphyregs[i].address & 0x3fff) |
4618
RADIO_DEFAULT_CORE),
4619
(u16) lcnphyregs[i].init_g);
4621
write_radio_reg(pi, RADIO_2064_REG032, 0x62);
4622
write_radio_reg(pi, RADIO_2064_REG033, 0x19);
4624
write_radio_reg(pi, RADIO_2064_REG090, 0x10);
4626
write_radio_reg(pi, RADIO_2064_REG010, 0x00);
4628
if (LCNREV_IS(pi->pubpi.phy_rev, 1)) {
4630
write_radio_reg(pi, RADIO_2064_REG060, 0x7f);
4631
write_radio_reg(pi, RADIO_2064_REG061, 0x72);
4632
write_radio_reg(pi, RADIO_2064_REG062, 0x7f);
4635
write_radio_reg(pi, RADIO_2064_REG01D, 0x02);
4636
write_radio_reg(pi, RADIO_2064_REG01E, 0x06);
4638
mod_phy_reg(pi, 0x4ea, (0x7 << 0), 0 << 0);
4640
mod_phy_reg(pi, 0x4ea, (0x7 << 3), 1 << 3);
4642
mod_phy_reg(pi, 0x4ea, (0x7 << 6), 2 << 6);
4644
mod_phy_reg(pi, 0x4ea, (0x7 << 9), 3 << 9);
4646
mod_phy_reg(pi, 0x4ea, (0x7 << 12), 4 << 12);
4648
write_phy_reg(pi, 0x4ea, 0x4688);
4650
mod_phy_reg(pi, 0x4eb, (0x7 << 0), 2 << 0);
4652
mod_phy_reg(pi, 0x4eb, (0x7 << 6), 0 << 6);
4654
mod_phy_reg(pi, 0x46a, (0xffff << 0), 25 << 0);
4656
wlc_lcnphy_set_tx_locc(pi, 0);
4658
wlc_lcnphy_rcal(pi);
4660
wlc_lcnphy_rc_cal(pi);
4663
static void WLBANDINITFN(wlc_lcnphy_radio_init) (phy_info_t *pi)
4665
if (NORADIO_ENAB(pi->pubpi))
4668
wlc_radio_2064_init(pi);
4671
static void wlc_lcnphy_rcal(phy_info_t *pi)
4675
if (NORADIO_ENAB(pi->pubpi))
4678
and_radio_reg(pi, RADIO_2064_REG05B, 0xfD);
4680
or_radio_reg(pi, RADIO_2064_REG004, 0x40);
4681
or_radio_reg(pi, RADIO_2064_REG120, 0x10);
4683
or_radio_reg(pi, RADIO_2064_REG078, 0x80);
4684
or_radio_reg(pi, RADIO_2064_REG129, 0x02);
4686
or_radio_reg(pi, RADIO_2064_REG057, 0x01);
4688
or_radio_reg(pi, RADIO_2064_REG05B, 0x02);
4690
SPINWAIT(!wlc_radio_2064_rcal_done(pi), 10 * 1000 * 1000);
4692
if (wlc_radio_2064_rcal_done(pi)) {
4693
rcal_value = (u8) read_radio_reg(pi, RADIO_2064_REG05C);
4694
rcal_value = rcal_value & 0x1f;
4697
and_radio_reg(pi, RADIO_2064_REG05B, 0xfD);
4699
and_radio_reg(pi, RADIO_2064_REG057, 0xFE);
4702
static void wlc_lcnphy_rc_cal(phy_info_t *pi)
4707
if (NORADIO_ENAB(pi->pubpi))
4710
dflt_rc_cal_val = 7;
4711
if (LCNREV_IS(pi->pubpi.phy_rev, 1))
4712
dflt_rc_cal_val = 11;
4714
(dflt_rc_cal_val << 10) | (dflt_rc_cal_val << 5) |
4716
write_phy_reg(pi, 0x933, flt_val);
4717
write_phy_reg(pi, 0x934, flt_val);
4718
write_phy_reg(pi, 0x935, flt_val);
4719
write_phy_reg(pi, 0x936, flt_val);
4720
write_phy_reg(pi, 0x937, (flt_val & 0x1FF));
4725
static bool wlc_phy_txpwr_srom_read_lcnphy(phy_info_t *pi)
4729
phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
4731
if (CHSPEC_IS2G(pi->radio_chanspec)) {
4733
u32 offset_ofdm, offset_mcs;
4735
pi_lcn->lcnphy_tr_isolation_mid =
4736
(u8) PHY_GETINTVAR(pi, "triso2g");
4738
pi_lcn->lcnphy_rx_power_offset =
4739
(u8) PHY_GETINTVAR(pi, "rxpo2g");
4741
pi->txpa_2g[0] = (s16) PHY_GETINTVAR(pi, "pa0b0");
4742
pi->txpa_2g[1] = (s16) PHY_GETINTVAR(pi, "pa0b1");
4743
pi->txpa_2g[2] = (s16) PHY_GETINTVAR(pi, "pa0b2");
4745
pi_lcn->lcnphy_rssi_vf = (u8) PHY_GETINTVAR(pi, "rssismf2g");
4746
pi_lcn->lcnphy_rssi_vc = (u8) PHY_GETINTVAR(pi, "rssismc2g");
4747
pi_lcn->lcnphy_rssi_gs = (u8) PHY_GETINTVAR(pi, "rssisav2g");
4750
pi_lcn->lcnphy_rssi_vf_lowtemp = pi_lcn->lcnphy_rssi_vf;
4751
pi_lcn->lcnphy_rssi_vc_lowtemp = pi_lcn->lcnphy_rssi_vc;
4752
pi_lcn->lcnphy_rssi_gs_lowtemp = pi_lcn->lcnphy_rssi_gs;
4754
pi_lcn->lcnphy_rssi_vf_hightemp =
4755
pi_lcn->lcnphy_rssi_vf;
4756
pi_lcn->lcnphy_rssi_vc_hightemp =
4757
pi_lcn->lcnphy_rssi_vc;
4758
pi_lcn->lcnphy_rssi_gs_hightemp =
4759
pi_lcn->lcnphy_rssi_gs;
4762
txpwr = (s8) PHY_GETINTVAR(pi, "maxp2ga0");
4763
pi->tx_srom_max_2g = txpwr;
4765
for (i = 0; i < PWRTBL_NUM_COEFF; i++) {
4766
pi->txpa_2g_low_temp[i] = pi->txpa_2g[i];
4767
pi->txpa_2g_high_temp[i] = pi->txpa_2g[i];
4770
cckpo = (u16) PHY_GETINTVAR(pi, "cck2gpo");
4772
uint max_pwr_chan = txpwr;
4774
for (i = TXP_FIRST_CCK; i <= TXP_LAST_CCK; i++) {
4775
pi->tx_srom_max_rate_2g[i] = max_pwr_chan -
4776
((cckpo & 0xf) * 2);
4780
offset_ofdm = (u32) PHY_GETINTVAR(pi, "ofdm2gpo");
4781
for (i = TXP_FIRST_OFDM; i <= TXP_LAST_OFDM; i++) {
4782
pi->tx_srom_max_rate_2g[i] = max_pwr_chan -
4783
((offset_ofdm & 0xf) * 2);
4789
opo = (u8) PHY_GETINTVAR(pi, "opo");
4791
for (i = TXP_FIRST_CCK; i <= TXP_LAST_CCK; i++) {
4792
pi->tx_srom_max_rate_2g[i] = txpwr;
4795
offset_ofdm = (u32) PHY_GETINTVAR(pi, "ofdm2gpo");
4797
for (i = TXP_FIRST_OFDM; i <= TXP_LAST_OFDM; i++) {
4798
pi->tx_srom_max_rate_2g[i] = txpwr -
4799
((offset_ofdm & 0xf) * 2);
4803
((u16) PHY_GETINTVAR(pi, "mcs2gpo1") << 16) |
4804
(u16) PHY_GETINTVAR(pi, "mcs2gpo0");
4805
pi_lcn->lcnphy_mcs20_po = offset_mcs;
4806
for (i = TXP_FIRST_SISO_MCS_20;
4807
i <= TXP_LAST_SISO_MCS_20; i++) {
4808
pi->tx_srom_max_rate_2g[i] =
4809
txpwr - ((offset_mcs & 0xf) * 2);
4814
pi_lcn->lcnphy_rawtempsense =
4815
(u16) PHY_GETINTVAR(pi, "rawtempsense");
4816
pi_lcn->lcnphy_measPower =
4817
(u8) PHY_GETINTVAR(pi, "measpower");
4818
pi_lcn->lcnphy_tempsense_slope =
4819
(u8) PHY_GETINTVAR(pi, "tempsense_slope");
4820
pi_lcn->lcnphy_hw_iqcal_en =
4821
(bool) PHY_GETINTVAR(pi, "hw_iqcal_en");
4822
pi_lcn->lcnphy_iqcal_swp_dis =
4823
(bool) PHY_GETINTVAR(pi, "iqcal_swp_dis");
4824
pi_lcn->lcnphy_tempcorrx =
4825
(u8) PHY_GETINTVAR(pi, "tempcorrx");
4826
pi_lcn->lcnphy_tempsense_option =
4827
(u8) PHY_GETINTVAR(pi, "tempsense_option");
4828
pi_lcn->lcnphy_freqoffset_corr =
4829
(u8) PHY_GETINTVAR(pi, "freqoffset_corr");
4830
if ((u8) getintvar(pi->vars, "aa2g") > 1)
4831
wlc_phy_ant_rxdiv_set((wlc_phy_t *) pi,
4832
(u8) getintvar(pi->vars,
4835
pi_lcn->lcnphy_cck_dig_filt_type = -1;
4836
if (PHY_GETVAR(pi, "cckdigfilttype")) {
4838
temp = (s16) PHY_GETINTVAR(pi, "cckdigfilttype");
4840
pi_lcn->lcnphy_cck_dig_filt_type = temp;
4847
void wlc_2064_vco_cal(phy_info_t *pi)
4851
mod_radio_reg(pi, RADIO_2064_REG057, 1 << 3, 1 << 3);
4852
calnrst = (u8) read_radio_reg(pi, RADIO_2064_REG056) & 0xf8;
4853
write_radio_reg(pi, RADIO_2064_REG056, calnrst);
4855
write_radio_reg(pi, RADIO_2064_REG056, calnrst | 0x03);
4857
write_radio_reg(pi, RADIO_2064_REG056, calnrst | 0x07);
4859
mod_radio_reg(pi, RADIO_2064_REG057, 1 << 3, 0);
4863
wlc_lcnphy_radio_2064_channel_tune_4313(phy_info_t *pi, u8 channel)
4866
const chan_info_2064_lcnphy_t *ci;
4867
u8 rfpll_doubler = 0;
4868
u8 pll_pwrup, pll_pwrup_ovr;
4869
fixed qFxtal, qFref, qFvco, qFcal;
4870
u8 d15, d16, f16, e44, e45;
4871
u32 div_int, div_frac, fvco3, fpfd, fref3, fcal_div;
4872
u16 loop_bw, d30, setCount;
4873
if (NORADIO_ENAB(pi->pubpi))
4875
ci = &chan_info_2064_lcnphy[0];
4878
mod_radio_reg(pi, RADIO_2064_REG09D, 0x4, 0x1 << 2);
4880
write_radio_reg(pi, RADIO_2064_REG09E, 0xf);
4881
if (!rfpll_doubler) {
4882
loop_bw = PLL_2064_LOOP_BW;
4885
loop_bw = PLL_2064_LOOP_BW_DOUBLER;
4886
d30 = PLL_2064_D30_DOUBLER;
4889
if (CHSPEC_IS2G(pi->radio_chanspec)) {
4890
for (i = 0; i < ARRAY_SIZE(chan_info_2064_lcnphy); i++)
4891
if (chan_info_2064_lcnphy[i].chan == channel)
4894
if (i >= ARRAY_SIZE(chan_info_2064_lcnphy)) {
4898
ci = &chan_info_2064_lcnphy[i];
4901
write_radio_reg(pi, RADIO_2064_REG02A, ci->logen_buftune);
4903
mod_radio_reg(pi, RADIO_2064_REG030, 0x3, ci->logen_rccr_tx);
4905
mod_radio_reg(pi, RADIO_2064_REG091, 0x3, ci->txrf_mix_tune_ctrl);
4907
mod_radio_reg(pi, RADIO_2064_REG038, 0xf, ci->pa_input_tune_g);
4909
mod_radio_reg(pi, RADIO_2064_REG030, 0x3 << 2,
4910
(ci->logen_rccr_rx) << 2);
4912
mod_radio_reg(pi, RADIO_2064_REG05E, 0xf, ci->pa_rxrf_lna1_freq_tune);
4914
mod_radio_reg(pi, RADIO_2064_REG05E, (0xf) << 4,
4915
(ci->pa_rxrf_lna2_freq_tune) << 4);
4917
write_radio_reg(pi, RADIO_2064_REG06C, ci->rxrf_rxrf_spare1);
4919
pll_pwrup = (u8) read_radio_reg(pi, RADIO_2064_REG044);
4920
pll_pwrup_ovr = (u8) read_radio_reg(pi, RADIO_2064_REG12B);
4922
or_radio_reg(pi, RADIO_2064_REG044, 0x07);
4924
or_radio_reg(pi, RADIO_2064_REG12B, (0x07) << 1);
4928
fpfd = rfpll_doubler ? (pi->xtalfreq << 1) : (pi->xtalfreq);
4929
if (pi->xtalfreq > 26000000)
4931
if (pi->xtalfreq > 52000000)
4939
fvco3 = (ci->freq * 3);
4942
qFxtal = wlc_lcnphy_qdiv_roundup(pi->xtalfreq, PLL_2064_MHZ, 16);
4943
qFref = wlc_lcnphy_qdiv_roundup(fpfd, PLL_2064_MHZ, 16);
4944
qFcal = pi->xtalfreq * fcal_div / PLL_2064_MHZ;
4945
qFvco = wlc_lcnphy_qdiv_roundup(fvco3, 2, 16);
4947
write_radio_reg(pi, RADIO_2064_REG04F, 0x02);
4949
d15 = (pi->xtalfreq * fcal_div * 4 / 5) / PLL_2064_MHZ - 1;
4950
write_radio_reg(pi, RADIO_2064_REG052, (0x07 & (d15 >> 2)));
4951
write_radio_reg(pi, RADIO_2064_REG053, (d15 & 0x3) << 5);
4953
d16 = (qFcal * 8 / (d15 + 1)) - 1;
4954
write_radio_reg(pi, RADIO_2064_REG051, d16);
4956
f16 = ((d16 + 1) * (d15 + 1)) / qFcal;
4957
setCount = f16 * 3 * (ci->freq) / 32 - 1;
4958
mod_radio_reg(pi, RADIO_2064_REG053, (0x0f << 0),
4959
(u8) (setCount >> 8));
4961
or_radio_reg(pi, RADIO_2064_REG053, 0x10);
4962
write_radio_reg(pi, RADIO_2064_REG054, (u8) (setCount & 0xff));
4964
div_int = ((fvco3 * (PLL_2064_MHZ >> 4)) / fref3) << 4;
4966
div_frac = ((fvco3 * (PLL_2064_MHZ >> 4)) % fref3) << 4;
4967
while (div_frac >= fref3) {
4971
div_frac = wlc_lcnphy_qdiv_roundup(div_frac, fref3, 20);
4973
mod_radio_reg(pi, RADIO_2064_REG045, (0x1f << 0),
4974
(u8) (div_int >> 4));
4975
mod_radio_reg(pi, RADIO_2064_REG046, (0x1f << 4),
4976
(u8) (div_int << 4));
4977
mod_radio_reg(pi, RADIO_2064_REG046, (0x0f << 0),
4978
(u8) (div_frac >> 16));
4979
write_radio_reg(pi, RADIO_2064_REG047, (u8) (div_frac >> 8) & 0xff);
4980
write_radio_reg(pi, RADIO_2064_REG048, (u8) div_frac & 0xff);
4982
write_radio_reg(pi, RADIO_2064_REG040, 0xfb);
4984
write_radio_reg(pi, RADIO_2064_REG041, 0x9A);
4985
write_radio_reg(pi, RADIO_2064_REG042, 0xA3);
4986
write_radio_reg(pi, RADIO_2064_REG043, 0x0C);
4989
u8 h29, h23, c28, d29, h28_ten, e30, h30_ten, cp_current;
4990
u16 c29, c38, c30, g30, d28;
4997
d28 = (((PLL_2064_HIGH_END_KVCO - PLL_2064_LOW_END_KVCO) *
4998
(fvco3 / 2 - PLL_2064_LOW_END_VCO)) /
4999
(PLL_2064_HIGH_END_VCO - PLL_2064_LOW_END_VCO))
5000
+ PLL_2064_LOW_END_KVCO;
5001
h28_ten = (d28 * 10) / c28;
5003
e30 = (d30 - 680) / 490;
5004
g30 = 680 + (e30 * 490);
5005
h30_ten = (g30 * 10) / c30;
5006
cp_current = ((c38 * h29 * h23 * 100) / h28_ten) / h30_ten;
5007
mod_radio_reg(pi, RADIO_2064_REG03C, 0x3f, cp_current);
5009
if (channel >= 1 && channel <= 5)
5010
write_radio_reg(pi, RADIO_2064_REG03C, 0x8);
5012
write_radio_reg(pi, RADIO_2064_REG03C, 0x7);
5013
write_radio_reg(pi, RADIO_2064_REG03D, 0x3);
5015
mod_radio_reg(pi, RADIO_2064_REG044, 0x0c, 0x0c);
5018
wlc_2064_vco_cal(pi);
5020
write_radio_reg(pi, RADIO_2064_REG044, pll_pwrup);
5021
write_radio_reg(pi, RADIO_2064_REG12B, pll_pwrup_ovr);
5022
if (LCNREV_IS(pi->pubpi.phy_rev, 1)) {
5023
write_radio_reg(pi, RADIO_2064_REG038, 3);
5024
write_radio_reg(pi, RADIO_2064_REG091, 7);
5028
bool wlc_phy_tpc_isenabled_lcnphy(phy_info_t *pi)
5030
if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi))
5033
return (LCNPHY_TX_PWR_CTRL_HW ==
5034
wlc_lcnphy_get_tx_pwr_ctrl((pi)));
5037
void wlc_phy_txpower_recalc_target_lcnphy(phy_info_t *pi)
5040
if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) {
5041
wlc_lcnphy_calib_modes(pi, LCNPHY_PERICAL_TEMPBASED_TXPWRCTRL);
5042
} else if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi)) {
5044
pwr_ctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
5045
wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
5046
wlc_lcnphy_txpower_recalc_target(pi);
5048
wlc_lcnphy_set_tx_pwr_ctrl(pi, pwr_ctrl);
5053
void wlc_phy_detach_lcnphy(phy_info_t *pi)
5055
kfree(pi->u.pi_lcnphy);
5058
bool wlc_phy_attach_lcnphy(phy_info_t *pi)
5060
phy_info_lcnphy_t *pi_lcn;
5062
pi->u.pi_lcnphy = kzalloc(sizeof(phy_info_lcnphy_t), GFP_ATOMIC);
5063
if (pi->u.pi_lcnphy == NULL) {
5067
pi_lcn = pi->u.pi_lcnphy;
5069
if ((0 == (pi->sh->boardflags & BFL_NOPA)) && !NORADIO_ENAB(pi->pubpi)) {
5070
pi->hwpwrctrl = true;
5071
pi->hwpwrctrl_capable = true;
5074
pi->xtalfreq = si_alp_clock(pi->sh->sih);
5075
ASSERT(0 == (pi->xtalfreq % 1000));
5077
pi_lcn->lcnphy_papd_rxGnCtrl_init = 0;
5079
pi->pi_fptr.init = wlc_phy_init_lcnphy;
5080
pi->pi_fptr.calinit = wlc_phy_cal_init_lcnphy;
5081
pi->pi_fptr.chanset = wlc_phy_chanspec_set_lcnphy;
5082
pi->pi_fptr.txpwrrecalc = wlc_phy_txpower_recalc_target_lcnphy;
5083
pi->pi_fptr.txiqccget = wlc_lcnphy_get_tx_iqcc;
5084
pi->pi_fptr.txiqccset = wlc_lcnphy_set_tx_iqcc;
5085
pi->pi_fptr.txloccget = wlc_lcnphy_get_tx_locc;
5086
pi->pi_fptr.radioloftget = wlc_lcnphy_get_radio_loft;
5087
pi->pi_fptr.detach = wlc_phy_detach_lcnphy;
5089
if (!wlc_phy_txpwr_srom_read_lcnphy(pi))
5092
if ((pi->sh->boardflags & BFL_FEM) && (LCNREV_IS(pi->pubpi.phy_rev, 1))) {
5093
if (pi_lcn->lcnphy_tempsense_option == 3) {
5094
pi->hwpwrctrl = true;
5095
pi->hwpwrctrl_capable = true;
5096
pi->temppwrctrl_capable = false;
5098
pi->hwpwrctrl = false;
5099
pi->hwpwrctrl_capable = false;
5100
pi->temppwrctrl_capable = true;
5107
static void wlc_lcnphy_set_rx_gain(phy_info_t *pi, u32 gain)
5109
u16 trsw, ext_lna, lna1, lna2, tia, biq0, biq1, gain0_15, gain16_19;
5111
trsw = (gain & ((u32) 1 << 28)) ? 0 : 1;
5112
ext_lna = (u16) (gain >> 29) & 0x01;
5113
lna1 = (u16) (gain >> 0) & 0x0f;
5114
lna2 = (u16) (gain >> 4) & 0x0f;
5115
tia = (u16) (gain >> 8) & 0xf;
5116
biq0 = (u16) (gain >> 12) & 0xf;
5117
biq1 = (u16) (gain >> 16) & 0xf;
5119
gain0_15 = (u16) ((lna1 & 0x3) | ((lna1 & 0x3) << 2) |
5120
((lna2 & 0x3) << 4) | ((lna2 & 0x3) << 6) |
5121
((tia & 0xf) << 8) | ((biq0 & 0xf) << 12));
5124
mod_phy_reg(pi, 0x44d, (0x1 << 0), trsw << 0);
5125
mod_phy_reg(pi, 0x4b1, (0x1 << 9), ext_lna << 9);
5126
mod_phy_reg(pi, 0x4b1, (0x1 << 10), ext_lna << 10);
5127
mod_phy_reg(pi, 0x4b6, (0xffff << 0), gain0_15 << 0);
5128
mod_phy_reg(pi, 0x4b7, (0xf << 0), gain16_19 << 0);
5130
if (CHSPEC_IS2G(pi->radio_chanspec)) {
5131
mod_phy_reg(pi, 0x4b1, (0x3 << 11), lna1 << 11);
5132
mod_phy_reg(pi, 0x4e6, (0x3 << 3), lna1 << 3);
5134
wlc_lcnphy_rx_gain_override_enable(pi, true);
5137
static u32 wlc_lcnphy_get_receive_power(phy_info_t *pi, s32 *gain_index)
5139
u32 received_power = 0;
5142
phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
5145
if (*gain_index >= 0)
5146
gain_code = lcnphy_23bitgaincode_table[*gain_index];
5148
if (-1 == *gain_index) {
5150
while ((*gain_index <= (s32) max_index)
5151
&& (received_power < 700)) {
5152
wlc_lcnphy_set_rx_gain(pi,
5153
lcnphy_23bitgaincode_table
5156
wlc_lcnphy_measure_digital_power(pi,
5158
lcnphy_noise_samples);
5163
wlc_lcnphy_set_rx_gain(pi, gain_code);
5165
wlc_lcnphy_measure_digital_power(pi,
5167
lcnphy_noise_samples);
5170
return received_power;
5173
s32 wlc_lcnphy_rx_signal_power(phy_info_t *pi, s32 gain_index)
5176
s32 nominal_power_db;
5177
s32 log_val, gain_mismatch, desired_gain, input_power_offset_db,
5179
s32 received_power, temperature;
5181
phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
5183
received_power = wlc_lcnphy_get_receive_power(pi, &gain_index);
5185
gain = lcnphy_gain_table[gain_index];
5187
nominal_power_db = read_phy_reg(pi, 0x425) >> 8;
5190
u32 power = (received_power * 16);
5191
u32 msb1, msb2, val1, val2, diff1, diff2;
5192
msb1 = ffs(power) - 1;
5196
diff1 = (power - val1);
5197
diff2 = (val2 - power);
5204
log_val = log_val * 3;
5206
gain_mismatch = (nominal_power_db / 2) - (log_val);
5208
desired_gain = gain + gain_mismatch;
5210
input_power_offset_db = read_phy_reg(pi, 0x434) & 0xFF;
5212
if (input_power_offset_db > 127)
5213
input_power_offset_db -= 256;
5215
input_power_db = input_power_offset_db - desired_gain;
5218
input_power_db + lcnphy_gain_index_offset_for_rssi[gain_index];
5220
freq = wlc_phy_channel2freq(CHSPEC_CHANNEL(pi->radio_chanspec));
5221
if ((freq > 2427) && (freq <= 2467))
5222
input_power_db = input_power_db - 1;
5224
temperature = pi_lcn->lcnphy_lastsensed_temperature;
5226
if ((temperature - 15) < -30) {
5228
input_power_db + (((temperature - 10 - 25) * 286) >> 12) -
5230
} else if ((temperature - 15) < 4) {
5232
input_power_db + (((temperature - 10 - 25) * 286) >> 12) -
5236
input_power_db + (((temperature - 10 - 25) * 286) >> 12);
5239
wlc_lcnphy_rx_gain_override_enable(pi, 0);
5241
return input_power_db;
5245
wlc_lcnphy_load_tx_iir_filter(phy_info_t *pi, bool is_ofdm, s16 filt_type)
5247
s16 filt_index = -1;
5289
for (j = 0; j < LCNPHY_NUM_TX_DIG_FILTERS_CCK; j++) {
5290
if (filt_type == LCNPHY_txdigfiltcoeffs_cck[j][0]) {
5291
filt_index = (s16) j;
5296
if (filt_index == -1) {
5299
for (j = 0; j < LCNPHY_NUM_DIG_FILT_COEFFS; j++) {
5300
write_phy_reg(pi, addr[j],
5301
LCNPHY_txdigfiltcoeffs_cck
5302
[filt_index][j + 1]);
5306
for (j = 0; j < LCNPHY_NUM_TX_DIG_FILTERS_OFDM; j++) {
5307
if (filt_type == LCNPHY_txdigfiltcoeffs_ofdm[j][0]) {
5308
filt_index = (s16) j;
5313
if (filt_index == -1) {
5316
for (j = 0; j < LCNPHY_NUM_DIG_FILT_COEFFS; j++) {
5317
write_phy_reg(pi, addr_ofdm[j],
5318
LCNPHY_txdigfiltcoeffs_ofdm
5319
[filt_index][j + 1]);
5324
return (filt_index != -1) ? 0 : -1;