diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/ar9002_calib.c')
| -rw-r--r-- | drivers/net/wireless/ath/ath9k/ar9002_calib.c | 192 |
1 files changed, 104 insertions, 88 deletions
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_calib.c b/drivers/net/wireless/ath/ath9k/ar9002_calib.c index 5e300bd3d26..cdc74005650 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_calib.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2010 Atheros Communications Inc. + * Copyright (c) 2008-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -26,6 +26,25 @@ enum ar9002_cal_types { IQ_MISMATCH_CAL = BIT(2), }; +static bool ar9002_hw_is_cal_supported(struct ath_hw *ah, + struct ath9k_channel *chan, + enum ar9002_cal_types cal_type) +{ + bool supported = false; + switch (ah->supp_cals & cal_type) { + case IQ_MISMATCH_CAL: + supported = true; + break; + case ADC_GAIN_CAL: + case ADC_DC_CAL: + /* Run ADC Gain Cal for non-CCK & non 2GHz-HT20 only */ + if (!((IS_CHAN_2GHZ(chan) || IS_CHAN_A_FAST_CLOCK(ah, chan)) && + IS_CHAN_HT20(chan))) + supported = true; + break; + } + return supported; +} static void ar9002_hw_setup_calibration(struct ath_hw *ah, struct ath9k_cal_list *currCal) @@ -39,18 +58,16 @@ static void ar9002_hw_setup_calibration(struct ath_hw *ah, switch (currCal->calData->calType) { case IQ_MISMATCH_CAL: REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ); - ath_dbg(common, ATH_DBG_CALIBRATE, + ath_dbg(common, CALIBRATE, "starting IQ Mismatch Calibration\n"); break; case ADC_GAIN_CAL: REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_GAIN); - ath_dbg(common, ATH_DBG_CALIBRATE, - "starting ADC Gain Calibration\n"); + ath_dbg(common, CALIBRATE, "starting ADC Gain Calibration\n"); break; case ADC_DC_CAL: REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_PER); - ath_dbg(common, ATH_DBG_CALIBRATE, - "starting ADC DC Calibration\n"); + ath_dbg(common, CALIBRATE, "starting ADC DC Calibration\n"); break; } @@ -107,7 +124,7 @@ static void ar9002_hw_iqcal_collect(struct ath_hw *ah) REG_READ(ah, AR_PHY_CAL_MEAS_1(i)); ah->totalIqCorrMeas[i] += (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i)); - ath_dbg(ath9k_hw_common(ah), ATH_DBG_CALIBRATE, + ath_dbg(ath9k_hw_common(ah), CALIBRATE, "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n", ah->cal_samples, i, ah->totalPowerMeasI[i], ah->totalPowerMeasQ[i], @@ -129,7 +146,7 @@ static void ar9002_hw_adc_gaincal_collect(struct ath_hw *ah) ah->totalAdcQEvenPhase[i] += REG_READ(ah, AR_PHY_CAL_MEAS_3(i)); - ath_dbg(ath9k_hw_common(ah), ATH_DBG_CALIBRATE, + ath_dbg(ath9k_hw_common(ah), CALIBRATE, "%d: Chn %d oddi=0x%08x; eveni=0x%08x; oddq=0x%08x; evenq=0x%08x;\n", ah->cal_samples, i, ah->totalAdcIOddPhase[i], @@ -153,7 +170,7 @@ static void ar9002_hw_adc_dccal_collect(struct ath_hw *ah) ah->totalAdcDcOffsetQEvenPhase[i] += (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_3(i)); - ath_dbg(ath9k_hw_common(ah), ATH_DBG_CALIBRATE, + ath_dbg(ath9k_hw_common(ah), CALIBRATE, "%d: Chn %d oddi=0x%08x; eveni=0x%08x; oddq=0x%08x; evenq=0x%08x;\n", ah->cal_samples, i, ah->totalAdcDcOffsetIOddPhase[i], @@ -176,12 +193,12 @@ static void ar9002_hw_iqcalibrate(struct ath_hw *ah, u8 numChains) powerMeasQ = ah->totalPowerMeasQ[i]; iqCorrMeas = ah->totalIqCorrMeas[i]; - ath_dbg(common, ATH_DBG_CALIBRATE, + ath_dbg(common, CALIBRATE, "Starting IQ Cal and Correction for Chain %d\n", i); - ath_dbg(common, ATH_DBG_CALIBRATE, - "Orignal: Chn %diq_corr_meas = 0x%08x\n", + ath_dbg(common, CALIBRATE, + "Original: Chn %d iq_corr_meas = 0x%08x\n", i, ah->totalIqCorrMeas[i]); iqCorrNeg = 0; @@ -191,12 +208,11 @@ static void ar9002_hw_iqcalibrate(struct ath_hw *ah, u8 numChains) iqCorrNeg = 1; } - ath_dbg(common, ATH_DBG_CALIBRATE, - "Chn %d pwr_meas_i = 0x%08x\n", i, powerMeasI); - ath_dbg(common, ATH_DBG_CALIBRATE, - "Chn %d pwr_meas_q = 0x%08x\n", i, powerMeasQ); - ath_dbg(common, ATH_DBG_CALIBRATE, "iqCorrNeg is 0x%08x\n", - iqCorrNeg); + ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_i = 0x%08x\n", + i, powerMeasI); + ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_q = 0x%08x\n", + i, powerMeasQ); + ath_dbg(common, CALIBRATE, "iqCorrNeg is 0x%08x\n", iqCorrNeg); iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 128; qCoffDenom = powerMeasQ / 64; @@ -205,13 +221,13 @@ static void ar9002_hw_iqcalibrate(struct ath_hw *ah, u8 numChains) (qCoffDenom != 0)) { iCoff = iqCorrMeas / iCoffDenom; qCoff = powerMeasI / qCoffDenom - 64; - ath_dbg(common, ATH_DBG_CALIBRATE, - "Chn %d iCoff = 0x%08x\n", i, iCoff); - ath_dbg(common, ATH_DBG_CALIBRATE, - "Chn %d qCoff = 0x%08x\n", i, qCoff); + ath_dbg(common, CALIBRATE, "Chn %d iCoff = 0x%08x\n", + i, iCoff); + ath_dbg(common, CALIBRATE, "Chn %d qCoff = 0x%08x\n", + i, qCoff); iCoff = iCoff & 0x3f; - ath_dbg(common, ATH_DBG_CALIBRATE, + ath_dbg(common, CALIBRATE, "New: Chn %d iCoff = 0x%08x\n", i, iCoff); if (iqCorrNeg == 0x0) iCoff = 0x40 - iCoff; @@ -221,7 +237,7 @@ static void ar9002_hw_iqcalibrate(struct ath_hw *ah, u8 numChains) else if (qCoff <= -16) qCoff = -16; - ath_dbg(common, ATH_DBG_CALIBRATE, + ath_dbg(common, CALIBRATE, "Chn %d : iCoff = 0x%x qCoff = 0x%x\n", i, iCoff, qCoff); @@ -231,7 +247,7 @@ static void ar9002_hw_iqcalibrate(struct ath_hw *ah, u8 numChains) REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i), AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF, qCoff); - ath_dbg(common, ATH_DBG_CALIBRATE, + ath_dbg(common, CALIBRATE, "IQ Cal and Correction done for Chain %d\n", i); } @@ -253,21 +269,17 @@ static void ar9002_hw_adc_gaincal_calibrate(struct ath_hw *ah, u8 numChains) qOddMeasOffset = ah->totalAdcQOddPhase[i]; qEvenMeasOffset = ah->totalAdcQEvenPhase[i]; - ath_dbg(common, ATH_DBG_CALIBRATE, + ath_dbg(common, CALIBRATE, "Starting ADC Gain Cal for Chain %d\n", i); - ath_dbg(common, ATH_DBG_CALIBRATE, - "Chn %d pwr_meas_odd_i = 0x%08x\n", i, - iOddMeasOffset); - ath_dbg(common, ATH_DBG_CALIBRATE, - "Chn %d pwr_meas_even_i = 0x%08x\n", i, - iEvenMeasOffset); - ath_dbg(common, ATH_DBG_CALIBRATE, - "Chn %d pwr_meas_odd_q = 0x%08x\n", i, - qOddMeasOffset); - ath_dbg(common, ATH_DBG_CALIBRATE, - "Chn %d pwr_meas_even_q = 0x%08x\n", i, - qEvenMeasOffset); + ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_odd_i = 0x%08x\n", + i, iOddMeasOffset); + ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_even_i = 0x%08x\n", + i, iEvenMeasOffset); + ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_odd_q = 0x%08x\n", + i, qOddMeasOffset); + ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_even_q = 0x%08x\n", + i, qEvenMeasOffset); if (iOddMeasOffset != 0 && qEvenMeasOffset != 0) { iGainMismatch = @@ -277,19 +289,19 @@ static void ar9002_hw_adc_gaincal_calibrate(struct ath_hw *ah, u8 numChains) ((qOddMeasOffset * 32) / qEvenMeasOffset) & 0x3f; - ath_dbg(common, ATH_DBG_CALIBRATE, - "Chn %d gain_mismatch_i = 0x%08x\n", i, - iGainMismatch); - ath_dbg(common, ATH_DBG_CALIBRATE, - "Chn %d gain_mismatch_q = 0x%08x\n", i, - qGainMismatch); + ath_dbg(common, CALIBRATE, + "Chn %d gain_mismatch_i = 0x%08x\n", + i, iGainMismatch); + ath_dbg(common, CALIBRATE, + "Chn %d gain_mismatch_q = 0x%08x\n", + i, qGainMismatch); val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i)); val &= 0xfffff000; val |= (qGainMismatch) | (iGainMismatch << 6); REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val); - ath_dbg(common, ATH_DBG_CALIBRATE, + ath_dbg(common, CALIBRATE, "ADC Gain Cal done for Chain %d\n", i); } } @@ -315,40 +327,36 @@ static void ar9002_hw_adc_dccal_calibrate(struct ath_hw *ah, u8 numChains) qOddMeasOffset = ah->totalAdcDcOffsetQOddPhase[i]; qEvenMeasOffset = ah->totalAdcDcOffsetQEvenPhase[i]; - ath_dbg(common, ATH_DBG_CALIBRATE, + ath_dbg(common, CALIBRATE, "Starting ADC DC Offset Cal for Chain %d\n", i); - ath_dbg(common, ATH_DBG_CALIBRATE, - "Chn %d pwr_meas_odd_i = %d\n", i, - iOddMeasOffset); - ath_dbg(common, ATH_DBG_CALIBRATE, - "Chn %d pwr_meas_even_i = %d\n", i, - iEvenMeasOffset); - ath_dbg(common, ATH_DBG_CALIBRATE, - "Chn %d pwr_meas_odd_q = %d\n", i, - qOddMeasOffset); - ath_dbg(common, ATH_DBG_CALIBRATE, - "Chn %d pwr_meas_even_q = %d\n", i, - qEvenMeasOffset); + ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_odd_i = %d\n", + i, iOddMeasOffset); + ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_even_i = %d\n", + i, iEvenMeasOffset); + ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_odd_q = %d\n", + i, qOddMeasOffset); + ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_even_q = %d\n", + i, qEvenMeasOffset); iDcMismatch = (((iEvenMeasOffset - iOddMeasOffset) * 2) / numSamples) & 0x1ff; qDcMismatch = (((qOddMeasOffset - qEvenMeasOffset) * 2) / numSamples) & 0x1ff; - ath_dbg(common, ATH_DBG_CALIBRATE, - "Chn %d dc_offset_mismatch_i = 0x%08x\n", i, - iDcMismatch); - ath_dbg(common, ATH_DBG_CALIBRATE, - "Chn %d dc_offset_mismatch_q = 0x%08x\n", i, - qDcMismatch); + ath_dbg(common, CALIBRATE, + "Chn %d dc_offset_mismatch_i = 0x%08x\n", + i, iDcMismatch); + ath_dbg(common, CALIBRATE, + "Chn %d dc_offset_mismatch_q = 0x%08x\n", + i, qDcMismatch); val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i)); val &= 0xc0000fff; val |= (qDcMismatch << 12) | (iDcMismatch << 21); REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val); - ath_dbg(common, ATH_DBG_CALIBRATE, + ath_dbg(common, CALIBRATE, "ADC DC Offset Cal done for Chain %d\n", i); } @@ -538,7 +546,7 @@ static inline void ar9285_hw_pa_cal(struct ath_hw *ah, bool is_reset) { 0x7838, 0 }, }; - ath_dbg(common, ATH_DBG_CALIBRATE, "Running PA Calibration\n"); + ath_dbg(common, CALIBRATE, "Running PA Calibration\n"); /* PA CAL is not needed for high power solution */ if (ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE) == @@ -660,7 +668,7 @@ static bool ar9002_hw_calibrate(struct ath_hw *ah, nfcal = !!(REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF); if (ah->caldata) - nfcal_pending = ah->caldata->nfcal_pending; + nfcal_pending = test_bit(NFCAL_PENDING, &ah->caldata->cal_flags); if (currCal && !nfcal && (currCal->calState == CAL_RUNNING || @@ -719,8 +727,9 @@ static bool ar9285_hw_cl_cal(struct ath_hw *ah, struct ath9k_channel *chan) REG_SET_BIT(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)) { - ath_dbg(common, ATH_DBG_CALIBRATE, - "offset calibration failed to complete in 1ms; noisy environment?\n"); + ath_dbg(common, CALIBRATE, + "offset calibration failed to complete in %d ms; noisy environment?\n", + AH_WAIT_TIMEOUT / 1000); return false; } REG_CLR_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN); @@ -733,8 +742,9 @@ static bool ar9285_hw_cl_cal(struct ath_hw *ah, struct ath9k_channel *chan) REG_SET_BIT(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)) { - ath_dbg(common, ATH_DBG_CALIBRATE, - "offset calibration failed to complete in 1ms; noisy environment?\n"); + ath_dbg(common, CALIBRATE, + "offset calibration failed to complete in %d ms; noisy environment?\n", + AH_WAIT_TIMEOUT / 1000); return false; } @@ -805,7 +815,10 @@ static bool ar9002_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan) { struct ath_common *common = ath9k_hw_common(ah); - if (AR_SREV_9271(ah) || AR_SREV_9285_12_OR_LATER(ah)) { + if (AR_SREV_9271(ah)) { + if (!ar9285_hw_cl_cal(ah, chan)) + return false; + } else if (AR_SREV_9285(ah) && AR_SREV_9285_12_OR_LATER(ah)) { if (!ar9285_hw_clc(ah, chan)) return false; } else { @@ -826,8 +839,9 @@ static bool ar9002_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan) if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, 0, AH_WAIT_TIMEOUT)) { - ath_dbg(common, ATH_DBG_CALIBRATE, - "offset calibration failed to complete in 1ms; noisy environment?\n"); + ath_dbg(common, CALIBRATE, + "offset calibration failed to complete in %d ms; noisy environment?\n", + AH_WAIT_TIMEOUT / 1000); return false; } @@ -843,11 +857,8 @@ static bool ar9002_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan) /* Do PA Calibration */ ar9002_hw_pa_cal(ah, true); - /* Do NF Calibration after DC offset and other calibrations */ - ath9k_hw_start_nfcal(ah, true); - if (ah->caldata) - ah->caldata->nfcal_pending = true; + set_bit(NFCAL_PENDING, &ah->caldata->cal_flags); ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL; @@ -855,26 +866,31 @@ static bool ar9002_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan) if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) { ah->supp_cals = IQ_MISMATCH_CAL; - if (AR_SREV_9160_10_OR_LATER(ah) && - !(IS_CHAN_2GHZ(chan) && IS_CHAN_HT20(chan))) { + if (AR_SREV_9160_10_OR_LATER(ah)) ah->supp_cals |= ADC_GAIN_CAL | ADC_DC_CAL; + if (AR_SREV_9287(ah)) + ah->supp_cals &= ~ADC_GAIN_CAL; + if (ar9002_hw_is_cal_supported(ah, chan, ADC_GAIN_CAL)) { INIT_CAL(&ah->adcgain_caldata); INSERT_CAL(ah, &ah->adcgain_caldata); - ath_dbg(common, ATH_DBG_CALIBRATE, - "enabling ADC Gain Calibration.\n"); + ath_dbg(common, CALIBRATE, + "enabling ADC Gain Calibration\n"); + } + if (ar9002_hw_is_cal_supported(ah, chan, ADC_DC_CAL)) { INIT_CAL(&ah->adcdc_caldata); INSERT_CAL(ah, &ah->adcdc_caldata); - ath_dbg(common, ATH_DBG_CALIBRATE, - "enabling ADC DC Calibration.\n"); + ath_dbg(common, CALIBRATE, + "enabling ADC DC Calibration\n"); } - INIT_CAL(&ah->iq_caldata); - INSERT_CAL(ah, &ah->iq_caldata); - ath_dbg(common, ATH_DBG_CALIBRATE, - "enabling IQ Calibration.\n"); + if (ar9002_hw_is_cal_supported(ah, chan, IQ_MISMATCH_CAL)) { + INIT_CAL(&ah->iq_caldata); + INSERT_CAL(ah, &ah->iq_caldata); + ath_dbg(common, CALIBRATE, "enabling IQ Calibration\n"); + } ah->cal_list_curr = ah->cal_list; |
