ath9k: Fix bug in calibration initialization

This patch fixes a bug in ath9k_hw_init_cal() where the wrong
calibration was being done for non-AR9285 chipsets.
Also add a few helpful comments.

Cc: stable@kernel.org
Signed-off-by: Sujith <Sujith.Manoharan@atheros.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
Sujith 2009-04-13 21:56:59 +05:30 committed by John W. Linville
parent cbfe946860
commit 04d19ddd25

View file

@ -918,83 +918,66 @@ static bool ar9285_clc(struct ath_hw *ah, struct ath9k_channel *chan)
return true; return true;
} }
bool ath9k_hw_init_cal(struct ath_hw *ah, bool ath9k_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan)
struct ath9k_channel *chan)
{ {
if (AR_SREV_9285(ah) && AR_SREV_9285_12_OR_LATER(ah)) { if (AR_SREV_9285(ah) && AR_SREV_9285_12_OR_LATER(ah)) {
if (!ar9285_clc(ah, chan)) if (!ar9285_clc(ah, chan))
return false; return false;
} else if (AR_SREV_9280_10_OR_LATER(ah)) { } else {
REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC); if (AR_SREV_9280_10_OR_LATER(ah)) {
REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL); REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); 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_WRITE(ah, AR_PHY_AGC_CONTROL,
REG_READ(ah, AR_PHY_AGC_CONTROL) | REG_READ(ah, AR_PHY_AGC_CONTROL) |
AR_PHY_AGC_CONTROL_CAL); AR_PHY_AGC_CONTROL_CAL);
if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, /* Poll for offset calibration complete */
AR_PHY_AGC_CONTROL_CAL, 0, if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL,
AH_WAIT_TIMEOUT)) { 0, AH_WAIT_TIMEOUT)) {
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
"offset calibration failed to complete in 1ms; " "offset calibration failed to complete in 1ms; "
"noisy environment?\n"); "noisy environment?\n");
return false; return false;
} }
REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC); if (AR_SREV_9280_10_OR_LATER(ah)) {
REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL); REG_SET_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL);
} }
/* 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);
} }
/* Do PA Calibration */ /* Do PA Calibration */
if (AR_SREV_9285(ah) && AR_SREV_9285_11_OR_LATER(ah)) if (AR_SREV_9285(ah) && AR_SREV_9285_11_OR_LATER(ah))
ath9k_hw_9285_pa_cal(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_WRITE(ah, AR_PHY_AGC_CONTROL,
REG_READ(ah, AR_PHY_AGC_CONTROL) | REG_READ(ah, AR_PHY_AGC_CONTROL) | AR_PHY_AGC_CONTROL_NF);
AR_PHY_AGC_CONTROL_NF);
ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL; 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 (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) {
if (ath9k_hw_iscal_supported(ah, ADC_GAIN_CAL)) { if (ath9k_hw_iscal_supported(ah, ADC_GAIN_CAL)) {
INIT_CAL(&ah->adcgain_caldata); INIT_CAL(&ah->adcgain_caldata);
INSERT_CAL(ah, &ah->adcgain_caldata); INSERT_CAL(ah, &ah->adcgain_caldata);
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, 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)) { if (ath9k_hw_iscal_supported(ah, ADC_DC_CAL)) {
INIT_CAL(&ah->adcdc_caldata); INIT_CAL(&ah->adcdc_caldata);
INSERT_CAL(ah, &ah->adcdc_caldata); INSERT_CAL(ah, &ah->adcdc_caldata);
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, 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)) { if (ath9k_hw_iscal_supported(ah, IQ_MISMATCH_CAL)) {
INIT_CAL(&ah->iq_caldata); INIT_CAL(&ah->iq_caldata);
INSERT_CAL(ah, &ah->iq_caldata); INSERT_CAL(ah, &ah->iq_caldata);
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
"enabling IQ Calibration.\n"); "enabling IQ Calibration.\n");
} }
ah->cal_list_curr = ah->cal_list; ah->cal_list_curr = ah->cal_list;