Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright (c) 2008-2011 Atheros Communications Inc.
0003  *
0004  * Permission to use, copy, modify, and/or distribute this software for any
0005  * purpose with or without fee is hereby granted, provided that the above
0006  * copyright notice and this permission notice appear in all copies.
0007  *
0008  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
0009  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
0010  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
0011  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
0012  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
0013  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
0014  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
0015  */
0016 
0017 #include "hw.h"
0018 #include "hw-ops.h"
0019 #include "ar9002_phy.h"
0020 
0021 #define AR9285_CLCAL_REDO_THRESH    1
0022 /* AGC & I/Q calibrations time limit, ms */
0023 #define AR9002_CAL_MAX_TIME     30000
0024 
0025 enum ar9002_cal_types {
0026     ADC_GAIN_CAL = BIT(0),
0027     ADC_DC_CAL = BIT(1),
0028     IQ_MISMATCH_CAL = BIT(2),
0029 };
0030 
0031 static bool ar9002_hw_is_cal_supported(struct ath_hw *ah,
0032                 struct ath9k_channel *chan,
0033                 enum ar9002_cal_types cal_type)
0034 {
0035     bool supported = false;
0036     switch (ah->supp_cals & cal_type) {
0037     case IQ_MISMATCH_CAL:
0038         supported = true;
0039         break;
0040     case ADC_GAIN_CAL:
0041     case ADC_DC_CAL:
0042         /* Run even/odd ADCs calibrations for HT40 channels only */
0043         if (IS_CHAN_HT40(chan))
0044             supported = true;
0045         break;
0046     }
0047     return supported;
0048 }
0049 
0050 static void ar9002_hw_setup_calibration(struct ath_hw *ah,
0051                     struct ath9k_cal_list *currCal)
0052 {
0053     struct ath_common *common = ath9k_hw_common(ah);
0054 
0055     REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(0),
0056               AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX,
0057               currCal->calData->calCountMax);
0058 
0059     switch (currCal->calData->calType) {
0060     case IQ_MISMATCH_CAL:
0061         REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ);
0062         ath_dbg(common, CALIBRATE,
0063             "starting IQ Mismatch Calibration\n");
0064         break;
0065     case ADC_GAIN_CAL:
0066         REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_GAIN);
0067         ath_dbg(common, CALIBRATE, "starting ADC Gain Calibration\n");
0068         break;
0069     case ADC_DC_CAL:
0070         REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_PER);
0071         ath_dbg(common, CALIBRATE, "starting ADC DC Calibration\n");
0072         break;
0073     }
0074 
0075     REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0),
0076             AR_PHY_TIMING_CTRL4_DO_CAL);
0077 }
0078 
0079 static bool ar9002_hw_per_calibration(struct ath_hw *ah,
0080                       struct ath9k_channel *ichan,
0081                       u8 rxchainmask,
0082                       struct ath9k_cal_list *currCal)
0083 {
0084     struct ath9k_hw_cal_data *caldata = ah->caldata;
0085     bool iscaldone = false;
0086 
0087     if (currCal->calState == CAL_RUNNING) {
0088         if (!(REG_READ(ah, AR_PHY_TIMING_CTRL4(0)) &
0089               AR_PHY_TIMING_CTRL4_DO_CAL)) {
0090 
0091             currCal->calData->calCollect(ah);
0092             ah->cal_samples++;
0093 
0094             if (ah->cal_samples >=
0095                 currCal->calData->calNumSamples) {
0096                 int i, numChains = 0;
0097                 for (i = 0; i < AR5416_MAX_CHAINS; i++) {
0098                     if (rxchainmask & (1 << i))
0099                         numChains++;
0100                 }
0101 
0102                 currCal->calData->calPostProc(ah, numChains);
0103                 caldata->CalValid |= currCal->calData->calType;
0104                 currCal->calState = CAL_DONE;
0105                 iscaldone = true;
0106             } else {
0107                 ar9002_hw_setup_calibration(ah, currCal);
0108             }
0109         } else if (time_after(jiffies, ah->cal_start_time +
0110                       msecs_to_jiffies(AR9002_CAL_MAX_TIME))) {
0111             REG_CLR_BIT(ah, AR_PHY_TIMING_CTRL4(0),
0112                     AR_PHY_TIMING_CTRL4_DO_CAL);
0113             ath_dbg(ath9k_hw_common(ah), CALIBRATE,
0114                 "calibration timeout\n");
0115             currCal->calState = CAL_WAITING;    /* Try later */
0116             iscaldone = true;
0117         }
0118     } else if (!(caldata->CalValid & currCal->calData->calType)) {
0119         ath9k_hw_reset_calibration(ah, currCal);
0120     }
0121 
0122     return iscaldone;
0123 }
0124 
0125 static void ar9002_hw_iqcal_collect(struct ath_hw *ah)
0126 {
0127     int i;
0128 
0129     for (i = 0; i < AR5416_MAX_CHAINS; i++) {
0130         ah->totalPowerMeasI[i] +=
0131             REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
0132         ah->totalPowerMeasQ[i] +=
0133             REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
0134         ah->totalIqCorrMeas[i] +=
0135             (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
0136         ath_dbg(ath9k_hw_common(ah), CALIBRATE,
0137             "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n",
0138             ah->cal_samples, i, ah->totalPowerMeasI[i],
0139             ah->totalPowerMeasQ[i],
0140             ah->totalIqCorrMeas[i]);
0141     }
0142 }
0143 
0144 static void ar9002_hw_adc_gaincal_collect(struct ath_hw *ah)
0145 {
0146     int i;
0147 
0148     for (i = 0; i < AR5416_MAX_CHAINS; i++) {
0149         ah->totalAdcIOddPhase[i] +=
0150             REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
0151         ah->totalAdcIEvenPhase[i] +=
0152             REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
0153         ah->totalAdcQOddPhase[i] +=
0154             REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
0155         ah->totalAdcQEvenPhase[i] +=
0156             REG_READ(ah, AR_PHY_CAL_MEAS_3(i));
0157 
0158         ath_dbg(ath9k_hw_common(ah), CALIBRATE,
0159             "%d: Chn %d oddi=0x%08x; eveni=0x%08x; oddq=0x%08x; evenq=0x%08x;\n",
0160             ah->cal_samples, i,
0161             ah->totalAdcIOddPhase[i],
0162             ah->totalAdcIEvenPhase[i],
0163             ah->totalAdcQOddPhase[i],
0164             ah->totalAdcQEvenPhase[i]);
0165     }
0166 }
0167 
0168 static void ar9002_hw_adc_dccal_collect(struct ath_hw *ah)
0169 {
0170     int i;
0171 
0172     for (i = 0; i < AR5416_MAX_CHAINS; i++) {
0173         ah->totalAdcDcOffsetIOddPhase[i] +=
0174             (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
0175         ah->totalAdcDcOffsetIEvenPhase[i] +=
0176             (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
0177         ah->totalAdcDcOffsetQOddPhase[i] +=
0178             (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
0179         ah->totalAdcDcOffsetQEvenPhase[i] +=
0180             (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_3(i));
0181 
0182         ath_dbg(ath9k_hw_common(ah), CALIBRATE,
0183             "%d: Chn %d oddi=0x%08x; eveni=0x%08x; oddq=0x%08x; evenq=0x%08x;\n",
0184             ah->cal_samples, i,
0185             ah->totalAdcDcOffsetIOddPhase[i],
0186             ah->totalAdcDcOffsetIEvenPhase[i],
0187             ah->totalAdcDcOffsetQOddPhase[i],
0188             ah->totalAdcDcOffsetQEvenPhase[i]);
0189     }
0190 }
0191 
0192 static void ar9002_hw_iqcalibrate(struct ath_hw *ah, u8 numChains)
0193 {
0194     struct ath_common *common = ath9k_hw_common(ah);
0195     u32 powerMeasQ, powerMeasI, iqCorrMeas;
0196     u32 qCoffDenom, iCoffDenom;
0197     int32_t qCoff, iCoff;
0198     int iqCorrNeg, i;
0199 
0200     for (i = 0; i < numChains; i++) {
0201         powerMeasI = ah->totalPowerMeasI[i];
0202         powerMeasQ = ah->totalPowerMeasQ[i];
0203         iqCorrMeas = ah->totalIqCorrMeas[i];
0204 
0205         ath_dbg(common, CALIBRATE,
0206             "Starting IQ Cal and Correction for Chain %d\n",
0207             i);
0208 
0209         ath_dbg(common, CALIBRATE,
0210             "Original: Chn %d iq_corr_meas = 0x%08x\n",
0211             i, ah->totalIqCorrMeas[i]);
0212 
0213         iqCorrNeg = 0;
0214 
0215         if (iqCorrMeas > 0x80000000) {
0216             iqCorrMeas = (0xffffffff - iqCorrMeas) + 1;
0217             iqCorrNeg = 1;
0218         }
0219 
0220         ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_i = 0x%08x\n",
0221             i, powerMeasI);
0222         ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_q = 0x%08x\n",
0223             i, powerMeasQ);
0224         ath_dbg(common, CALIBRATE, "iqCorrNeg is 0x%08x\n", iqCorrNeg);
0225 
0226         iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 128;
0227         qCoffDenom = powerMeasQ / 64;
0228 
0229         if ((powerMeasQ != 0) && (iCoffDenom != 0) &&
0230             (qCoffDenom != 0)) {
0231             iCoff = iqCorrMeas / iCoffDenom;
0232             qCoff = powerMeasI / qCoffDenom - 64;
0233             ath_dbg(common, CALIBRATE, "Chn %d iCoff = 0x%08x\n",
0234                 i, iCoff);
0235             ath_dbg(common, CALIBRATE, "Chn %d qCoff = 0x%08x\n",
0236                 i, qCoff);
0237 
0238             iCoff = iCoff & 0x3f;
0239             ath_dbg(common, CALIBRATE,
0240                 "New: Chn %d iCoff = 0x%08x\n", i, iCoff);
0241             if (iqCorrNeg == 0x0)
0242                 iCoff = 0x40 - iCoff;
0243 
0244             if (qCoff > 15)
0245                 qCoff = 15;
0246             else if (qCoff <= -16)
0247                 qCoff = -16;
0248 
0249             ath_dbg(common, CALIBRATE,
0250                 "Chn %d : iCoff = 0x%x  qCoff = 0x%x\n",
0251                 i, iCoff, qCoff);
0252 
0253             REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i),
0254                       AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF,
0255                       iCoff);
0256             REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i),
0257                       AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF,
0258                       qCoff);
0259             ath_dbg(common, CALIBRATE,
0260                 "IQ Cal and Correction done for Chain %d\n",
0261                 i);
0262         }
0263     }
0264 
0265     REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0),
0266             AR_PHY_TIMING_CTRL4_IQCORR_ENABLE);
0267 }
0268 
0269 static void ar9002_hw_adc_gaincal_calibrate(struct ath_hw *ah, u8 numChains)
0270 {
0271     struct ath_common *common = ath9k_hw_common(ah);
0272     u32 iOddMeasOffset, iEvenMeasOffset, qOddMeasOffset, qEvenMeasOffset;
0273     u32 qGainMismatch, iGainMismatch, val, i;
0274 
0275     for (i = 0; i < numChains; i++) {
0276         iOddMeasOffset = ah->totalAdcIOddPhase[i];
0277         iEvenMeasOffset = ah->totalAdcIEvenPhase[i];
0278         qOddMeasOffset = ah->totalAdcQOddPhase[i];
0279         qEvenMeasOffset = ah->totalAdcQEvenPhase[i];
0280 
0281         ath_dbg(common, CALIBRATE,
0282             "Starting ADC Gain Cal for Chain %d\n", i);
0283 
0284         ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_odd_i = 0x%08x\n",
0285             i, iOddMeasOffset);
0286         ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_even_i = 0x%08x\n",
0287             i, iEvenMeasOffset);
0288         ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_odd_q = 0x%08x\n",
0289             i, qOddMeasOffset);
0290         ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_even_q = 0x%08x\n",
0291             i, qEvenMeasOffset);
0292 
0293         if (iOddMeasOffset != 0 && qEvenMeasOffset != 0) {
0294             iGainMismatch =
0295                 ((iEvenMeasOffset * 32) /
0296                  iOddMeasOffset) & 0x3f;
0297             qGainMismatch =
0298                 ((qOddMeasOffset * 32) /
0299                  qEvenMeasOffset) & 0x3f;
0300 
0301             ath_dbg(common, CALIBRATE,
0302                 "Chn %d gain_mismatch_i = 0x%08x\n",
0303                 i, iGainMismatch);
0304             ath_dbg(common, CALIBRATE,
0305                 "Chn %d gain_mismatch_q = 0x%08x\n",
0306                 i, qGainMismatch);
0307 
0308             val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i));
0309             val &= 0xfffff000;
0310             val |= (qGainMismatch) | (iGainMismatch << 6);
0311             REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val);
0312 
0313             ath_dbg(common, CALIBRATE,
0314                 "ADC Gain Cal done for Chain %d\n", i);
0315         }
0316     }
0317 
0318     REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0),
0319           REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) |
0320           AR_PHY_NEW_ADC_GAIN_CORR_ENABLE);
0321 }
0322 
0323 static void ar9002_hw_adc_dccal_calibrate(struct ath_hw *ah, u8 numChains)
0324 {
0325     struct ath_common *common = ath9k_hw_common(ah);
0326     u32 iOddMeasOffset, iEvenMeasOffset, val, i;
0327     int32_t qOddMeasOffset, qEvenMeasOffset, qDcMismatch, iDcMismatch;
0328     const struct ath9k_percal_data *calData =
0329         ah->cal_list_curr->calData;
0330     u32 numSamples =
0331         (1 << (calData->calCountMax + 5)) * calData->calNumSamples;
0332 
0333     for (i = 0; i < numChains; i++) {
0334         iOddMeasOffset = ah->totalAdcDcOffsetIOddPhase[i];
0335         iEvenMeasOffset = ah->totalAdcDcOffsetIEvenPhase[i];
0336         qOddMeasOffset = ah->totalAdcDcOffsetQOddPhase[i];
0337         qEvenMeasOffset = ah->totalAdcDcOffsetQEvenPhase[i];
0338 
0339         ath_dbg(common, CALIBRATE,
0340             "Starting ADC DC Offset Cal for Chain %d\n", i);
0341 
0342         ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_odd_i = %d\n",
0343             i, iOddMeasOffset);
0344         ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_even_i = %d\n",
0345             i, iEvenMeasOffset);
0346         ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_odd_q = %d\n",
0347             i, qOddMeasOffset);
0348         ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_even_q = %d\n",
0349             i, qEvenMeasOffset);
0350 
0351         iDcMismatch = (((iEvenMeasOffset - iOddMeasOffset) * 2) /
0352                    numSamples) & 0x1ff;
0353         qDcMismatch = (((qOddMeasOffset - qEvenMeasOffset) * 2) /
0354                    numSamples) & 0x1ff;
0355 
0356         ath_dbg(common, CALIBRATE,
0357             "Chn %d dc_offset_mismatch_i = 0x%08x\n",
0358             i, iDcMismatch);
0359         ath_dbg(common, CALIBRATE,
0360             "Chn %d dc_offset_mismatch_q = 0x%08x\n",
0361             i, qDcMismatch);
0362 
0363         val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i));
0364         val &= 0xc0000fff;
0365         val |= (qDcMismatch << 12) | (iDcMismatch << 21);
0366         REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val);
0367 
0368         ath_dbg(common, CALIBRATE,
0369             "ADC DC Offset Cal done for Chain %d\n", i);
0370     }
0371 
0372     REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0),
0373           REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) |
0374           AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE);
0375 }
0376 
0377 static void ar9287_hw_olc_temp_compensation(struct ath_hw *ah)
0378 {
0379     u32 rddata;
0380     int32_t delta, currPDADC, slope;
0381 
0382     rddata = REG_READ(ah, AR_PHY_TX_PWRCTRL4);
0383     currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT);
0384 
0385     if (ah->initPDADC == 0 || currPDADC == 0) {
0386         /*
0387          * Zero value indicates that no frames have been transmitted
0388          * yet, can't do temperature compensation until frames are
0389          * transmitted.
0390          */
0391         return;
0392     } else {
0393         slope = ah->eep_ops->get_eeprom(ah, EEP_TEMPSENSE_SLOPE);
0394 
0395         if (slope == 0) { /* to avoid divide by zero case */
0396             delta = 0;
0397         } else {
0398             delta = ((currPDADC - ah->initPDADC)*4) / slope;
0399         }
0400         REG_RMW_FIELD(ah, AR_PHY_CH0_TX_PWRCTRL11,
0401                   AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, delta);
0402         REG_RMW_FIELD(ah, AR_PHY_CH1_TX_PWRCTRL11,
0403                   AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, delta);
0404     }
0405 }
0406 
0407 static void ar9280_hw_olc_temp_compensation(struct ath_hw *ah)
0408 {
0409     u32 rddata, i;
0410     int delta, currPDADC, regval;
0411 
0412     rddata = REG_READ(ah, AR_PHY_TX_PWRCTRL4);
0413     currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT);
0414 
0415     if (ah->initPDADC == 0 || currPDADC == 0)
0416         return;
0417 
0418     if (ah->eep_ops->get_eeprom(ah, EEP_DAC_HPWR_5G))
0419         delta = (currPDADC - ah->initPDADC + 4) / 8;
0420     else
0421         delta = (currPDADC - ah->initPDADC + 5) / 10;
0422 
0423     if (delta != ah->PDADCdelta) {
0424         ah->PDADCdelta = delta;
0425         for (i = 1; i < AR9280_TX_GAIN_TABLE_SIZE; i++) {
0426             regval = ah->originalGain[i] - delta;
0427             if (regval < 0)
0428                 regval = 0;
0429 
0430             REG_RMW_FIELD(ah,
0431                       AR_PHY_TX_GAIN_TBL1 + i * 4,
0432                       AR_PHY_TX_GAIN, regval);
0433         }
0434     }
0435 }
0436 
0437 static void ar9271_hw_pa_cal(struct ath_hw *ah, bool is_reset)
0438 {
0439     u32 regVal;
0440     unsigned int i;
0441     u32 regList[][2] = {
0442         { AR9285_AN_TOP3, 0 },
0443         { AR9285_AN_RXTXBB1, 0 },
0444         { AR9285_AN_RF2G1, 0 },
0445         { AR9285_AN_RF2G2, 0 },
0446         { AR9285_AN_TOP2, 0 },
0447         { AR9285_AN_RF2G8, 0 },
0448         { AR9285_AN_RF2G7, 0 },
0449         { AR9285_AN_RF2G3, 0 },
0450     };
0451 
0452     REG_READ_ARRAY(ah, regList, ARRAY_SIZE(regList));
0453 
0454     ENABLE_REG_RMW_BUFFER(ah);
0455     /* 7834, b1=0 */
0456     REG_CLR_BIT(ah, AR9285_AN_RF2G6, 1 << 0);
0457     /* 9808, b27=1 */
0458     REG_SET_BIT(ah, 0x9808, 1 << 27);
0459     /* 786c,b23,1, pwddac=1 */
0460     REG_SET_BIT(ah, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC);
0461     /* 7854, b5,1, pdrxtxbb=1 */
0462     REG_SET_BIT(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1);
0463     /* 7854, b7,1, pdv2i=1 */
0464     REG_SET_BIT(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I);
0465     /* 7854, b8,1, pddacinterface=1 */
0466     REG_SET_BIT(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF);
0467     /* 7824,b12,0, offcal=0 */
0468     REG_CLR_BIT(ah, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL);
0469     /* 7838, b1,0, pwddb=0 */
0470     REG_CLR_BIT(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB);
0471     /* 7820,b11,0, enpacal=0 */
0472     REG_CLR_BIT(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL);
0473     /* 7820,b25,1, pdpadrv1=0 */
0474     REG_CLR_BIT(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1);
0475     /* 7820,b24,0, pdpadrv2=0 */
0476     REG_CLR_BIT(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV2);
0477     /* 7820,b23,0, pdpaout=0 */
0478     REG_CLR_BIT(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT);
0479     /* 783c,b14-16,7, padrvgn2tab_0=7 */
0480     REG_RMW_FIELD(ah, AR9285_AN_RF2G8, AR9285_AN_RF2G8_PADRVGN2TAB0, 7);
0481     /*
0482      * 7838,b29-31,0, padrvgn1tab_0=0
0483      * does not matter since we turn it off
0484      */
0485     REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PADRVGN2TAB0, 0);
0486     /* 7828, b0-11, ccom=fff */
0487     REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9271_AN_RF2G3_CCOMP, 0xfff);
0488     REG_RMW_BUFFER_FLUSH(ah);
0489 
0490     /* Set:
0491      * localmode=1,bmode=1,bmoderxtx=1,synthon=1,
0492      * txon=1,paon=1,oscon=1,synthon_force=1
0493      */
0494     REG_WRITE(ah, AR9285_AN_TOP2, 0xca0358a0);
0495     udelay(30);
0496     REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9271_AN_RF2G6_OFFS, 0);
0497 
0498     /* find off_6_1; */
0499     for (i = 6; i > 0; i--) {
0500         regVal = REG_READ(ah, AR9285_AN_RF2G6);
0501         regVal |= (1 << (20 + i));
0502         REG_WRITE(ah, AR9285_AN_RF2G6, regVal);
0503         udelay(1);
0504         /* regVal = REG_READ(ah, 0x7834); */
0505         regVal &= (~(0x1 << (20 + i)));
0506         regVal |= (MS(REG_READ(ah, AR9285_AN_RF2G9),
0507                   AR9285_AN_RXTXBB1_SPARE9)
0508                 << (20 + i));
0509         REG_WRITE(ah, AR9285_AN_RF2G6, regVal);
0510     }
0511 
0512     regVal = (regVal >> 20) & 0x7f;
0513 
0514     /* Update PA cal info */
0515     if ((!is_reset) && (ah->pacal_info.prev_offset == regVal)) {
0516         if (ah->pacal_info.max_skipcount < MAX_PACAL_SKIPCOUNT)
0517             ah->pacal_info.max_skipcount =
0518                 2 * ah->pacal_info.max_skipcount;
0519         ah->pacal_info.skipcount = ah->pacal_info.max_skipcount;
0520     } else {
0521         ah->pacal_info.max_skipcount = 1;
0522         ah->pacal_info.skipcount = 0;
0523         ah->pacal_info.prev_offset = regVal;
0524     }
0525 
0526 
0527     ENABLE_REG_RMW_BUFFER(ah);
0528     /* 7834, b1=1 */
0529     REG_SET_BIT(ah, AR9285_AN_RF2G6, 1 << 0);
0530     /* 9808, b27=0 */
0531     REG_CLR_BIT(ah, 0x9808, 1 << 27);
0532     REG_RMW_BUFFER_FLUSH(ah);
0533 
0534     ENABLE_REGWRITE_BUFFER(ah);
0535     for (i = 0; i < ARRAY_SIZE(regList); i++)
0536         REG_WRITE(ah, regList[i][0], regList[i][1]);
0537 
0538     REGWRITE_BUFFER_FLUSH(ah);
0539 }
0540 
0541 static inline void ar9285_hw_pa_cal(struct ath_hw *ah, bool is_reset)
0542 {
0543     struct ath_common *common = ath9k_hw_common(ah);
0544     u32 regVal;
0545     int i, offset, offs_6_1, offs_0;
0546     u32 ccomp_org, reg_field;
0547     u32 regList[][2] = {
0548         { 0x786c, 0 },
0549         { 0x7854, 0 },
0550         { 0x7820, 0 },
0551         { 0x7824, 0 },
0552         { 0x7868, 0 },
0553         { 0x783c, 0 },
0554         { 0x7838, 0 },
0555     };
0556 
0557     ath_dbg(common, CALIBRATE, "Running PA Calibration\n");
0558 
0559     /* PA CAL is not needed for high power solution */
0560     if (ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE) ==
0561         AR5416_EEP_TXGAIN_HIGH_POWER)
0562         return;
0563 
0564     for (i = 0; i < ARRAY_SIZE(regList); i++)
0565         regList[i][1] = REG_READ(ah, regList[i][0]);
0566 
0567     regVal = REG_READ(ah, 0x7834);
0568     regVal &= (~(0x1));
0569     REG_WRITE(ah, 0x7834, regVal);
0570     regVal = REG_READ(ah, 0x9808);
0571     regVal |= (0x1 << 27);
0572     REG_WRITE(ah, 0x9808, regVal);
0573 
0574     REG_RMW_FIELD(ah, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC, 1);
0575     REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1, 1);
0576     REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I, 1);
0577     REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF, 1);
0578     REG_RMW_FIELD(ah, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL, 0);
0579     REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB, 0);
0580     REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL, 0);
0581     REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1, 0);
0582     REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV2, 0);
0583     REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT, 0);
0584     REG_RMW_FIELD(ah, AR9285_AN_RF2G8, AR9285_AN_RF2G8_PADRVGN2TAB0, 7);
0585     REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PADRVGN2TAB0, 0);
0586     ccomp_org = MS(REG_READ(ah, AR9285_AN_RF2G6), AR9285_AN_RF2G6_CCOMP);
0587     REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, 0xf);
0588 
0589     REG_WRITE(ah, AR9285_AN_TOP2, 0xca0358a0);
0590     udelay(30);
0591     REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS, 0);
0592     REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, 0);
0593 
0594     for (i = 6; i > 0; i--) {
0595         regVal = REG_READ(ah, 0x7834);
0596         regVal |= (1 << (19 + i));
0597         REG_WRITE(ah, 0x7834, regVal);
0598         udelay(1);
0599         regVal = REG_READ(ah, 0x7834);
0600         regVal &= (~(0x1 << (19 + i)));
0601         reg_field = MS(REG_READ(ah, 0x7840), AR9285_AN_RXTXBB1_SPARE9);
0602         regVal |= (reg_field << (19 + i));
0603         REG_WRITE(ah, 0x7834, regVal);
0604     }
0605 
0606     REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, 1);
0607     udelay(1);
0608     reg_field = MS(REG_READ(ah, AR9285_AN_RF2G9), AR9285_AN_RXTXBB1_SPARE9);
0609     REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, reg_field);
0610     offs_6_1 = MS(REG_READ(ah, AR9285_AN_RF2G6), AR9285_AN_RF2G6_OFFS);
0611     offs_0   = MS(REG_READ(ah, AR9285_AN_RF2G3), AR9285_AN_RF2G3_PDVCCOMP);
0612 
0613     offset = (offs_6_1<<1) | offs_0;
0614     offset = offset - 0;
0615     offs_6_1 = offset>>1;
0616     offs_0 = offset & 1;
0617 
0618     if ((!is_reset) && (ah->pacal_info.prev_offset == offset)) {
0619         if (ah->pacal_info.max_skipcount < MAX_PACAL_SKIPCOUNT)
0620             ah->pacal_info.max_skipcount =
0621                 2 * ah->pacal_info.max_skipcount;
0622         ah->pacal_info.skipcount = ah->pacal_info.max_skipcount;
0623     } else {
0624         ah->pacal_info.max_skipcount = 1;
0625         ah->pacal_info.skipcount = 0;
0626         ah->pacal_info.prev_offset = offset;
0627     }
0628 
0629     REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS, offs_6_1);
0630     REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, offs_0);
0631 
0632     regVal = REG_READ(ah, 0x7834);
0633     regVal |= 0x1;
0634     REG_WRITE(ah, 0x7834, regVal);
0635     regVal = REG_READ(ah, 0x9808);
0636     regVal &= (~(0x1 << 27));
0637     REG_WRITE(ah, 0x9808, regVal);
0638 
0639     for (i = 0; i < ARRAY_SIZE(regList); i++)
0640         REG_WRITE(ah, regList[i][0], regList[i][1]);
0641 
0642     REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, ccomp_org);
0643 }
0644 
0645 static void ar9002_hw_pa_cal(struct ath_hw *ah, bool is_reset)
0646 {
0647     if (AR_SREV_9271(ah)) {
0648         if (is_reset || !ah->pacal_info.skipcount)
0649             ar9271_hw_pa_cal(ah, is_reset);
0650         else
0651             ah->pacal_info.skipcount--;
0652     } else if (AR_SREV_9285_12_OR_LATER(ah)) {
0653         if (is_reset || !ah->pacal_info.skipcount)
0654             ar9285_hw_pa_cal(ah, is_reset);
0655         else
0656             ah->pacal_info.skipcount--;
0657     }
0658 }
0659 
0660 static void ar9002_hw_olc_temp_compensation(struct ath_hw *ah)
0661 {
0662     if (OLC_FOR_AR9287_10_LATER)
0663         ar9287_hw_olc_temp_compensation(ah);
0664     else if (OLC_FOR_AR9280_20_LATER)
0665         ar9280_hw_olc_temp_compensation(ah);
0666 }
0667 
0668 static int ar9002_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan,
0669                    u8 rxchainmask, bool longcal)
0670 {
0671     struct ath9k_cal_list *currCal = ah->cal_list_curr;
0672     bool nfcal, nfcal_pending = false, percal_pending;
0673     int ret;
0674 
0675     nfcal = !!(REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF);
0676     if (ah->caldata) {
0677         nfcal_pending = test_bit(NFCAL_PENDING, &ah->caldata->cal_flags);
0678         if (longcal)        /* Remember to not miss */
0679             set_bit(LONGCAL_PENDING, &ah->caldata->cal_flags);
0680         else if (test_bit(LONGCAL_PENDING, &ah->caldata->cal_flags))
0681             longcal = true; /* Respin a previous one */
0682     }
0683 
0684     percal_pending = (currCal &&
0685               (currCal->calState == CAL_RUNNING ||
0686                currCal->calState == CAL_WAITING));
0687 
0688     if (percal_pending && !nfcal) {
0689         if (!ar9002_hw_per_calibration(ah, chan, rxchainmask, currCal))
0690             return 0;
0691 
0692         /* Looking for next waiting calibration if any */
0693         for (currCal = currCal->calNext; currCal != ah->cal_list_curr;
0694              currCal = currCal->calNext) {
0695             if (currCal->calState == CAL_WAITING)
0696                 break;
0697         }
0698         if (currCal->calState == CAL_WAITING) {
0699             percal_pending = true;
0700             ah->cal_list_curr = currCal;
0701         } else {
0702             percal_pending = false;
0703             ah->cal_list_curr = ah->cal_list;
0704         }
0705     }
0706 
0707     /* Do not start a next calibration if the longcal is in action */
0708     if (percal_pending && !nfcal && !longcal) {
0709         ath9k_hw_reset_calibration(ah, currCal);
0710 
0711         return 0;
0712     }
0713 
0714     /* Do NF cal only at longer intervals */
0715     if (longcal || nfcal_pending) {
0716         /*
0717          * Get the value from the previous NF cal and update
0718          * history buffer.
0719          */
0720         if (ath9k_hw_getnf(ah, chan)) {
0721             /*
0722              * Load the NF from history buffer of the current
0723              * channel.
0724              * NF is slow time-variant, so it is OK to use a
0725              * historical value.
0726              */
0727             ret = ath9k_hw_loadnf(ah, ah->curchan);
0728             if (ret < 0)
0729                 return ret;
0730         }
0731 
0732         if (longcal) {
0733             if (ah->caldata)
0734                 clear_bit(LONGCAL_PENDING,
0735                       &ah->caldata->cal_flags);
0736             ath9k_hw_start_nfcal(ah, false);
0737             /* Do periodic PAOffset Cal */
0738             ar9002_hw_pa_cal(ah, false);
0739             ar9002_hw_olc_temp_compensation(ah);
0740         }
0741     }
0742 
0743     return !percal_pending;
0744 }
0745 
0746 /* Carrier leakage Calibration fix */
0747 static bool ar9285_hw_cl_cal(struct ath_hw *ah, struct ath9k_channel *chan)
0748 {
0749     struct ath_common *common = ath9k_hw_common(ah);
0750 
0751     REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
0752     if (IS_CHAN_HT20(chan)) {
0753         REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE);
0754         REG_SET_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN);
0755         REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
0756                 AR_PHY_AGC_CONTROL_FLTR_CAL);
0757         REG_CLR_BIT(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE);
0758         REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL);
0759         if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL,
0760                   AR_PHY_AGC_CONTROL_CAL, 0, AH_WAIT_TIMEOUT)) {
0761             ath_dbg(common, CALIBRATE,
0762                 "offset calibration failed to complete in %d ms; noisy environment?\n",
0763                 AH_WAIT_TIMEOUT / 1000);
0764             return false;
0765         }
0766         REG_CLR_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN);
0767         REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE);
0768         REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
0769     }
0770     REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
0771     REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL);
0772     REG_SET_BIT(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE);
0773     REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL);
0774     if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL,
0775               0, AH_WAIT_TIMEOUT)) {
0776         ath_dbg(common, CALIBRATE,
0777             "offset calibration failed to complete in %d ms; noisy environment?\n",
0778             AH_WAIT_TIMEOUT / 1000);
0779         return false;
0780     }
0781 
0782     REG_SET_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
0783     REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
0784     REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL);
0785 
0786     return true;
0787 }
0788 
0789 static bool ar9285_hw_clc(struct ath_hw *ah, struct ath9k_channel *chan)
0790 {
0791     int i;
0792     u_int32_t txgain_max;
0793     u_int32_t clc_gain, gain_mask = 0, clc_num = 0;
0794     u_int32_t reg_clc_I0, reg_clc_Q0;
0795     u_int32_t i0_num = 0;
0796     u_int32_t q0_num = 0;
0797     u_int32_t total_num = 0;
0798     u_int32_t reg_rf2g5_org;
0799     bool retv = true;
0800 
0801     if (!(ar9285_hw_cl_cal(ah, chan)))
0802         return false;
0803 
0804     txgain_max = MS(REG_READ(ah, AR_PHY_TX_PWRCTRL7),
0805             AR_PHY_TX_PWRCTRL_TX_GAIN_TAB_MAX);
0806 
0807     for (i = 0; i < (txgain_max+1); i++) {
0808         clc_gain = (REG_READ(ah, (AR_PHY_TX_GAIN_TBL1+(i<<2))) &
0809                AR_PHY_TX_GAIN_CLC) >> AR_PHY_TX_GAIN_CLC_S;
0810         if (!(gain_mask & (1 << clc_gain))) {
0811             gain_mask |= (1 << clc_gain);
0812             clc_num++;
0813         }
0814     }
0815 
0816     for (i = 0; i < clc_num; i++) {
0817         reg_clc_I0 = (REG_READ(ah, (AR_PHY_CLC_TBL1 + (i << 2)))
0818                   & AR_PHY_CLC_I0) >> AR_PHY_CLC_I0_S;
0819         reg_clc_Q0 = (REG_READ(ah, (AR_PHY_CLC_TBL1 + (i << 2)))
0820                   & AR_PHY_CLC_Q0) >> AR_PHY_CLC_Q0_S;
0821         if (reg_clc_I0 == 0)
0822             i0_num++;
0823 
0824         if (reg_clc_Q0 == 0)
0825             q0_num++;
0826     }
0827     total_num = i0_num + q0_num;
0828     if (total_num > AR9285_CLCAL_REDO_THRESH) {
0829         reg_rf2g5_org = REG_READ(ah, AR9285_RF2G5);
0830         if (AR_SREV_9285E_20(ah)) {
0831             REG_WRITE(ah, AR9285_RF2G5,
0832                   (reg_rf2g5_org & AR9285_RF2G5_IC50TX) |
0833                   AR9285_RF2G5_IC50TX_XE_SET);
0834         } else {
0835             REG_WRITE(ah, AR9285_RF2G5,
0836                   (reg_rf2g5_org & AR9285_RF2G5_IC50TX) |
0837                   AR9285_RF2G5_IC50TX_SET);
0838         }
0839         retv = ar9285_hw_cl_cal(ah, chan);
0840         REG_WRITE(ah, AR9285_RF2G5, reg_rf2g5_org);
0841     }
0842     return retv;
0843 }
0844 
0845 static bool ar9002_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan)
0846 {
0847     struct ath_common *common = ath9k_hw_common(ah);
0848 
0849     if (AR_SREV_9271(ah)) {
0850         if (!ar9285_hw_cl_cal(ah, chan))
0851             return false;
0852     } else if (AR_SREV_9285(ah) && AR_SREV_9285_12_OR_LATER(ah)) {
0853         if (!ar9285_hw_clc(ah, chan))
0854             return false;
0855     } else {
0856         if (AR_SREV_9280_20_OR_LATER(ah)) {
0857             if (!AR_SREV_9287_11_OR_LATER(ah))
0858                 REG_CLR_BIT(ah, AR_PHY_ADC_CTL,
0859                         AR_PHY_ADC_CTL_OFF_PWDADC);
0860             REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
0861                     AR_PHY_AGC_CONTROL_FLTR_CAL);
0862         }
0863 
0864         /* Calibrate the AGC */
0865         REG_WRITE(ah, AR_PHY_AGC_CONTROL,
0866               REG_READ(ah, AR_PHY_AGC_CONTROL) |
0867               AR_PHY_AGC_CONTROL_CAL);
0868 
0869         /* Poll for offset calibration complete */
0870         if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL,
0871                    AR_PHY_AGC_CONTROL_CAL,
0872                    0, AH_WAIT_TIMEOUT)) {
0873             ath_dbg(common, CALIBRATE,
0874                 "offset calibration failed to complete in %d ms; noisy environment?\n",
0875                 AH_WAIT_TIMEOUT / 1000);
0876             return false;
0877         }
0878 
0879         if (AR_SREV_9280_20_OR_LATER(ah)) {
0880             if (!AR_SREV_9287_11_OR_LATER(ah))
0881                 REG_SET_BIT(ah, AR_PHY_ADC_CTL,
0882                         AR_PHY_ADC_CTL_OFF_PWDADC);
0883             REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
0884                     AR_PHY_AGC_CONTROL_FLTR_CAL);
0885         }
0886     }
0887 
0888     /* Do PA Calibration */
0889     ar9002_hw_pa_cal(ah, true);
0890     ath9k_hw_loadnf(ah, chan);
0891     ath9k_hw_start_nfcal(ah, true);
0892 
0893     ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL;
0894 
0895     /* Enable IQ, ADC Gain and ADC DC offset CALs */
0896     if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) {
0897         ah->supp_cals = IQ_MISMATCH_CAL;
0898 
0899         if (AR_SREV_9160_10_OR_LATER(ah))
0900             ah->supp_cals |= ADC_GAIN_CAL | ADC_DC_CAL;
0901 
0902         if (AR_SREV_9287(ah))
0903             ah->supp_cals &= ~ADC_GAIN_CAL;
0904 
0905         if (ar9002_hw_is_cal_supported(ah, chan, ADC_GAIN_CAL)) {
0906             INIT_CAL(&ah->adcgain_caldata);
0907             INSERT_CAL(ah, &ah->adcgain_caldata);
0908             ath_dbg(common, CALIBRATE,
0909                     "enabling ADC Gain Calibration\n");
0910         }
0911 
0912         if (ar9002_hw_is_cal_supported(ah, chan, ADC_DC_CAL)) {
0913             INIT_CAL(&ah->adcdc_caldata);
0914             INSERT_CAL(ah, &ah->adcdc_caldata);
0915             ath_dbg(common, CALIBRATE,
0916                     "enabling ADC DC Calibration\n");
0917         }
0918 
0919         if (ar9002_hw_is_cal_supported(ah, chan, IQ_MISMATCH_CAL)) {
0920             INIT_CAL(&ah->iq_caldata);
0921             INSERT_CAL(ah, &ah->iq_caldata);
0922             ath_dbg(common, CALIBRATE, "enabling IQ Calibration\n");
0923         }
0924 
0925         ah->cal_list_curr = ah->cal_list;
0926 
0927         if (ah->cal_list_curr)
0928             ath9k_hw_reset_calibration(ah, ah->cal_list_curr);
0929     }
0930 
0931     if (ah->caldata)
0932         ah->caldata->CalValid = 0;
0933 
0934     return true;
0935 }
0936 
0937 static const struct ath9k_percal_data iq_cal_multi_sample = {
0938     IQ_MISMATCH_CAL,
0939     MAX_CAL_SAMPLES,
0940     PER_MIN_LOG_COUNT,
0941     ar9002_hw_iqcal_collect,
0942     ar9002_hw_iqcalibrate
0943 };
0944 static const struct ath9k_percal_data iq_cal_single_sample = {
0945     IQ_MISMATCH_CAL,
0946     MIN_CAL_SAMPLES,
0947     PER_MAX_LOG_COUNT,
0948     ar9002_hw_iqcal_collect,
0949     ar9002_hw_iqcalibrate
0950 };
0951 static const struct ath9k_percal_data adc_gain_cal_multi_sample = {
0952     ADC_GAIN_CAL,
0953     MAX_CAL_SAMPLES,
0954     PER_MIN_LOG_COUNT,
0955     ar9002_hw_adc_gaincal_collect,
0956     ar9002_hw_adc_gaincal_calibrate
0957 };
0958 static const struct ath9k_percal_data adc_gain_cal_single_sample = {
0959     ADC_GAIN_CAL,
0960     MIN_CAL_SAMPLES,
0961     PER_MAX_LOG_COUNT,
0962     ar9002_hw_adc_gaincal_collect,
0963     ar9002_hw_adc_gaincal_calibrate
0964 };
0965 static const struct ath9k_percal_data adc_dc_cal_multi_sample = {
0966     ADC_DC_CAL,
0967     MAX_CAL_SAMPLES,
0968     PER_MIN_LOG_COUNT,
0969     ar9002_hw_adc_dccal_collect,
0970     ar9002_hw_adc_dccal_calibrate
0971 };
0972 static const struct ath9k_percal_data adc_dc_cal_single_sample = {
0973     ADC_DC_CAL,
0974     MIN_CAL_SAMPLES,
0975     PER_MAX_LOG_COUNT,
0976     ar9002_hw_adc_dccal_collect,
0977     ar9002_hw_adc_dccal_calibrate
0978 };
0979 
0980 static void ar9002_hw_init_cal_settings(struct ath_hw *ah)
0981 {
0982     if (AR_SREV_9100(ah)) {
0983         ah->iq_caldata.calData = &iq_cal_multi_sample;
0984         ah->supp_cals = IQ_MISMATCH_CAL;
0985         return;
0986     }
0987 
0988     if (AR_SREV_9160_10_OR_LATER(ah)) {
0989         if (AR_SREV_9280_20_OR_LATER(ah)) {
0990             ah->iq_caldata.calData = &iq_cal_single_sample;
0991             ah->adcgain_caldata.calData =
0992                 &adc_gain_cal_single_sample;
0993             ah->adcdc_caldata.calData =
0994                 &adc_dc_cal_single_sample;
0995         } else {
0996             ah->iq_caldata.calData = &iq_cal_multi_sample;
0997             ah->adcgain_caldata.calData =
0998                 &adc_gain_cal_multi_sample;
0999             ah->adcdc_caldata.calData =
1000                 &adc_dc_cal_multi_sample;
1001         }
1002         ah->supp_cals = ADC_GAIN_CAL | ADC_DC_CAL | IQ_MISMATCH_CAL;
1003 
1004         if (AR_SREV_9287(ah))
1005             ah->supp_cals &= ~ADC_GAIN_CAL;
1006     }
1007 }
1008 
1009 void ar9002_hw_attach_calib_ops(struct ath_hw *ah)
1010 {
1011     struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
1012     struct ath_hw_ops *ops = ath9k_hw_ops(ah);
1013 
1014     priv_ops->init_cal_settings = ar9002_hw_init_cal_settings;
1015     priv_ops->init_cal = ar9002_hw_init_cal;
1016     priv_ops->setup_calibration = ar9002_hw_setup_calibration;
1017 
1018     ops->calibrate = ar9002_hw_calibrate;
1019 }