ath9k: Add support for AR9287 based chipsets.
[cascardo/linux.git] / drivers / net / wireless / ath / ath9k / calib.c
index 67375ad..d1bbb02 100644 (file)
@@ -116,7 +116,7 @@ static void ath9k_hw_do_getnf(struct ath_hw *ah,
                                "NF calibrated [ctl] [chain 1] is %d\n", nf);
                nfarray[1] = nf;
 
-               if (!AR_SREV_9280(ah)) {
+               if (!AR_SREV_9280(ah) && !AR_SREV_9287(ah)) {
                        nf = MS(REG_READ(ah, AR_PHY_CH2_CCA),
                                        AR_PHY_CH2_MINCCA_PWR);
                        if (nf & 0x100)
@@ -154,7 +154,7 @@ static void ath9k_hw_do_getnf(struct ath_hw *ah,
                                "NF calibrated [ext] [chain 1] is %d\n", nf);
                nfarray[4] = nf;
 
-               if (!AR_SREV_9280(ah)) {
+               if (!AR_SREV_9280(ah) && !AR_SREV_9287(ah)) {
                        nf = MS(REG_READ(ah, AR_PHY_CH2_EXT_CCA),
                                        AR_PHY_CH2_EXT_MINCCA_PWR);
                        if (nf & 0x100)
@@ -613,7 +613,7 @@ void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan)
 
        if (AR_SREV_9285(ah))
                chainmask = 0x9;
-       else if (AR_SREV_9280(ah))
+       else if (AR_SREV_9280(ah) || AR_SREV_9287(ah))
                chainmask = 0x1B;
        else
                chainmask = 0x3F;
@@ -691,15 +691,22 @@ int16_t ath9k_hw_getnf(struct ath_hw *ah,
 void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah)
 {
        int i, j;
+       s16 noise_floor;
+
+       if (AR_SREV_9280(ah))
+               noise_floor = AR_PHY_CCA_MAX_AR9280_GOOD_VALUE;
+       else if (AR_SREV_9285(ah))
+               noise_floor = AR_PHY_CCA_MAX_AR9285_GOOD_VALUE;
+       else
+               noise_floor = AR_PHY_CCA_MAX_AR5416_GOOD_VALUE;
 
        for (i = 0; i < NUM_NF_READINGS; i++) {
                ah->nfCalHist[i].currIndex = 0;
-               ah->nfCalHist[i].privNF = AR_PHY_CCA_MAX_GOOD_VALUE;
+               ah->nfCalHist[i].privNF = noise_floor;
                ah->nfCalHist[i].invalidNFcount =
                        AR_PHY_CCA_FILTERWINDOW_LENGTH;
                for (j = 0; j < ATH9K_NF_CAL_HIST_MAX; j++) {
-                       ah->nfCalHist[i].nfCalBuffer[j] =
-                               AR_PHY_CCA_MAX_GOOD_VALUE;
+                       ah->nfCalHist[i].nfCalBuffer[j] = noise_floor;
                }
        }
 }
@@ -863,17 +870,14 @@ bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan,
        }
 
        if (longcal) {
-               if (AR_SREV_9285(ah) && AR_SREV_9285_11_OR_LATER(ah))
+               if (AR_SREV_9285_11_OR_LATER(ah))
                        ath9k_hw_9285_pa_cal(ah);
 
-               if (OLC_FOR_AR9280_20_LATER)
+               if (OLC_FOR_AR9280_20_LATER || OLC_FOR_AR9287_10_LATER)
                        ath9k_olc_temp_compensation(ah);
                ath9k_hw_getnf(ah, chan);
                ath9k_hw_loadnf(ah, ah->curchan);
                ath9k_hw_start_nfcal(ah);
-
-               if (chan->channelFlags & CHANNEL_CW_INT)
-                       chan->channelFlags &= ~CHANNEL_CW_INT;
        }
 
        return iscaldone;
@@ -918,83 +922,72 @@ static bool ar9285_clc(struct ath_hw *ah, struct ath9k_channel *chan)
        return true;
 }
 
-bool ath9k_hw_init_cal(struct ath_hw *ah,
-                      struct ath9k_channel *chan)
+bool ath9k_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan)
 {
-       if (AR_SREV_9285(ah) && AR_SREV_9285_12_OR_LATER(ah)) {
+       if (AR_SREV_9285_12_OR_LATER(ah)) {
                if (!ar9285_clc(ah, chan))
                        return false;
-       } else if (AR_SREV_9280_10_OR_LATER(ah)) {
-               REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
-               REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL);
-               REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
+       } else {
+               if (AR_SREV_9280_10_OR_LATER(ah)) {
+                       if (!AR_SREV_9287_10_OR_LATER(ah))
+                               REG_CLR_BIT(ah, AR_PHY_ADC_CTL,
+                                           AR_PHY_ADC_CTL_OFF_PWDADC);
+                       REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
+                                   AR_PHY_AGC_CONTROL_FLTR_CAL);
+               }
 
-               /* Kick off the cal */
+               /* Calibrate the AGC */
                REG_WRITE(ah, AR_PHY_AGC_CONTROL,
-                               REG_READ(ah, AR_PHY_AGC_CONTROL) |
-                               AR_PHY_AGC_CONTROL_CAL);
+                         REG_READ(ah, AR_PHY_AGC_CONTROL) |
+                         AR_PHY_AGC_CONTROL_CAL);
 
