aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath9k/calib.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/ath9k/calib.c')
-rw-r--r--drivers/net/wireless/ath9k/calib.c214
1 files changed, 82 insertions, 132 deletions
diff --git a/drivers/net/wireless/ath9k/calib.c b/drivers/net/wireless/ath9k/calib.c
index 3c7454fc51bd..69ff01ce968b 100644
--- a/drivers/net/wireless/ath9k/calib.c
+++ b/drivers/net/wireless/ath9k/calib.c
@@ -19,8 +19,6 @@
19#include "reg.h" 19#include "reg.h"
20#include "phy.h" 20#include "phy.h"
21 21
22static const int16_t NOISE_FLOOR[] = { -96, -93, -98, -96, -93, -96 };
23
24/* We can tune this as we go by monitoring really low values */ 22/* We can tune this as we go by monitoring really low values */
25#define ATH9K_NF_TOO_LOW -60 23#define ATH9K_NF_TOO_LOW -60
26 24
@@ -107,27 +105,29 @@ static void ath9k_hw_do_getnf(struct ath_hal *ah,
107 "NF calibrated [ctl] [chain 0] is %d\n", nf); 105 "NF calibrated [ctl] [chain 0] is %d\n", nf);
108 nfarray[0] = nf; 106 nfarray[0] = nf;
109 107
110 if (AR_SREV_9280_10_OR_LATER(ah)) 108 if (!AR_SREV_9285(ah)) {
111 nf = MS(REG_READ(ah, AR_PHY_CH1_CCA), 109 if (AR_SREV_9280_10_OR_LATER(ah))
112 AR9280_PHY_CH1_MINCCA_PWR); 110 nf = MS(REG_READ(ah, AR_PHY_CH1_CCA),
113 else 111 AR9280_PHY_CH1_MINCCA_PWR);
114 nf = MS(REG_READ(ah, AR_PHY_CH1_CCA), 112 else
115 AR_PHY_CH1_MINCCA_PWR); 113 nf = MS(REG_READ(ah, AR_PHY_CH1_CCA),
114 AR_PHY_CH1_MINCCA_PWR);
116 115
117 if (nf & 0x100)
118 nf = 0 - ((nf ^ 0x1ff) + 1);
119 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
120 "NF calibrated [ctl] [chain 1] is %d\n", nf);
121 nfarray[1] = nf;
122
123 if (!AR_SREV_9280(ah)) {
124 nf = MS(REG_READ(ah, AR_PHY_CH2_CCA),
125 AR_PHY_CH2_MINCCA_PWR);
126 if (nf & 0x100) 116 if (nf & 0x100)
127 nf = 0 - ((nf ^ 0x1ff) + 1); 117 nf = 0 - ((nf ^ 0x1ff) + 1);
128 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, 118 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
129 "NF calibrated [ctl] [chain 2] is %d\n", nf); 119 "NF calibrated [ctl] [chain 1] is %d\n", nf);
130 nfarray[2] = nf; 120 nfarray[1] = nf;
121
122 if (!AR_SREV_9280(ah)) {
123 nf = MS(REG_READ(ah, AR_PHY_CH2_CCA),
124 AR_PHY_CH2_MINCCA_PWR);
125 if (nf & 0x100)
126 nf = 0 - ((nf ^ 0x1ff) + 1);
127 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
128 "NF calibrated [ctl] [chain 2] is %d\n", nf);
129 nfarray[2] = nf;
130 }
131 } 131 }
132 132
133 if (AR_SREV_9280_10_OR_LATER(ah)) 133 if (AR_SREV_9280_10_OR_LATER(ah))
@@ -143,51 +143,45 @@ static void ath9k_hw_do_getnf(struct ath_hal *ah,
143 "NF calibrated [ext] [chain 0] is %d\n", nf); 143 "NF calibrated [ext] [chain 0] is %d\n", nf);
144 nfarray[3] = nf; 144 nfarray[3] = nf;
145 145
146 if (AR_SREV_9280_10_OR_LATER(ah)) 146 if (!AR_SREV_9285(ah)) {
147 nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA), 147 if (AR_SREV_9280_10_OR_LATER(ah))
148 AR9280_PHY_CH1_EXT_MINCCA_PWR); 148 nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA),
149 else 149 AR9280_PHY_CH1_EXT_MINCCA_PWR);
150 nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA), 150 else
151 AR_PHY_CH1_EXT_MINCCA_PWR); 151 nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA),
152 152 AR_PHY_CH1_EXT_MINCCA_PWR);
153 if (nf & 0x100)
154 nf = 0 - ((nf ^ 0x1ff) + 1);
155 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
156 "NF calibrated [ext] [chain 1] is %d\n", nf);
157 nfarray[4] = nf;
158 153
159 if (!AR_SREV_9280(ah)) {
160 nf = MS(REG_READ(ah, AR_PHY_CH2_EXT_CCA),
161 AR_PHY_CH2_EXT_MINCCA_PWR);
162 if (nf & 0x100) 154 if (nf & 0x100)
163 nf = 0 - ((nf ^ 0x1ff) + 1); 155 nf = 0 - ((nf ^ 0x1ff) + 1);
164 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, 156 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
165 "NF calibrated [ext] [chain 2] is %d\n", nf); 157 "NF calibrated [ext] [chain 1] is %d\n", nf);
166 nfarray[5] = nf; 158 nfarray[4] = nf;
159
160 if (!AR_SREV_9280(ah)) {
161 nf = MS(REG_READ(ah, AR_PHY_CH2_EXT_CCA),
162 AR_PHY_CH2_EXT_MINCCA_PWR);
163 if (nf & 0x100)
164 nf = 0 - ((nf ^ 0x1ff) + 1);
165 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
166 "NF calibrated [ext] [chain 2] is %d\n", nf);
167 nfarray[5] = nf;
168 }
167 } 169 }
168} 170}
169 171
170static bool getNoiseFloorThresh(struct ath_hal *ah, 172static bool getNoiseFloorThresh(struct ath_hal *ah,
171 const struct ath9k_channel *chan, 173 enum ieee80211_band band,
172 int16_t *nft) 174 int16_t *nft)
173{ 175{
174 switch (chan->chanmode) { 176 switch (band) {
175 case CHANNEL_A: 177 case IEEE80211_BAND_5GHZ:
176 case CHANNEL_A_HT20:
177 case CHANNEL_A_HT40PLUS:
178 case CHANNEL_A_HT40MINUS:
179 *nft = (int8_t)ath9k_hw_get_eeprom(ah, EEP_NFTHRESH_5); 178 *nft = (int8_t)ath9k_hw_get_eeprom(ah, EEP_NFTHRESH_5);
180 break; 179 break;
181 case CHANNEL_B: 180 case IEEE80211_BAND_2GHZ:
182 case CHANNEL_G:
183 case CHANNEL_G_HT20:
184 case CHANNEL_G_HT40PLUS:
185 case CHANNEL_G_HT40MINUS:
186 *nft = (int8_t)ath9k_hw_get_eeprom(ah, EEP_NFTHRESH_2); 181 *nft = (int8_t)ath9k_hw_get_eeprom(ah, EEP_NFTHRESH_2);
187 break; 182 break;
188 default: 183 default:
189 DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL, 184 BUG_ON(1);
190 "invalid channel flags 0x%x\n", chan->channelFlags);
191 return false; 185 return false;
192 } 186 }
193 187
@@ -285,27 +279,24 @@ static void ath9k_hw_per_calibration(struct ath_hal *ah,
285 } 279 }
286} 280}
287 281
282/* Assumes you are talking about the currently configured channel */
288static bool ath9k_hw_iscal_supported(struct ath_hal *ah, 283static bool ath9k_hw_iscal_supported(struct ath_hal *ah,
289 struct ath9k_channel *chan,
290 enum hal_cal_types calType) 284 enum hal_cal_types calType)
291{ 285{
292 struct ath_hal_5416 *ahp = AH5416(ah); 286 struct ath_hal_5416 *ahp = AH5416(ah);
293 bool retval = false; 287 struct ieee80211_conf *conf = &ah->ah_sc->hw->conf;
294 288
295 switch (calType & ahp->ah_suppCals) { 289 switch (calType & ahp->ah_suppCals) {
296 case IQ_MISMATCH_CAL: 290 case IQ_MISMATCH_CAL: /* Both 2 GHz and 5 GHz support OFDM */
297 if (!IS_CHAN_B(chan)) 291 return true;
298 retval = true;
299 break;
300 case ADC_GAIN_CAL: 292 case ADC_GAIN_CAL:
301 case ADC_DC_CAL: 293 case ADC_DC_CAL:
302 if (!IS_CHAN_B(chan) 294 if (conf->channel->band == IEEE80211_BAND_5GHZ &&
303 && !(IS_CHAN_2GHZ(chan) && IS_CHAN_HT20(chan))) 295 conf_is_ht20(conf))
304 retval = true; 296 return true;
305 break; 297 break;
306 } 298 }
307 299 return false;
308 return retval;
309} 300}
310 301
311static void ath9k_hw_iqcal_collect(struct ath_hal *ah) 302static void ath9k_hw_iqcal_collect(struct ath_hal *ah)
@@ -573,50 +564,40 @@ static void ath9k_hw_adc_dccal_calibrate(struct ath_hal *ah, u8 numChains)
573 AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE); 564 AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE);
574} 565}
575 566
576void ath9k_hw_reset_calvalid(struct ath_hal *ah, struct ath9k_channel *chan, 567/* This is done for the currently configured channel */
577 bool *isCalDone) 568bool ath9k_hw_reset_calvalid(struct ath_hal *ah)
578{ 569{
579 struct ath_hal_5416 *ahp = AH5416(ah); 570 struct ath_hal_5416 *ahp = AH5416(ah);
580 struct ath9k_channel *ichan = 571 struct ieee80211_conf *conf = &ah->ah_sc->hw->conf;
581 ath9k_regd_check_channel(ah, chan);
582 struct hal_cal_list *currCal = ahp->ah_cal_list_curr; 572 struct hal_cal_list *currCal = ahp->ah_cal_list_curr;
583 573
584 *isCalDone = true; 574 if (!ah->ah_curchan)
575 return true;
585 576
586 if (!AR_SREV_9100(ah) && !AR_SREV_9160_10_OR_LATER(ah)) 577 if (!AR_SREV_9100(ah) && !AR_SREV_9160_10_OR_LATER(ah))
587 return; 578 return true;
588 579
589 if (currCal == NULL) 580 if (currCal == NULL)
590 return; 581 return true;
591
592 if (ichan == NULL) {
593 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
594 "invalid channel %u/0x%x; no mapping\n",
595 chan->channel, chan->channelFlags);
596 return;
597 }
598
599 582
600 if (currCal->calState != CAL_DONE) { 583 if (currCal->calState != CAL_DONE) {
601 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, 584 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
602 "Calibration state incorrect, %d\n", 585 "Calibration state incorrect, %d\n",
603 currCal->calState); 586 currCal->calState);
604 return; 587 return true;
605 } 588 }
606 589
607 590 if (!ath9k_hw_iscal_supported(ah, currCal->calData->calType))
608 if (!ath9k_hw_iscal_supported(ah, chan, currCal->calData->calType)) 591 return true;
609 return;
610 592
611 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, 593 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
612 "Resetting Cal %d state for channel %u/0x%x\n", 594 "Resetting Cal %d state for channel %u\n",
613 currCal->calData->calType, chan->channel, 595 currCal->calData->calType, conf->channel->center_freq);
614 chan->channelFlags);
615 596
616 ichan->CalValid &= ~currCal->calData->calType; 597 ah->ah_curchan->CalValid &= ~currCal->calData->calType;
617 currCal->calState = CAL_WAITING; 598 currCal->calState = CAL_WAITING;
618 599
619 *isCalDone = false; 600 return false;
620} 601}
621 602
622void ath9k_hw_start_nfcal(struct ath_hal *ah) 603void ath9k_hw_start_nfcal(struct ath_hal *ah)
@@ -643,16 +624,14 @@ void ath9k_hw_loadnf(struct ath_hal *ah, struct ath9k_channel *chan)
643 }; 624 };
644 u8 chainmask; 625 u8 chainmask;
645 626
646 if (AR_SREV_9280(ah)) 627 if (AR_SREV_9285(ah))
628 chainmask = 0x9;
629 else if (AR_SREV_9280(ah))
647 chainmask = 0x1B; 630 chainmask = 0x1B;
648 else 631 else
649 chainmask = 0x3F; 632 chainmask = 0x3F;
650 633
651#ifdef ATH_NF_PER_CHAN
652 h = chan->nfCalHist;
653#else
654 h = ah->nfCalHist; 634 h = ah->nfCalHist;
655#endif
656 635
657 for (i = 0; i < NUM_NF_READINGS; i++) { 636 for (i = 0; i < NUM_NF_READINGS; i++) {
658 if (chainmask & (1 << i)) { 637 if (chainmask & (1 << i)) {
@@ -692,12 +671,7 @@ int16_t ath9k_hw_getnf(struct ath_hal *ah,
692 int16_t nf, nfThresh; 671 int16_t nf, nfThresh;
693 int16_t nfarray[NUM_NF_READINGS] = { 0 }; 672 int16_t nfarray[NUM_NF_READINGS] = { 0 };
694 struct ath9k_nfcal_hist *h; 673 struct ath9k_nfcal_hist *h;
695 u8 chainmask; 674 struct ieee80211_channel *c = chan->chan;
696
697 if (AR_SREV_9280(ah))
698 chainmask = 0x1B;
699 else
700 chainmask = 0x3F;
701 675
702 chan->channelFlags &= (~CHANNEL_CW_INT); 676 chan->channelFlags &= (~CHANNEL_CW_INT);
703 if (REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) { 677 if (REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) {
@@ -709,7 +683,7 @@ int16_t ath9k_hw_getnf(struct ath_hal *ah,
709 } else { 683 } else {
710 ath9k_hw_do_getnf(ah, nfarray); 684 ath9k_hw_do_getnf(ah, nfarray);
711 nf = nfarray[0]; 685 nf = nfarray[0];
712 if (getNoiseFloorThresh(ah, chan, &nfThresh) 686 if (getNoiseFloorThresh(ah, c->band, &nfThresh)
713 && nf > nfThresh) { 687 && nf > nfThresh) {
714 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, 688 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
715 "noise floor failed detected; " 689 "noise floor failed detected; "
@@ -719,11 +693,7 @@ int16_t ath9k_hw_getnf(struct ath_hal *ah,
719 } 693 }
720 } 694 }
721 695
722#ifdef ATH_NF_PER_CHAN
723 h = chan->nfCalHist;
724#else
725 h = ah->nfCalHist; 696 h = ah->nfCalHist;
726#endif
727 697
728 ath9k_hw_update_nfcal_hist_buffer(h, nfarray); 698 ath9k_hw_update_nfcal_hist_buffer(h, nfarray);
729 chan->rawNoiseFloor = h[0].privNF; 699 chan->rawNoiseFloor = h[0].privNF;
@@ -750,21 +720,12 @@ void ath9k_init_nfcal_hist_buffer(struct ath_hal *ah)
750 720
751s16 ath9k_hw_getchan_noise(struct ath_hal *ah, struct ath9k_channel *chan) 721s16 ath9k_hw_getchan_noise(struct ath_hal *ah, struct ath9k_channel *chan)
752{ 722{
753 struct ath9k_channel *ichan;
754 s16 nf; 723 s16 nf;
755 724
756 ichan = ath9k_regd_check_channel(ah, chan); 725 if (chan->rawNoiseFloor == 0)
757 if (ichan == NULL) { 726 nf = -96;
758 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, 727 else
759 "invalid channel %u/0x%x; no mapping\n", 728 nf = chan->rawNoiseFloor;
760 chan->channel, chan->channelFlags);
761 return ATH_DEFAULT_NOISE_FLOOR;
762 }
763 if (ichan->rawNoiseFloor == 0) {
764 enum wireless_mode mode = ath9k_hw_chan2wmode(ah, chan);
765 nf = NOISE_FLOOR[mode];
766 } else
767 nf = ichan->rawNoiseFloor;
768 729
769 if (!ath9k_hw_nf_in_range(ah, nf)) 730 if (!ath9k_hw_nf_in_range(ah, nf))
770 nf = ATH_DEFAULT_NOISE_FLOOR; 731 nf = ATH_DEFAULT_NOISE_FLOOR;
@@ -778,21 +739,13 @@ bool ath9k_hw_calibrate(struct ath_hal *ah, struct ath9k_channel *chan,
778{ 739{
779 struct ath_hal_5416 *ahp = AH5416(ah); 740 struct ath_hal_5416 *ahp = AH5416(ah);
780 struct hal_cal_list *currCal = ahp->ah_cal_list_curr; 741 struct hal_cal_list *currCal = ahp->ah_cal_list_curr;
781 struct ath9k_channel *ichan = ath9k_regd_check_channel(ah, chan);
782 742
783 *isCalDone = true; 743 *isCalDone = true;
784 744
785 if (ichan == NULL) {
786 DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL,
787 "invalid channel %u/0x%x; no mapping\n",
788 chan->channel, chan->channelFlags);
789 return false;
790 }
791
792 if (currCal && 745 if (currCal &&
793 (currCal->calState == CAL_RUNNING || 746 (currCal->calState == CAL_RUNNING ||
794 currCal->calState == CAL_WAITING)) { 747 currCal->calState == CAL_WAITING)) {
795 ath9k_hw_per_calibration(ah, ichan, rxchainmask, currCal, 748 ath9k_hw_per_calibration(ah, chan, rxchainmask, currCal,
796 isCalDone); 749 isCalDone);
797 if (*isCalDone) { 750 if (*isCalDone) {
798 ahp->ah_cal_list_curr = currCal = currCal->calNext; 751 ahp->ah_cal_list_curr = currCal = currCal->calNext;
@@ -805,14 +758,12 @@ bool ath9k_hw_calibrate(struct ath_hal *ah, struct ath9k_channel *chan,
805 } 758 }
806 759
807 if (longcal) { 760 if (longcal) {
808 ath9k_hw_getnf(ah, ichan); 761 ath9k_hw_getnf(ah, chan);
809 ath9k_hw_loadnf(ah, ah->ah_curchan); 762 ath9k_hw_loadnf(ah, ah->ah_curchan);
810 ath9k_hw_start_nfcal(ah); 763 ath9k_hw_start_nfcal(ah);
811 764
812 if ((ichan->channelFlags & CHANNEL_CW_INT) != 0) { 765 if (chan->channelFlags & CHANNEL_CW_INT)
813 chan->channelFlags |= CHANNEL_CW_INT; 766 chan->channelFlags &= ~CHANNEL_CW_INT;
814 ichan->channelFlags &= ~CHANNEL_CW_INT;
815 }
816 } 767 }
817 768
818 return true; 769 return true;
@@ -917,7 +868,6 @@ bool ath9k_hw_init_cal(struct ath_hal *ah,
917 struct ath9k_channel *chan) 868 struct ath9k_channel *chan)
918{ 869{
919 struct ath_hal_5416 *ahp = AH5416(ah); 870 struct ath_hal_5416 *ahp = AH5416(ah);
920 struct ath9k_channel *ichan = ath9k_regd_check_channel(ah, chan);
921 871
922 REG_WRITE(ah, AR_PHY_AGC_CONTROL, 872 REG_WRITE(ah, AR_PHY_AGC_CONTROL,
923 REG_READ(ah, AR_PHY_AGC_CONTROL) | 873 REG_READ(ah, AR_PHY_AGC_CONTROL) |
@@ -940,19 +890,19 @@ bool ath9k_hw_init_cal(struct ath_hal *ah,
940 ahp->ah_cal_list = ahp->ah_cal_list_last = ahp->ah_cal_list_curr = NULL; 890 ahp->ah_cal_list = ahp->ah_cal_list_last = ahp->ah_cal_list_curr = NULL;
941 891
942 if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) { 892 if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) {
943 if (ath9k_hw_iscal_supported(ah, chan, ADC_GAIN_CAL)) { 893 if (ath9k_hw_iscal_supported(ah, ADC_GAIN_CAL)) {
944 INIT_CAL(&ahp->ah_adcGainCalData); 894 INIT_CAL(&ahp->ah_adcGainCalData);
945 INSERT_CAL(ahp, &ahp->ah_adcGainCalData); 895 INSERT_CAL(ahp, &ahp->ah_adcGainCalData);
946 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, 896 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
947 "enabling ADC Gain Calibration.\n"); 897 "enabling ADC Gain Calibration.\n");
948 } 898 }
949 if (ath9k_hw_iscal_supported(ah, chan, ADC_DC_CAL)) { 899 if (ath9k_hw_iscal_supported(ah, ADC_DC_CAL)) {
950 INIT_CAL(&ahp->ah_adcDcCalData); 900 INIT_CAL(&ahp->ah_adcDcCalData);
951 INSERT_CAL(ahp, &ahp->ah_adcDcCalData); 901 INSERT_CAL(ahp, &ahp->ah_adcDcCalData);
952 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, 902 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
953 "enabling ADC DC Calibration.\n"); 903 "enabling ADC DC Calibration.\n");
954 } 904 }
955 if (ath9k_hw_iscal_supported(ah, chan, IQ_MISMATCH_CAL)) { 905 if (ath9k_hw_iscal_supported(ah, IQ_MISMATCH_CAL)) {
956 INIT_CAL(&ahp->ah_iqCalData); 906 INIT_CAL(&ahp->ah_iqCalData);
957 INSERT_CAL(ahp, &ahp->ah_iqCalData); 907 INSERT_CAL(ahp, &ahp->ah_iqCalData);
958 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, 908 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
@@ -965,7 +915,7 @@ bool ath9k_hw_init_cal(struct ath_hal *ah,
965 ath9k_hw_reset_calibration(ah, ahp->ah_cal_list_curr); 915 ath9k_hw_reset_calibration(ah, ahp->ah_cal_list_curr);
966 } 916 }
967 917
968 ichan->CalValid = 0; 918 chan->CalValid = 0;
969 919
970 return true; 920 return true;
971} 921}