-               if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL,
-                                       AR_PHY_AGC_CONTROL_CAL, 0,
-                                       AH_WAIT_TIMEOUT)) {
+               /* Poll for offset calibration complete */
+               if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL,
+                                  0, AH_WAIT_TIMEOUT)) {
                        DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
                                "offset calibration failed to complete in 1ms; "
                                "noisy environment?\n");
                        return false;
                }
 
-               REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
-               REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL);
-               REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
-       }
-
-       /* Calibrate the AGC */
-       REG_WRITE(ah, AR_PHY_AGC_CONTROL,
-                       REG_READ(ah, AR_PHY_AGC_CONTROL) |
-                       AR_PHY_AGC_CONTROL_CAL);
-
-       if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL,
-                               0, AH_WAIT_TIMEOUT)) {
-               DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-                       "offset calibration failed to complete in 1ms; "
-                       "noisy environment?\n");
-               return false;
-       }
-
-       if (AR_SREV_9280_10_OR_LATER(ah)) {
-               REG_SET_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
-               REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL);
+               if (AR_SREV_9280_10_OR_LATER(ah)) {
+                       if (!AR_SREV_9287_10_OR_LATER(ah))
+                               REG_SET_BIT(ah, AR_PHY_ADC_CTL,
+                                           AR_PHY_ADC_CTL_OFF_PWDADC);
+                       REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
+                                   AR_PHY_AGC_CONTROL_FLTR_CAL);
+               }
        }
 
        /* Do PA Calibration */
-       if (AR_SREV_9285(ah) && AR_SREV_9285_11_OR_LATER(ah))
+       if (AR_SREV_9285_11_OR_LATER(ah))
                ath9k_hw_9285_pa_cal(ah);
 
-       /* Do NF Calibration */
+       /* Do NF Calibration after DC offset and other calibrations */
        REG_WRITE(ah, AR_PHY_AGC_CONTROL,
-                       REG_READ(ah, AR_PHY_AGC_CONTROL) |
-                       AR_PHY_AGC_CONTROL_NF);
+                 REG_READ(ah, AR_PHY_AGC_CONTROL) | AR_PHY_AGC_CONTROL_NF);
 
        ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL;
 
+       /* Enable IQ, ADC Gain and ADC DC offset CALs */
        if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) {
                if (ath9k_hw_iscal_supported(ah, ADC_GAIN_CAL)) {
                        INIT_CAL(&ah->adcgain_caldata);
                        INSERT_CAL(ah, &ah->adcgain_caldata);
                        DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-                                       "enabling ADC Gain Calibration.\n");
+                               "enabling ADC Gain Calibration.\n");
                }
                if (ath9k_hw_iscal_supported(ah, ADC_DC_CAL)) {
                        INIT_CAL(&ah->adcdc_caldata);
                        INSERT_CAL(ah, &ah->adcdc_caldata);
                        DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-                                       "enabling ADC DC Calibration.\n");
+                               "enabling ADC DC Calibration.\n");
                }
                if (ath9k_hw_iscal_supported(ah, IQ_MISMATCH_CAL)) {
                        INIT_CAL(&ah->iq_caldata);
                        INSERT_CAL(ah, &ah->iq_caldata);
                        DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-                                       "enabling IQ Calibration.\n");
+                               "enabling IQ Calibration.\n");
                }
 
                ah->cal_list_curr = ah->cal_list;