Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright (c) 2010-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 "ar9003_phy.h"
0020 #include "ar9003_rtt.h"
0021 #include "ar9003_mci.h"
0022 
0023 #define MAX_MEASUREMENT MAX_IQCAL_MEASUREMENT
0024 #define MAX_MAG_DELTA   11
0025 #define MAX_PHS_DELTA   10
0026 #define MAXIQCAL        3
0027 
0028 struct coeff {
0029     int mag_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT][MAXIQCAL];
0030     int phs_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT][MAXIQCAL];
0031     int iqc_coeff[2];
0032 };
0033 
0034 enum ar9003_cal_types {
0035     IQ_MISMATCH_CAL = BIT(0),
0036 };
0037 
0038 static void ar9003_hw_setup_calibration(struct ath_hw *ah,
0039                     struct ath9k_cal_list *currCal)
0040 {
0041     struct ath_common *common = ath9k_hw_common(ah);
0042 
0043     /* Select calibration to run */
0044     switch (currCal->calData->calType) {
0045     case IQ_MISMATCH_CAL:
0046         /*
0047          * Start calibration with
0048          * 2^(INIT_IQCAL_LOG_COUNT_MAX+1) samples
0049          */
0050         REG_RMW_FIELD(ah, AR_PHY_TIMING4,
0051                   AR_PHY_TIMING4_IQCAL_LOG_COUNT_MAX,
0052                   currCal->calData->calCountMax);
0053         REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ);
0054 
0055         ath_dbg(common, CALIBRATE,
0056             "starting IQ Mismatch Calibration\n");
0057 
0058         /* Kick-off cal */
0059         REG_SET_BIT(ah, AR_PHY_TIMING4, AR_PHY_TIMING4_DO_CAL);
0060         break;
0061     default:
0062         ath_err(common, "Invalid calibration type\n");
0063         break;
0064     }
0065 }
0066 
0067 /*
0068  * Generic calibration routine.
0069  * Recalibrate the lower PHY chips to account for temperature/environment
0070  * changes.
0071  */
0072 static bool ar9003_hw_per_calibration(struct ath_hw *ah,
0073                       struct ath9k_channel *ichan,
0074                       u8 rxchainmask,
0075                       struct ath9k_cal_list *currCal)
0076 {
0077     struct ath9k_hw_cal_data *caldata = ah->caldata;
0078     const struct ath9k_percal_data *cur_caldata = currCal->calData;
0079 
0080     /* Calibration in progress. */
0081     if (currCal->calState == CAL_RUNNING) {
0082         /* Check to see if it has finished. */
0083         if (REG_READ(ah, AR_PHY_TIMING4) & AR_PHY_TIMING4_DO_CAL)
0084             return false;
0085 
0086         /*
0087         * Accumulate cal measures for active chains
0088         */
0089         cur_caldata->calCollect(ah);
0090         ah->cal_samples++;
0091 
0092         if (ah->cal_samples >= cur_caldata->calNumSamples) {
0093             unsigned int i, numChains = 0;
0094             for (i = 0; i < AR9300_MAX_CHAINS; i++) {
0095                 if (rxchainmask & (1 << i))
0096                     numChains++;
0097             }
0098 
0099             /*
0100             * Process accumulated data
0101             */
0102             cur_caldata->calPostProc(ah, numChains);
0103 
0104             /* Calibration has finished. */
0105             caldata->CalValid |= cur_caldata->calType;
0106             currCal->calState = CAL_DONE;
0107             return true;
0108         } else {
0109             /*
0110              * Set-up collection of another sub-sample until we
0111              * get desired number
0112              */
0113             ar9003_hw_setup_calibration(ah, currCal);
0114         }
0115     } else if (!(caldata->CalValid & cur_caldata->calType)) {
0116         /* If current cal is marked invalid in channel, kick it off */
0117         ath9k_hw_reset_calibration(ah, currCal);
0118     }
0119 
0120     return false;
0121 }
0122 
0123 static int ar9003_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan,
0124                    u8 rxchainmask, bool longcal)
0125 {
0126     bool iscaldone = true;
0127     struct ath9k_cal_list *currCal = ah->cal_list_curr;
0128     int ret;
0129 
0130     /*
0131      * For given calibration:
0132      * 1. Call generic cal routine
0133      * 2. When this cal is done (isCalDone) if we have more cals waiting
0134      *    (eg after reset), mask this to upper layers by not propagating
0135      *    isCalDone if it is set to TRUE.
0136      *    Instead, change isCalDone to FALSE and setup the waiting cal(s)
0137      *    to be run.
0138      */
0139     if (currCal &&
0140         (currCal->calState == CAL_RUNNING ||
0141          currCal->calState == CAL_WAITING)) {
0142         iscaldone = ar9003_hw_per_calibration(ah, chan,
0143                               rxchainmask, currCal);
0144         if (iscaldone) {
0145             ah->cal_list_curr = currCal = currCal->calNext;
0146 
0147             if (currCal->calState == CAL_WAITING) {
0148                 iscaldone = false;
0149                 ath9k_hw_reset_calibration(ah, currCal);
0150             }
0151         }
0152     }
0153 
0154     /*
0155      * Do NF cal only at longer intervals. Get the value from
0156      * the previous NF cal and update history buffer.
0157      */
0158     if (longcal && ath9k_hw_getnf(ah, chan)) {
0159         /*
0160          * Load the NF from history buffer of the current channel.
0161          * NF is slow time-variant, so it is OK to use a historical
0162          * value.
0163          */
0164         ret = ath9k_hw_loadnf(ah, ah->curchan);
0165         if (ret < 0)
0166             return ret;
0167 
0168         /* start NF calibration, without updating BB NF register */
0169         ath9k_hw_start_nfcal(ah, false);
0170     }
0171 
0172     return iscaldone;
0173 }
0174 
0175 static void ar9003_hw_iqcal_collect(struct ath_hw *ah)
0176 {
0177     int i;
0178 
0179     /* Accumulate IQ cal measures for active chains */
0180     for (i = 0; i < AR9300_MAX_CHAINS; i++) {
0181         if (ah->txchainmask & BIT(i)) {
0182             ah->totalPowerMeasI[i] +=
0183                 REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
0184             ah->totalPowerMeasQ[i] +=
0185                 REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
0186             ah->totalIqCorrMeas[i] +=
0187                 (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
0188             ath_dbg(ath9k_hw_common(ah), CALIBRATE,
0189                 "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n",
0190                 ah->cal_samples, i, ah->totalPowerMeasI[i],
0191                 ah->totalPowerMeasQ[i],
0192                 ah->totalIqCorrMeas[i]);
0193         }
0194     }
0195 }
0196 
0197 static void ar9003_hw_iqcalibrate(struct ath_hw *ah, u8 numChains)
0198 {
0199     struct ath_common *common = ath9k_hw_common(ah);
0200     u32 powerMeasQ, powerMeasI, iqCorrMeas;
0201     u32 qCoffDenom, iCoffDenom;
0202     int32_t qCoff, iCoff;
0203     int iqCorrNeg, i;
0204     static const u_int32_t offset_array[3] = {
0205         AR_PHY_RX_IQCAL_CORR_B0,
0206         AR_PHY_RX_IQCAL_CORR_B1,
0207         AR_PHY_RX_IQCAL_CORR_B2,
0208     };
0209 
0210     for (i = 0; i < numChains; i++) {
0211         powerMeasI = ah->totalPowerMeasI[i];
0212         powerMeasQ = ah->totalPowerMeasQ[i];
0213         iqCorrMeas = ah->totalIqCorrMeas[i];
0214 
0215         ath_dbg(common, CALIBRATE,
0216             "Starting IQ Cal and Correction for Chain %d\n", i);
0217 
0218         ath_dbg(common, CALIBRATE,
0219             "Original: Chn %d iq_corr_meas = 0x%08x\n",
0220             i, ah->totalIqCorrMeas[i]);
0221 
0222         iqCorrNeg = 0;
0223 
0224         if (iqCorrMeas > 0x80000000) {
0225             iqCorrMeas = (0xffffffff - iqCorrMeas) + 1;
0226             iqCorrNeg = 1;
0227         }
0228 
0229         ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_i = 0x%08x\n",
0230             i, powerMeasI);
0231         ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_q = 0x%08x\n",
0232             i, powerMeasQ);
0233         ath_dbg(common, CALIBRATE, "iqCorrNeg is 0x%08x\n", iqCorrNeg);
0234 
0235         iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 256;
0236         qCoffDenom = powerMeasQ / 64;
0237 
0238         if ((iCoffDenom != 0) && (qCoffDenom != 0)) {
0239             iCoff = iqCorrMeas / iCoffDenom;
0240             qCoff = powerMeasI / qCoffDenom - 64;
0241             ath_dbg(common, CALIBRATE, "Chn %d iCoff = 0x%08x\n",
0242                 i, iCoff);
0243             ath_dbg(common, CALIBRATE, "Chn %d qCoff = 0x%08x\n",
0244                 i, qCoff);
0245 
0246             /* Force bounds on iCoff */
0247             if (iCoff >= 63)
0248                 iCoff = 63;
0249             else if (iCoff <= -63)
0250                 iCoff = -63;
0251 
0252             /* Negate iCoff if iqCorrNeg == 0 */
0253             if (iqCorrNeg == 0x0)
0254                 iCoff = -iCoff;
0255 
0256             /* Force bounds on qCoff */
0257             if (qCoff >= 63)
0258                 qCoff = 63;
0259             else if (qCoff <= -63)
0260                 qCoff = -63;
0261 
0262             iCoff = iCoff & 0x7f;
0263             qCoff = qCoff & 0x7f;
0264 
0265             ath_dbg(common, CALIBRATE,
0266                 "Chn %d : iCoff = 0x%x  qCoff = 0x%x\n",
0267                 i, iCoff, qCoff);
0268             ath_dbg(common, CALIBRATE,
0269                 "Register offset (0x%04x) before update = 0x%x\n",
0270                 offset_array[i],
0271                 REG_READ(ah, offset_array[i]));
0272 
0273             if (AR_SREV_9565(ah) &&
0274                 (iCoff == 63 || qCoff == 63 ||
0275                  iCoff == -63 || qCoff == -63))
0276                 return;
0277 
0278             REG_RMW_FIELD(ah, offset_array[i],
0279                       AR_PHY_RX_IQCAL_CORR_IQCORR_Q_I_COFF,
0280                       iCoff);
0281             REG_RMW_FIELD(ah, offset_array[i],
0282                       AR_PHY_RX_IQCAL_CORR_IQCORR_Q_Q_COFF,
0283                       qCoff);
0284             ath_dbg(common, CALIBRATE,
0285                 "Register offset (0x%04x) QI COFF (bitfields 0x%08x) after update = 0x%x\n",
0286                 offset_array[i],
0287                 AR_PHY_RX_IQCAL_CORR_IQCORR_Q_I_COFF,
0288                 REG_READ(ah, offset_array[i]));
0289             ath_dbg(common, CALIBRATE,
0290                 "Register offset (0x%04x) QQ COFF (bitfields 0x%08x) after update = 0x%x\n",
0291                 offset_array[i],
0292                 AR_PHY_RX_IQCAL_CORR_IQCORR_Q_Q_COFF,
0293                 REG_READ(ah, offset_array[i]));
0294 
0295             ath_dbg(common, CALIBRATE,
0296                 "IQ Cal and Correction done for Chain %d\n", i);
0297         }
0298     }
0299 
0300     REG_SET_BIT(ah, AR_PHY_RX_IQCAL_CORR_B0,
0301             AR_PHY_RX_IQCAL_CORR_IQCORR_ENABLE);
0302     ath_dbg(common, CALIBRATE,
0303         "IQ Cal and Correction (offset 0x%04x) enabled (bit position 0x%08x). New Value 0x%08x\n",
0304         (unsigned) (AR_PHY_RX_IQCAL_CORR_B0),
0305         AR_PHY_RX_IQCAL_CORR_IQCORR_ENABLE,
0306         REG_READ(ah, AR_PHY_RX_IQCAL_CORR_B0));
0307 }
0308 
0309 static const struct ath9k_percal_data iq_cal_single_sample = {
0310     IQ_MISMATCH_CAL,
0311     MIN_CAL_SAMPLES,
0312     PER_MAX_LOG_COUNT,
0313     ar9003_hw_iqcal_collect,
0314     ar9003_hw_iqcalibrate
0315 };
0316 
0317 static void ar9003_hw_init_cal_settings(struct ath_hw *ah)
0318 {
0319     ah->iq_caldata.calData = &iq_cal_single_sample;
0320 
0321     if (AR_SREV_9300_20_OR_LATER(ah)) {
0322         ah->enabled_cals |= TX_IQ_CAL;
0323         if (AR_SREV_9485_OR_LATER(ah) && !AR_SREV_9340(ah))
0324             ah->enabled_cals |= TX_IQ_ON_AGC_CAL;
0325     }
0326 
0327     ah->supp_cals = IQ_MISMATCH_CAL;
0328 }
0329 
0330 #define OFF_UPPER_LT 24
0331 #define OFF_LOWER_LT 7
0332 
0333 static bool ar9003_hw_dynamic_osdac_selection(struct ath_hw *ah,
0334                           bool txiqcal_done)
0335 {
0336     struct ath_common *common = ath9k_hw_common(ah);
0337     int ch0_done, osdac_ch0, dc_off_ch0_i1, dc_off_ch0_q1, dc_off_ch0_i2,
0338         dc_off_ch0_q2, dc_off_ch0_i3, dc_off_ch0_q3;
0339     int ch1_done, osdac_ch1, dc_off_ch1_i1, dc_off_ch1_q1, dc_off_ch1_i2,
0340         dc_off_ch1_q2, dc_off_ch1_i3, dc_off_ch1_q3;
0341     int ch2_done, osdac_ch2, dc_off_ch2_i1, dc_off_ch2_q1, dc_off_ch2_i2,
0342         dc_off_ch2_q2, dc_off_ch2_i3, dc_off_ch2_q3;
0343     bool status;
0344     u32 temp, val;
0345 
0346     /*
0347      * Clear offset and IQ calibration, run AGC cal.
0348      */
0349     REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
0350             AR_PHY_AGC_CONTROL_OFFSET_CAL);
0351     REG_CLR_BIT(ah, AR_PHY_TX_IQCAL_CONTROL_0,
0352             AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL);
0353     REG_WRITE(ah, AR_PHY_AGC_CONTROL,
0354           REG_READ(ah, AR_PHY_AGC_CONTROL) | AR_PHY_AGC_CONTROL_CAL);
0355 
0356     status = ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL,
0357                    AR_PHY_AGC_CONTROL_CAL,
0358                    0, AH_WAIT_TIMEOUT);
0359     if (!status) {
0360         ath_dbg(common, CALIBRATE,
0361             "AGC cal without offset cal failed to complete in 1ms");
0362         return false;
0363     }
0364 
0365     /*
0366      * Allow only offset calibration and disable the others
0367      * (Carrier Leak calibration, TX Filter calibration and
0368      *  Peak Detector offset calibration).
0369      */
0370     REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
0371             AR_PHY_AGC_CONTROL_OFFSET_CAL);
0372     REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL,
0373             AR_PHY_CL_CAL_ENABLE);
0374     REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
0375             AR_PHY_AGC_CONTROL_FLTR_CAL);
0376     REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
0377             AR_PHY_AGC_CONTROL_PKDET_CAL);
0378 
0379     ch0_done = 0;
0380     ch1_done = 0;
0381     ch2_done = 0;
0382 
0383     while ((ch0_done == 0) || (ch1_done == 0) || (ch2_done == 0)) {
0384         osdac_ch0 = (REG_READ(ah, AR_PHY_65NM_CH0_BB1) >> 30) & 0x3;
0385         osdac_ch1 = (REG_READ(ah, AR_PHY_65NM_CH1_BB1) >> 30) & 0x3;
0386         osdac_ch2 = (REG_READ(ah, AR_PHY_65NM_CH2_BB1) >> 30) & 0x3;
0387 
0388         REG_SET_BIT(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
0389 
0390         REG_WRITE(ah, AR_PHY_AGC_CONTROL,
0391               REG_READ(ah, AR_PHY_AGC_CONTROL) | AR_PHY_AGC_CONTROL_CAL);
0392 
0393         status = ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL,
0394                        AR_PHY_AGC_CONTROL_CAL,
0395                        0, AH_WAIT_TIMEOUT);
0396         if (!status) {
0397             ath_dbg(common, CALIBRATE,
0398                 "DC offset cal failed to complete in 1ms");
0399             return false;
0400         }
0401 
0402         REG_CLR_BIT(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
0403 
0404         /*
0405          * High gain.
0406          */
0407         REG_WRITE(ah, AR_PHY_65NM_CH0_BB3,
0408               ((REG_READ(ah, AR_PHY_65NM_CH0_BB3) & 0xfffffcff) | (1 << 8)));
0409         REG_WRITE(ah, AR_PHY_65NM_CH1_BB3,
0410               ((REG_READ(ah, AR_PHY_65NM_CH1_BB3) & 0xfffffcff) | (1 << 8)));
0411         REG_WRITE(ah, AR_PHY_65NM_CH2_BB3,
0412               ((REG_READ(ah, AR_PHY_65NM_CH2_BB3) & 0xfffffcff) | (1 << 8)));
0413 
0414         temp = REG_READ(ah, AR_PHY_65NM_CH0_BB3);
0415         dc_off_ch0_i1 = (temp >> 26) & 0x1f;
0416         dc_off_ch0_q1 = (temp >> 21) & 0x1f;
0417 
0418         temp = REG_READ(ah, AR_PHY_65NM_CH1_BB3);
0419         dc_off_ch1_i1 = (temp >> 26) & 0x1f;
0420         dc_off_ch1_q1 = (temp >> 21) & 0x1f;
0421 
0422         temp = REG_READ(ah, AR_PHY_65NM_CH2_BB3);
0423         dc_off_ch2_i1 = (temp >> 26) & 0x1f;
0424         dc_off_ch2_q1 = (temp >> 21) & 0x1f;
0425 
0426         /*
0427          * Low gain.
0428          */
0429         REG_WRITE(ah, AR_PHY_65NM_CH0_BB3,
0430               ((REG_READ(ah, AR_PHY_65NM_CH0_BB3) & 0xfffffcff) | (2 << 8)));
0431         REG_WRITE(ah, AR_PHY_65NM_CH1_BB3,
0432               ((REG_READ(ah, AR_PHY_65NM_CH1_BB3) & 0xfffffcff) | (2 << 8)));
0433         REG_WRITE(ah, AR_PHY_65NM_CH2_BB3,
0434               ((REG_READ(ah, AR_PHY_65NM_CH2_BB3) & 0xfffffcff) | (2 << 8)));
0435 
0436         temp = REG_READ(ah, AR_PHY_65NM_CH0_BB3);
0437         dc_off_ch0_i2 = (temp >> 26) & 0x1f;
0438         dc_off_ch0_q2 = (temp >> 21) & 0x1f;
0439 
0440         temp = REG_READ(ah, AR_PHY_65NM_CH1_BB3);
0441         dc_off_ch1_i2 = (temp >> 26) & 0x1f;
0442         dc_off_ch1_q2 = (temp >> 21) & 0x1f;
0443 
0444         temp = REG_READ(ah, AR_PHY_65NM_CH2_BB3);
0445         dc_off_ch2_i2 = (temp >> 26) & 0x1f;
0446         dc_off_ch2_q2 = (temp >> 21) & 0x1f;
0447 
0448         /*
0449          * Loopback.
0450          */
0451         REG_WRITE(ah, AR_PHY_65NM_CH0_BB3,
0452               ((REG_READ(ah, AR_PHY_65NM_CH0_BB3) & 0xfffffcff) | (3 << 8)));
0453         REG_WRITE(ah, AR_PHY_65NM_CH1_BB3,
0454               ((REG_READ(ah, AR_PHY_65NM_CH1_BB3) & 0xfffffcff) | (3 << 8)));
0455         REG_WRITE(ah, AR_PHY_65NM_CH2_BB3,
0456               ((REG_READ(ah, AR_PHY_65NM_CH2_BB3) & 0xfffffcff) | (3 << 8)));
0457 
0458         temp = REG_READ(ah, AR_PHY_65NM_CH0_BB3);
0459         dc_off_ch0_i3 = (temp >> 26) & 0x1f;
0460         dc_off_ch0_q3 = (temp >> 21) & 0x1f;
0461 
0462         temp = REG_READ(ah, AR_PHY_65NM_CH1_BB3);
0463         dc_off_ch1_i3 = (temp >> 26) & 0x1f;
0464         dc_off_ch1_q3 = (temp >> 21) & 0x1f;
0465 
0466         temp = REG_READ(ah, AR_PHY_65NM_CH2_BB3);
0467         dc_off_ch2_i3 = (temp >> 26) & 0x1f;
0468         dc_off_ch2_q3 = (temp >> 21) & 0x1f;
0469 
0470         if ((dc_off_ch0_i1 > OFF_UPPER_LT) || (dc_off_ch0_i1 < OFF_LOWER_LT) ||
0471             (dc_off_ch0_i2 > OFF_UPPER_LT) || (dc_off_ch0_i2 < OFF_LOWER_LT) ||
0472             (dc_off_ch0_i3 > OFF_UPPER_LT) || (dc_off_ch0_i3 < OFF_LOWER_LT) ||
0473             (dc_off_ch0_q1 > OFF_UPPER_LT) || (dc_off_ch0_q1 < OFF_LOWER_LT) ||
0474             (dc_off_ch0_q2 > OFF_UPPER_LT) || (dc_off_ch0_q2 < OFF_LOWER_LT) ||
0475             (dc_off_ch0_q3 > OFF_UPPER_LT) || (dc_off_ch0_q3 < OFF_LOWER_LT)) {
0476             if (osdac_ch0 == 3) {
0477                 ch0_done = 1;
0478             } else {
0479                 osdac_ch0++;
0480 
0481                 val = REG_READ(ah, AR_PHY_65NM_CH0_BB1) & 0x3fffffff;
0482                 val |= (osdac_ch0 << 30);
0483                 REG_WRITE(ah, AR_PHY_65NM_CH0_BB1, val);
0484 
0485                 ch0_done = 0;
0486             }
0487         } else {
0488             ch0_done = 1;
0489         }
0490 
0491         if ((dc_off_ch1_i1 > OFF_UPPER_LT) || (dc_off_ch1_i1 < OFF_LOWER_LT) ||
0492             (dc_off_ch1_i2 > OFF_UPPER_LT) || (dc_off_ch1_i2 < OFF_LOWER_LT) ||
0493             (dc_off_ch1_i3 > OFF_UPPER_LT) || (dc_off_ch1_i3 < OFF_LOWER_LT) ||
0494             (dc_off_ch1_q1 > OFF_UPPER_LT) || (dc_off_ch1_q1 < OFF_LOWER_LT) ||
0495             (dc_off_ch1_q2 > OFF_UPPER_LT) || (dc_off_ch1_q2 < OFF_LOWER_LT) ||
0496             (dc_off_ch1_q3 > OFF_UPPER_LT) || (dc_off_ch1_q3 < OFF_LOWER_LT)) {
0497             if (osdac_ch1 == 3) {
0498                 ch1_done = 1;
0499             } else {
0500                 osdac_ch1++;
0501 
0502                 val = REG_READ(ah, AR_PHY_65NM_CH1_BB1) & 0x3fffffff;
0503                 val |= (osdac_ch1 << 30);
0504                 REG_WRITE(ah, AR_PHY_65NM_CH1_BB1, val);
0505 
0506                 ch1_done = 0;
0507             }
0508         } else {
0509             ch1_done = 1;
0510         }
0511 
0512         if ((dc_off_ch2_i1 > OFF_UPPER_LT) || (dc_off_ch2_i1 < OFF_LOWER_LT) ||
0513             (dc_off_ch2_i2 > OFF_UPPER_LT) || (dc_off_ch2_i2 < OFF_LOWER_LT) ||
0514             (dc_off_ch2_i3 > OFF_UPPER_LT) || (dc_off_ch2_i3 < OFF_LOWER_LT) ||
0515             (dc_off_ch2_q1 > OFF_UPPER_LT) || (dc_off_ch2_q1 < OFF_LOWER_LT) ||
0516             (dc_off_ch2_q2 > OFF_UPPER_LT) || (dc_off_ch2_q2 < OFF_LOWER_LT) ||
0517             (dc_off_ch2_q3 > OFF_UPPER_LT) || (dc_off_ch2_q3 < OFF_LOWER_LT)) {
0518             if (osdac_ch2 == 3) {
0519                 ch2_done = 1;
0520             } else {
0521                 osdac_ch2++;
0522 
0523                 val = REG_READ(ah, AR_PHY_65NM_CH2_BB1) & 0x3fffffff;
0524                 val |= (osdac_ch2 << 30);
0525                 REG_WRITE(ah, AR_PHY_65NM_CH2_BB1, val);
0526 
0527                 ch2_done = 0;
0528             }
0529         } else {
0530             ch2_done = 1;
0531         }
0532     }
0533 
0534     REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
0535             AR_PHY_AGC_CONTROL_OFFSET_CAL);
0536     REG_SET_BIT(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
0537 
0538     /*
0539      * We don't need to check txiqcal_done here since it is always
0540      * set for AR9550.
0541      */
0542     REG_SET_BIT(ah, AR_PHY_TX_IQCAL_CONTROL_0,
0543             AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL);
0544 
0545     return true;
0546 }
0547 
0548 /*
0549  * solve 4x4 linear equation used in loopback iq cal.
0550  */
0551 static bool ar9003_hw_solve_iq_cal(struct ath_hw *ah,
0552                    s32 sin_2phi_1,
0553                    s32 cos_2phi_1,
0554                    s32 sin_2phi_2,
0555                    s32 cos_2phi_2,
0556                    s32 mag_a0_d0,
0557                    s32 phs_a0_d0,
0558                    s32 mag_a1_d0,
0559                    s32 phs_a1_d0,
0560                    s32 solved_eq[])
0561 {
0562     s32 f1 = cos_2phi_1 - cos_2phi_2,
0563         f3 = sin_2phi_1 - sin_2phi_2,
0564         f2;
0565     s32 mag_tx, phs_tx, mag_rx, phs_rx;
0566     const s32 result_shift = 1 << 15;
0567     struct ath_common *common = ath9k_hw_common(ah);
0568 
0569     f2 = ((f1 >> 3) * (f1 >> 3) + (f3 >> 3) * (f3 >> 3)) >> 9;
0570 
0571     if (!f2) {
0572         ath_dbg(common, CALIBRATE, "Divide by 0\n");
0573         return false;
0574     }
0575 
0576     /* mag mismatch, tx */
0577     mag_tx = f1 * (mag_a0_d0  - mag_a1_d0) + f3 * (phs_a0_d0 - phs_a1_d0);
0578     /* phs mismatch, tx */
0579     phs_tx = f3 * (-mag_a0_d0 + mag_a1_d0) + f1 * (phs_a0_d0 - phs_a1_d0);
0580 
0581     mag_tx = (mag_tx / f2);
0582     phs_tx = (phs_tx / f2);
0583 
0584     /* mag mismatch, rx */
0585     mag_rx = mag_a0_d0 - (cos_2phi_1 * mag_tx + sin_2phi_1 * phs_tx) /
0586          result_shift;
0587     /* phs mismatch, rx */
0588     phs_rx = phs_a0_d0 + (sin_2phi_1 * mag_tx - cos_2phi_1 * phs_tx) /
0589          result_shift;
0590 
0591     solved_eq[0] = mag_tx;
0592     solved_eq[1] = phs_tx;
0593     solved_eq[2] = mag_rx;
0594     solved_eq[3] = phs_rx;
0595 
0596     return true;
0597 }
0598 
0599 static s32 ar9003_hw_find_mag_approx(struct ath_hw *ah, s32 in_re, s32 in_im)
0600 {
0601     s32 abs_i = abs(in_re),
0602         abs_q = abs(in_im),
0603         max_abs, min_abs;
0604 
0605     if (abs_i > abs_q) {
0606         max_abs = abs_i;
0607         min_abs = abs_q;
0608     } else {
0609         max_abs = abs_q;
0610         min_abs = abs_i;
0611     }
0612 
0613     return max_abs - (max_abs / 32) + (min_abs / 8) + (min_abs / 4);
0614 }
0615 
0616 #define DELPT 32
0617 
0618 static bool ar9003_hw_calc_iq_corr(struct ath_hw *ah,
0619                    s32 chain_idx,
0620                    const s32 iq_res[],
0621                    s32 iqc_coeff[])
0622 {
0623     s32 i2_m_q2_a0_d0, i2_p_q2_a0_d0, iq_corr_a0_d0,
0624         i2_m_q2_a0_d1, i2_p_q2_a0_d1, iq_corr_a0_d1,
0625         i2_m_q2_a1_d0, i2_p_q2_a1_d0, iq_corr_a1_d0,
0626         i2_m_q2_a1_d1, i2_p_q2_a1_d1, iq_corr_a1_d1;
0627     s32 mag_a0_d0, mag_a1_d0, mag_a0_d1, mag_a1_d1,
0628         phs_a0_d0, phs_a1_d0, phs_a0_d1, phs_a1_d1,
0629         sin_2phi_1, cos_2phi_1,
0630         sin_2phi_2, cos_2phi_2;
0631     s32 mag_tx, phs_tx, mag_rx, phs_rx;
0632     s32 solved_eq[4], mag_corr_tx, phs_corr_tx, mag_corr_rx, phs_corr_rx,
0633         q_q_coff, q_i_coff;
0634     const s32 res_scale = 1 << 15;
0635     const s32 delpt_shift = 1 << 8;
0636     s32 mag1, mag2;
0637     struct ath_common *common = ath9k_hw_common(ah);
0638 
0639     i2_m_q2_a0_d0 = iq_res[0] & 0xfff;
0640     i2_p_q2_a0_d0 = (iq_res[0] >> 12) & 0xfff;
0641     iq_corr_a0_d0 = ((iq_res[0] >> 24) & 0xff) + ((iq_res[1] & 0xf) << 8);
0642 
0643     if (i2_m_q2_a0_d0 > 0x800)
0644         i2_m_q2_a0_d0 = -((0xfff - i2_m_q2_a0_d0) + 1);
0645 
0646     if (i2_p_q2_a0_d0 > 0x800)
0647         i2_p_q2_a0_d0 = -((0xfff - i2_p_q2_a0_d0) + 1);
0648 
0649     if (iq_corr_a0_d0 > 0x800)
0650         iq_corr_a0_d0 = -((0xfff - iq_corr_a0_d0) + 1);
0651 
0652     i2_m_q2_a0_d1 = (iq_res[1] >> 4) & 0xfff;
0653     i2_p_q2_a0_d1 = (iq_res[2] & 0xfff);
0654     iq_corr_a0_d1 = (iq_res[2] >> 12) & 0xfff;
0655 
0656     if (i2_m_q2_a0_d1 > 0x800)
0657         i2_m_q2_a0_d1 = -((0xfff - i2_m_q2_a0_d1) + 1);
0658 
0659     if (iq_corr_a0_d1 > 0x800)
0660         iq_corr_a0_d1 = -((0xfff - iq_corr_a0_d1) + 1);
0661 
0662     i2_m_q2_a1_d0 = ((iq_res[2] >> 24) & 0xff) + ((iq_res[3] & 0xf) << 8);
0663     i2_p_q2_a1_d0 = (iq_res[3] >> 4) & 0xfff;
0664     iq_corr_a1_d0 = iq_res[4] & 0xfff;
0665 
0666     if (i2_m_q2_a1_d0 > 0x800)
0667         i2_m_q2_a1_d0 = -((0xfff - i2_m_q2_a1_d0) + 1);
0668 
0669     if (i2_p_q2_a1_d0 > 0x800)
0670         i2_p_q2_a1_d0 = -((0xfff - i2_p_q2_a1_d0) + 1);
0671 
0672     if (iq_corr_a1_d0 > 0x800)
0673         iq_corr_a1_d0 = -((0xfff - iq_corr_a1_d0) + 1);
0674 
0675     i2_m_q2_a1_d1 = (iq_res[4] >> 12) & 0xfff;
0676     i2_p_q2_a1_d1 = ((iq_res[4] >> 24) & 0xff) + ((iq_res[5] & 0xf) << 8);
0677     iq_corr_a1_d1 = (iq_res[5] >> 4) & 0xfff;
0678 
0679     if (i2_m_q2_a1_d1 > 0x800)
0680         i2_m_q2_a1_d1 = -((0xfff - i2_m_q2_a1_d1) + 1);
0681 
0682     if (i2_p_q2_a1_d1 > 0x800)
0683         i2_p_q2_a1_d1 = -((0xfff - i2_p_q2_a1_d1) + 1);
0684 
0685     if (iq_corr_a1_d1 > 0x800)
0686         iq_corr_a1_d1 = -((0xfff - iq_corr_a1_d1) + 1);
0687 
0688     if ((i2_p_q2_a0_d0 == 0) || (i2_p_q2_a0_d1 == 0) ||
0689         (i2_p_q2_a1_d0 == 0) || (i2_p_q2_a1_d1 == 0)) {
0690         ath_dbg(common, CALIBRATE,
0691             "Divide by 0:\n"
0692             "a0_d0=%d\n"
0693             "a0_d1=%d\n"
0694             "a2_d0=%d\n"
0695             "a1_d1=%d\n",
0696             i2_p_q2_a0_d0, i2_p_q2_a0_d1,
0697             i2_p_q2_a1_d0, i2_p_q2_a1_d1);
0698         return false;
0699     }
0700 
0701     if ((i2_p_q2_a0_d0 < 1024) || (i2_p_q2_a0_d0 > 2047) ||
0702             (i2_p_q2_a1_d0 < 0) || (i2_p_q2_a1_d1 < 0) ||
0703             (i2_p_q2_a0_d0 <= i2_m_q2_a0_d0) ||
0704             (i2_p_q2_a0_d0 <= iq_corr_a0_d0) ||
0705             (i2_p_q2_a0_d1 <= i2_m_q2_a0_d1) ||
0706             (i2_p_q2_a0_d1 <= iq_corr_a0_d1) ||
0707             (i2_p_q2_a1_d0 <= i2_m_q2_a1_d0) ||
0708             (i2_p_q2_a1_d0 <= iq_corr_a1_d0) ||
0709             (i2_p_q2_a1_d1 <= i2_m_q2_a1_d1) ||
0710             (i2_p_q2_a1_d1 <= iq_corr_a1_d1)) {
0711         return false;
0712     }
0713 
0714     mag_a0_d0 = (i2_m_q2_a0_d0 * res_scale) / i2_p_q2_a0_d0;
0715     phs_a0_d0 = (iq_corr_a0_d0 * res_scale) / i2_p_q2_a0_d0;
0716 
0717     mag_a0_d1 = (i2_m_q2_a0_d1 * res_scale) / i2_p_q2_a0_d1;
0718     phs_a0_d1 = (iq_corr_a0_d1 * res_scale) / i2_p_q2_a0_d1;
0719 
0720     mag_a1_d0 = (i2_m_q2_a1_d0 * res_scale) / i2_p_q2_a1_d0;
0721     phs_a1_d0 = (iq_corr_a1_d0 * res_scale) / i2_p_q2_a1_d0;
0722 
0723     mag_a1_d1 = (i2_m_q2_a1_d1 * res_scale) / i2_p_q2_a1_d1;
0724     phs_a1_d1 = (iq_corr_a1_d1 * res_scale) / i2_p_q2_a1_d1;
0725 
0726     /* w/o analog phase shift */
0727     sin_2phi_1 = (((mag_a0_d0 - mag_a0_d1) * delpt_shift) / DELPT);
0728     /* w/o analog phase shift */
0729     cos_2phi_1 = (((phs_a0_d1 - phs_a0_d0) * delpt_shift) / DELPT);
0730     /* w/  analog phase shift */
0731     sin_2phi_2 = (((mag_a1_d0 - mag_a1_d1) * delpt_shift) / DELPT);
0732     /* w/  analog phase shift */
0733     cos_2phi_2 = (((phs_a1_d1 - phs_a1_d0) * delpt_shift) / DELPT);
0734 
0735     /*
0736      * force sin^2 + cos^2 = 1;
0737      * find magnitude by approximation
0738      */
0739     mag1 = ar9003_hw_find_mag_approx(ah, cos_2phi_1, sin_2phi_1);
0740     mag2 = ar9003_hw_find_mag_approx(ah, cos_2phi_2, sin_2phi_2);
0741 
0742     if ((mag1 == 0) || (mag2 == 0)) {
0743         ath_dbg(common, CALIBRATE, "Divide by 0: mag1=%d, mag2=%d\n",
0744             mag1, mag2);
0745         return false;
0746     }
0747 
0748     /* normalization sin and cos by mag */
0749     sin_2phi_1 = (sin_2phi_1 * res_scale / mag1);
0750     cos_2phi_1 = (cos_2phi_1 * res_scale / mag1);
0751     sin_2phi_2 = (sin_2phi_2 * res_scale / mag2);
0752     cos_2phi_2 = (cos_2phi_2 * res_scale / mag2);
0753 
0754     /* calculate IQ mismatch */
0755     if (!ar9003_hw_solve_iq_cal(ah,
0756                  sin_2phi_1, cos_2phi_1,
0757                  sin_2phi_2, cos_2phi_2,
0758                  mag_a0_d0, phs_a0_d0,
0759                  mag_a1_d0,
0760                  phs_a1_d0, solved_eq)) {
0761         ath_dbg(common, CALIBRATE,
0762             "Call to ar9003_hw_solve_iq_cal() failed\n");
0763         return false;
0764     }
0765 
0766     mag_tx = solved_eq[0];
0767     phs_tx = solved_eq[1];
0768     mag_rx = solved_eq[2];
0769     phs_rx = solved_eq[3];
0770 
0771     ath_dbg(common, CALIBRATE,
0772         "chain %d: mag mismatch=%d phase mismatch=%d\n",
0773         chain_idx, mag_tx/res_scale, phs_tx/res_scale);
0774 
0775     if (res_scale == mag_tx) {
0776         ath_dbg(common, CALIBRATE,
0777             "Divide by 0: mag_tx=%d, res_scale=%d\n",
0778             mag_tx, res_scale);
0779         return false;
0780     }
0781 
0782     /* calculate and quantize Tx IQ correction factor */
0783     mag_corr_tx = (mag_tx * res_scale) / (res_scale - mag_tx);
0784     phs_corr_tx = -phs_tx;
0785 
0786     q_q_coff = (mag_corr_tx * 128 / res_scale);
0787     q_i_coff = (phs_corr_tx * 256 / res_scale);
0788 
0789     ath_dbg(common, CALIBRATE, "tx chain %d: mag corr=%d  phase corr=%d\n",
0790         chain_idx, q_q_coff, q_i_coff);
0791 
0792     if (q_i_coff < -63)
0793         q_i_coff = -63;
0794     if (q_i_coff > 63)
0795         q_i_coff = 63;
0796     if (q_q_coff < -63)
0797         q_q_coff = -63;
0798     if (q_q_coff > 63)
0799         q_q_coff = 63;
0800 
0801     iqc_coeff[0] = (q_q_coff * 128) + (0x7f & q_i_coff);
0802 
0803     ath_dbg(common, CALIBRATE, "tx chain %d: iq corr coeff=%x\n",
0804         chain_idx, iqc_coeff[0]);
0805 
0806     if (-mag_rx == res_scale) {
0807         ath_dbg(common, CALIBRATE,
0808             "Divide by 0: mag_rx=%d, res_scale=%d\n",
0809             mag_rx, res_scale);
0810         return false;
0811     }
0812 
0813     /* calculate and quantize Rx IQ correction factors */
0814     mag_corr_rx = (-mag_rx * res_scale) / (res_scale + mag_rx);
0815     phs_corr_rx = -phs_rx;
0816 
0817     q_q_coff = (mag_corr_rx * 128 / res_scale);
0818     q_i_coff = (phs_corr_rx * 256 / res_scale);
0819 
0820     ath_dbg(common, CALIBRATE, "rx chain %d: mag corr=%d  phase corr=%d\n",
0821         chain_idx, q_q_coff, q_i_coff);
0822 
0823     if (q_i_coff < -63)
0824         q_i_coff = -63;
0825     if (q_i_coff > 63)
0826         q_i_coff = 63;
0827     if (q_q_coff < -63)
0828         q_q_coff = -63;
0829     if (q_q_coff > 63)
0830         q_q_coff = 63;
0831 
0832     iqc_coeff[1] = (q_q_coff * 128) + (0x7f & q_i_coff);
0833 
0834     ath_dbg(common, CALIBRATE, "rx chain %d: iq corr coeff=%x\n",
0835         chain_idx, iqc_coeff[1]);
0836 
0837     return true;
0838 }
0839 
0840 static void ar9003_hw_detect_outlier(int mp_coeff[][MAXIQCAL],
0841                      int nmeasurement,
0842                      int max_delta)
0843 {
0844     int mp_max = -64, max_idx = 0;
0845     int mp_min = 63, min_idx = 0;
0846     int mp_avg = 0, i, outlier_idx = 0, mp_count = 0;
0847 
0848     /* find min/max mismatch across all calibrated gains */
0849     for (i = 0; i < nmeasurement; i++) {
0850         if (mp_coeff[i][0] > mp_max) {
0851             mp_max = mp_coeff[i][0];
0852             max_idx = i;
0853         } else if (mp_coeff[i][0] < mp_min) {
0854             mp_min = mp_coeff[i][0];
0855             min_idx = i;
0856         }
0857     }
0858 
0859     /* find average (exclude max abs value) */
0860     for (i = 0; i < nmeasurement; i++) {
0861         if ((abs(mp_coeff[i][0]) < abs(mp_max)) ||
0862             (abs(mp_coeff[i][0]) < abs(mp_min))) {
0863             mp_avg += mp_coeff[i][0];
0864             mp_count++;
0865         }
0866     }
0867 
0868     /*
0869      * finding mean magnitude/phase if possible, otherwise
0870      * just use the last value as the mean
0871      */
0872     if (mp_count)
0873         mp_avg /= mp_count;
0874     else
0875         mp_avg = mp_coeff[nmeasurement - 1][0];
0876 
0877     /* detect outlier */
0878     if (abs(mp_max - mp_min) > max_delta) {
0879         if (abs(mp_max - mp_avg) > abs(mp_min - mp_avg))
0880             outlier_idx = max_idx;
0881         else
0882             outlier_idx = min_idx;
0883 
0884         mp_coeff[outlier_idx][0] = mp_avg;
0885     }
0886 }
0887 
0888 static void ar9003_hw_tx_iq_cal_outlier_detection(struct ath_hw *ah,
0889                           struct coeff *coeff,
0890                           bool is_reusable)
0891 {
0892     int i, im, nmeasurement;
0893     int magnitude, phase;
0894     u32 tx_corr_coeff[MAX_MEASUREMENT][AR9300_MAX_CHAINS];
0895     struct ath9k_hw_cal_data *caldata = ah->caldata;
0896 
0897     memset(tx_corr_coeff, 0, sizeof(tx_corr_coeff));
0898     for (i = 0; i < MAX_MEASUREMENT / 2; i++) {
0899         tx_corr_coeff[i * 2][0] = tx_corr_coeff[(i * 2) + 1][0] =
0900                     AR_PHY_TX_IQCAL_CORR_COEFF_B0(i);
0901         if (!AR_SREV_9485(ah)) {
0902             tx_corr_coeff[i * 2][1] =
0903             tx_corr_coeff[(i * 2) + 1][1] =
0904                     AR_PHY_TX_IQCAL_CORR_COEFF_B1(i);
0905 
0906             tx_corr_coeff[i * 2][2] =
0907             tx_corr_coeff[(i * 2) + 1][2] =
0908                     AR_PHY_TX_IQCAL_CORR_COEFF_B2(i);
0909         }
0910     }
0911 
0912     /* Load the average of 2 passes */
0913     for (i = 0; i < AR9300_MAX_CHAINS; i++) {
0914         if (!(ah->txchainmask & (1 << i)))
0915             continue;
0916         nmeasurement = REG_READ_FIELD(ah,
0917                 AR_PHY_TX_IQCAL_STATUS_B0,
0918                 AR_PHY_CALIBRATED_GAINS_0);
0919 
0920         if (nmeasurement > MAX_MEASUREMENT)
0921             nmeasurement = MAX_MEASUREMENT;
0922 
0923         /*
0924          * Skip normal outlier detection for AR9550.
0925          */
0926         if (!AR_SREV_9550(ah)) {
0927             /* detect outlier only if nmeasurement > 1 */
0928             if (nmeasurement > 1) {
0929                 /* Detect magnitude outlier */
0930                 ar9003_hw_detect_outlier(coeff->mag_coeff[i],
0931                              nmeasurement,
0932                              MAX_MAG_DELTA);
0933 
0934                 /* Detect phase outlier */
0935                 ar9003_hw_detect_outlier(coeff->phs_coeff[i],
0936                              nmeasurement,
0937                              MAX_PHS_DELTA);
0938             }
0939         }
0940 
0941         for (im = 0; im < nmeasurement; im++) {
0942             magnitude = coeff->mag_coeff[i][im][0];
0943             phase = coeff->phs_coeff[i][im][0];
0944 
0945             coeff->iqc_coeff[0] =
0946                 (phase & 0x7f) | ((magnitude & 0x7f) << 7);
0947 
0948             if ((im % 2) == 0)
0949                 REG_RMW_FIELD(ah, tx_corr_coeff[im][i],
0950                     AR_PHY_TX_IQCAL_CORR_COEFF_00_COEFF_TABLE,
0951                     coeff->iqc_coeff[0]);
0952             else
0953                 REG_RMW_FIELD(ah, tx_corr_coeff[im][i],
0954                     AR_PHY_TX_IQCAL_CORR_COEFF_01_COEFF_TABLE,
0955                     coeff->iqc_coeff[0]);
0956 
0957             if (caldata)
0958                 caldata->tx_corr_coeff[im][i] =
0959                     coeff->iqc_coeff[0];
0960         }
0961         if (caldata)
0962             caldata->num_measures[i] = nmeasurement;
0963     }
0964 
0965     REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_3,
0966               AR_PHY_TX_IQCAL_CONTROL_3_IQCORR_EN, 0x1);
0967     REG_RMW_FIELD(ah, AR_PHY_RX_IQCAL_CORR_B0,
0968               AR_PHY_RX_IQCAL_CORR_B0_LOOPBACK_IQCORR_EN, 0x1);
0969 
0970     if (caldata) {
0971         if (is_reusable)
0972             set_bit(TXIQCAL_DONE, &caldata->cal_flags);
0973         else
0974             clear_bit(TXIQCAL_DONE, &caldata->cal_flags);
0975     }
0976 
0977     return;
0978 }
0979 
0980 static bool ar9003_hw_tx_iq_cal_run(struct ath_hw *ah)
0981 {
0982     struct ath_common *common = ath9k_hw_common(ah);
0983     u8 tx_gain_forced;
0984 
0985     tx_gain_forced = REG_READ_FIELD(ah, AR_PHY_TX_FORCED_GAIN,
0986                     AR_PHY_TXGAIN_FORCE);
0987     if (tx_gain_forced)
0988         REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN,
0989                   AR_PHY_TXGAIN_FORCE, 0);
0990 
0991     REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_START,
0992               AR_PHY_TX_IQCAL_START_DO_CAL, 1);
0993 
0994     if (!ath9k_hw_wait(ah, AR_PHY_TX_IQCAL_START,
0995             AR_PHY_TX_IQCAL_START_DO_CAL, 0,
0996             AH_WAIT_TIMEOUT)) {
0997         ath_dbg(common, CALIBRATE, "Tx IQ Cal is not completed\n");
0998         return false;
0999     }
1000     return true;
1001 }
1002 
1003 static void __ar955x_tx_iq_cal_sort(struct ath_hw *ah,
1004                     struct coeff *coeff,
1005                     int i, int nmeasurement)
1006 {
1007     struct ath_common *common = ath9k_hw_common(ah);
1008     int im, ix, iy;
1009 
1010     for (im = 0; im < nmeasurement; im++) {
1011         for (ix = 0; ix < MAXIQCAL - 1; ix++) {
1012             for (iy = ix + 1; iy <= MAXIQCAL - 1; iy++) {
1013                 if (coeff->mag_coeff[i][im][iy] <
1014                     coeff->mag_coeff[i][im][ix]) {
1015                     swap(coeff->mag_coeff[i][im][ix],
1016                          coeff->mag_coeff[i][im][iy]);
1017                 }
1018                 if (coeff->phs_coeff[i][im][iy] <
1019                     coeff->phs_coeff[i][im][ix]) {
1020                     swap(coeff->phs_coeff[i][im][ix],
1021                          coeff->phs_coeff[i][im][iy]);
1022                 }
1023             }
1024         }
1025         coeff->mag_coeff[i][im][0] = coeff->mag_coeff[i][im][MAXIQCAL / 2];
1026         coeff->phs_coeff[i][im][0] = coeff->phs_coeff[i][im][MAXIQCAL / 2];
1027 
1028         ath_dbg(common, CALIBRATE,
1029             "IQCAL: Median [ch%d][gain%d]: mag = %d phase = %d\n",
1030             i, im,
1031             coeff->mag_coeff[i][im][0],
1032             coeff->phs_coeff[i][im][0]);
1033     }
1034 }
1035 
1036 static bool ar955x_tx_iq_cal_median(struct ath_hw *ah,
1037                     struct coeff *coeff,
1038                     int iqcal_idx,
1039                     int nmeasurement)
1040 {
1041     int i;
1042 
1043     if ((iqcal_idx + 1) != MAXIQCAL)
1044         return false;
1045 
1046     for (i = 0; i < AR9300_MAX_CHAINS; i++) {
1047         __ar955x_tx_iq_cal_sort(ah, coeff, i, nmeasurement);
1048     }
1049 
1050     return true;
1051 }
1052 
1053 static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah,
1054                       int iqcal_idx,
1055                       bool is_reusable)
1056 {
1057     struct ath_common *common = ath9k_hw_common(ah);
1058     const u32 txiqcal_status[AR9300_MAX_CHAINS] = {
1059         AR_PHY_TX_IQCAL_STATUS_B0,
1060         AR_PHY_TX_IQCAL_STATUS_B1,
1061         AR_PHY_TX_IQCAL_STATUS_B2,
1062     };
1063     const u_int32_t chan_info_tab[] = {
1064         AR_PHY_CHAN_INFO_TAB_0,
1065         AR_PHY_CHAN_INFO_TAB_1,
1066         AR_PHY_CHAN_INFO_TAB_2,
1067     };
1068     static struct coeff coeff;
1069     s32 iq_res[6];
1070     int i, im, j;
1071     int nmeasurement = 0;
1072     bool outlier_detect = true;
1073 
1074     for (i = 0; i < AR9300_MAX_CHAINS; i++) {
1075         if (!(ah->txchainmask & (1 << i)))
1076             continue;
1077 
1078         nmeasurement = REG_READ_FIELD(ah,
1079                 AR_PHY_TX_IQCAL_STATUS_B0,
1080                 AR_PHY_CALIBRATED_GAINS_0);
1081         if (nmeasurement > MAX_MEASUREMENT)
1082             nmeasurement = MAX_MEASUREMENT;
1083 
1084         for (im = 0; im < nmeasurement; im++) {
1085             ath_dbg(common, CALIBRATE,
1086                 "Doing Tx IQ Cal for chain %d\n", i);
1087 
1088             if (REG_READ(ah, txiqcal_status[i]) &
1089                     AR_PHY_TX_IQCAL_STATUS_FAILED) {
1090                 ath_dbg(common, CALIBRATE,
1091                     "Tx IQ Cal failed for chain %d\n", i);
1092                 goto tx_iqcal_fail;
1093             }
1094 
1095             for (j = 0; j < 3; j++) {
1096                 u32 idx = 2 * j, offset = 4 * (3 * im + j);
1097 
1098                 REG_RMW_FIELD(ah,
1099                         AR_PHY_CHAN_INFO_MEMORY,
1100                         AR_PHY_CHAN_INFO_TAB_S2_READ,
1101                         0);
1102 
1103                 /* 32 bits */
1104                 iq_res[idx] = REG_READ(ah,
1105                         chan_info_tab[i] +
1106                         offset);
1107 
1108                 REG_RMW_FIELD(ah,
1109                         AR_PHY_CHAN_INFO_MEMORY,
1110                         AR_PHY_CHAN_INFO_TAB_S2_READ,
1111                         1);
1112 
1113                 /* 16 bits */
1114                 iq_res[idx + 1] = 0xffff & REG_READ(ah,
1115                         chan_info_tab[i] + offset);
1116 
1117                 ath_dbg(common, CALIBRATE,
1118                     "IQ_RES[%d]=0x%x IQ_RES[%d]=0x%x\n",
1119                     idx, iq_res[idx], idx + 1,
1120                     iq_res[idx + 1]);
1121             }
1122 
1123             if (!ar9003_hw_calc_iq_corr(ah, i, iq_res,
1124                         coeff.iqc_coeff)) {
1125                 ath_dbg(common, CALIBRATE,
1126                     "Failed in calculation of IQ correction\n");
1127                 goto tx_iqcal_fail;
1128             }
1129 
1130             coeff.phs_coeff[i][im][iqcal_idx] =
1131                 coeff.iqc_coeff[0] & 0x7f;
1132             coeff.mag_coeff[i][im][iqcal_idx] =
1133                 (coeff.iqc_coeff[0] >> 7) & 0x7f;
1134 
1135             if (coeff.mag_coeff[i][im][iqcal_idx] > 63)
1136                 coeff.mag_coeff[i][im][iqcal_idx] -= 128;
1137             if (coeff.phs_coeff[i][im][iqcal_idx] > 63)
1138                 coeff.phs_coeff[i][im][iqcal_idx] -= 128;
1139         }
1140     }
1141 
1142     if (AR_SREV_9550(ah))
1143         outlier_detect = ar955x_tx_iq_cal_median(ah, &coeff,
1144                              iqcal_idx, nmeasurement);
1145     if (outlier_detect)
1146         ar9003_hw_tx_iq_cal_outlier_detection(ah, &coeff, is_reusable);
1147 
1148     return;
1149 
1150 tx_iqcal_fail:
1151     ath_dbg(common, CALIBRATE, "Tx IQ Cal failed\n");
1152     return;
1153 }
1154 
1155 static void ar9003_hw_tx_iq_cal_reload(struct ath_hw *ah)
1156 {
1157     struct ath9k_hw_cal_data *caldata = ah->caldata;
1158     u32 tx_corr_coeff[MAX_MEASUREMENT][AR9300_MAX_CHAINS];
1159     int i, im;
1160 
1161     memset(tx_corr_coeff, 0, sizeof(tx_corr_coeff));
1162     for (i = 0; i < MAX_MEASUREMENT / 2; i++) {
1163         tx_corr_coeff[i * 2][0] = tx_corr_coeff[(i * 2) + 1][0] =
1164                     AR_PHY_TX_IQCAL_CORR_COEFF_B0(i);
1165         if (!AR_SREV_9485(ah)) {
1166             tx_corr_coeff[i * 2][1] =
1167             tx_corr_coeff[(i * 2) + 1][1] =
1168                     AR_PHY_TX_IQCAL_CORR_COEFF_B1(i);
1169 
1170             tx_corr_coeff[i * 2][2] =
1171             tx_corr_coeff[(i * 2) + 1][2] =
1172                     AR_PHY_TX_IQCAL_CORR_COEFF_B2(i);
1173         }
1174     }
1175 
1176     for (i = 0; i < AR9300_MAX_CHAINS; i++) {
1177         if (!(ah->txchainmask & (1 << i)))
1178             continue;
1179 
1180         for (im = 0; im < caldata->num_measures[i]; im++) {
1181             if ((im % 2) == 0)
1182                 REG_RMW_FIELD(ah, tx_corr_coeff[im][i],
1183                      AR_PHY_TX_IQCAL_CORR_COEFF_00_COEFF_TABLE,
1184                      caldata->tx_corr_coeff[im][i]);
1185             else
1186                 REG_RMW_FIELD(ah, tx_corr_coeff[im][i],
1187                      AR_PHY_TX_IQCAL_CORR_COEFF_01_COEFF_TABLE,
1188                      caldata->tx_corr_coeff[im][i]);
1189         }
1190     }
1191 
1192     REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_3,
1193               AR_PHY_TX_IQCAL_CONTROL_3_IQCORR_EN, 0x1);
1194     REG_RMW_FIELD(ah, AR_PHY_RX_IQCAL_CORR_B0,
1195               AR_PHY_RX_IQCAL_CORR_B0_LOOPBACK_IQCORR_EN, 0x1);
1196 }
1197 
1198 static void ar9003_hw_manual_peak_cal(struct ath_hw *ah, u8 chain, bool is_2g)
1199 {
1200     int offset[8] = {0}, total = 0, test;
1201     int agc_out, i, peak_detect_threshold = 0;
1202 
1203     if (AR_SREV_9550(ah) || AR_SREV_9531(ah))
1204         peak_detect_threshold = 8;
1205     else if (AR_SREV_9561(ah))
1206         peak_detect_threshold = 11;
1207 
1208     /*
1209      * Turn off LNA/SW.
1210      */
1211     REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_GAINSTAGES(chain),
1212               AR_PHY_65NM_RXRF_GAINSTAGES_RX_OVERRIDE, 0x1);
1213     REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_GAINSTAGES(chain),
1214               AR_PHY_65NM_RXRF_GAINSTAGES_LNAON_CALDC, 0x0);
1215 
1216     if (AR_SREV_9003_PCOEM(ah) || AR_SREV_9330_11(ah)) {
1217         if (is_2g)
1218             REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_GAINSTAGES(chain),
1219                       AR_PHY_65NM_RXRF_GAINSTAGES_LNA2G_GAIN_OVR, 0x0);
1220         else
1221             REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_GAINSTAGES(chain),
1222                       AR_PHY_65NM_RXRF_GAINSTAGES_LNA5G_GAIN_OVR, 0x0);
1223     }
1224 
1225     /*
1226      * Turn off RXON.
1227      */
1228     REG_RMW_FIELD(ah, AR_PHY_65NM_RXTX2(chain),
1229               AR_PHY_65NM_RXTX2_RXON_OVR, 0x1);
1230     REG_RMW_FIELD(ah, AR_PHY_65NM_RXTX2(chain),
1231               AR_PHY_65NM_RXTX2_RXON, 0x0);
1232 
1233     /*
1234      * Turn on AGC for cal.
1235      */
1236     REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
1237               AR_PHY_65NM_RXRF_AGC_AGC_OVERRIDE, 0x1);
1238     REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
1239               AR_PHY_65NM_RXRF_AGC_AGC_ON_OVR, 0x1);
1240     REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
1241               AR_PHY_65NM_RXRF_AGC_AGC_CAL_OVR, 0x1);
1242 
1243     if (AR_SREV_9330_11(ah))
1244         REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
1245                   AR_PHY_65NM_RXRF_AGC_AGC2G_CALDAC_OVR, 0x0);
1246 
1247     if (is_2g)
1248         REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
1249                   AR_PHY_65NM_RXRF_AGC_AGC2G_DBDAC_OVR,
1250                   peak_detect_threshold);
1251     else
1252         REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
1253                   AR_PHY_65NM_RXRF_AGC_AGC5G_DBDAC_OVR,
1254                   peak_detect_threshold);
1255 
1256     for (i = 6; i > 0; i--) {
1257         offset[i] = BIT(i - 1);
1258         test = total + offset[i];
1259 
1260         if (is_2g)
1261             REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
1262                       AR_PHY_65NM_RXRF_AGC_AGC2G_CALDAC_OVR,
1263                       test);
1264         else
1265             REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
1266                       AR_PHY_65NM_RXRF_AGC_AGC5G_CALDAC_OVR,
1267                       test);
1268         udelay(100);
1269         agc_out = REG_READ_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
1270                      AR_PHY_65NM_RXRF_AGC_AGC_OUT);
1271         offset[i] = (agc_out) ? 0 : 1;
1272         total += (offset[i] << (i - 1));
1273     }
1274 
1275     if (is_2g)
1276         REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
1277                   AR_PHY_65NM_RXRF_AGC_AGC2G_CALDAC_OVR, total);
1278     else
1279         REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
1280                   AR_PHY_65NM_RXRF_AGC_AGC5G_CALDAC_OVR, total);
1281 
1282     /*
1283      * Turn on LNA.
1284      */
1285     REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_GAINSTAGES(chain),
1286               AR_PHY_65NM_RXRF_GAINSTAGES_RX_OVERRIDE, 0);
1287     /*
1288      * Turn off RXON.
1289      */
1290     REG_RMW_FIELD(ah, AR_PHY_65NM_RXTX2(chain),
1291               AR_PHY_65NM_RXTX2_RXON_OVR, 0);
1292     /*
1293      * Turn off peak detect calibration.
1294      */
1295     REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
1296               AR_PHY_65NM_RXRF_AGC_AGC_CAL_OVR, 0);
1297 }
1298 
1299 static void ar9003_hw_do_pcoem_manual_peak_cal(struct ath_hw *ah,
1300                            struct ath9k_channel *chan,
1301                            bool run_rtt_cal)
1302 {
1303     struct ath9k_hw_cal_data *caldata = ah->caldata;
1304     int i;
1305 
1306     if ((ah->caps.hw_caps & ATH9K_HW_CAP_RTT) && !run_rtt_cal)
1307         return;
1308 
1309     for (i = 0; i < AR9300_MAX_CHAINS; i++) {
1310         if (!(ah->rxchainmask & (1 << i)))
1311             continue;
1312         ar9003_hw_manual_peak_cal(ah, i, IS_CHAN_2GHZ(chan));
1313     }
1314 
1315     if (caldata)
1316         set_bit(SW_PKDET_DONE, &caldata->cal_flags);
1317 
1318     if ((ah->caps.hw_caps & ATH9K_HW_CAP_RTT) && caldata) {
1319         if (IS_CHAN_2GHZ(chan)){
1320             caldata->caldac[0] = REG_READ_FIELD(ah,
1321                             AR_PHY_65NM_RXRF_AGC(0),
1322                             AR_PHY_65NM_RXRF_AGC_AGC2G_CALDAC_OVR);
1323             caldata->caldac[1] = REG_READ_FIELD(ah,
1324                             AR_PHY_65NM_RXRF_AGC(1),
1325                             AR_PHY_65NM_RXRF_AGC_AGC2G_CALDAC_OVR);
1326         } else {
1327             caldata->caldac[0] = REG_READ_FIELD(ah,
1328                             AR_PHY_65NM_RXRF_AGC(0),
1329                             AR_PHY_65NM_RXRF_AGC_AGC5G_CALDAC_OVR);
1330             caldata->caldac[1] = REG_READ_FIELD(ah,
1331                             AR_PHY_65NM_RXRF_AGC(1),
1332                             AR_PHY_65NM_RXRF_AGC_AGC5G_CALDAC_OVR);
1333         }
1334     }
1335 }
1336 
1337 static void ar9003_hw_cl_cal_post_proc(struct ath_hw *ah, bool is_reusable)
1338 {
1339     u32 cl_idx[AR9300_MAX_CHAINS] = { AR_PHY_CL_TAB_0,
1340                       AR_PHY_CL_TAB_1,
1341                       AR_PHY_CL_TAB_2 };
1342     struct ath9k_hw_cal_data *caldata = ah->caldata;
1343     bool txclcal_done = false;
1344     int i, j;
1345 
1346     if (!caldata || !(ah->enabled_cals & TX_CL_CAL))
1347         return;
1348 
1349     txclcal_done = !!(REG_READ(ah, AR_PHY_AGC_CONTROL) &
1350               AR_PHY_AGC_CONTROL_CLC_SUCCESS);
1351 
1352     if (test_bit(TXCLCAL_DONE, &caldata->cal_flags)) {
1353         for (i = 0; i < AR9300_MAX_CHAINS; i++) {
1354             if (!(ah->txchainmask & (1 << i)))
1355                 continue;
1356             for (j = 0; j < MAX_CL_TAB_ENTRY; j++)
1357                 REG_WRITE(ah, CL_TAB_ENTRY(cl_idx[i]),
1358                       caldata->tx_clcal[i][j]);
1359         }
1360     } else if (is_reusable && txclcal_done) {
1361         for (i = 0; i < AR9300_MAX_CHAINS; i++) {
1362             if (!(ah->txchainmask & (1 << i)))
1363                 continue;
1364             for (j = 0; j < MAX_CL_TAB_ENTRY; j++)
1365                 caldata->tx_clcal[i][j] =
1366                     REG_READ(ah, CL_TAB_ENTRY(cl_idx[i]));
1367         }
1368         set_bit(TXCLCAL_DONE, &caldata->cal_flags);
1369     }
1370 }
1371 
1372 static void ar9003_hw_init_cal_common(struct ath_hw *ah)
1373 {
1374     struct ath9k_hw_cal_data *caldata = ah->caldata;
1375 
1376     /* Initialize list pointers */
1377     ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL;
1378 
1379     INIT_CAL(&ah->iq_caldata);
1380     INSERT_CAL(ah, &ah->iq_caldata);
1381 
1382     /* Initialize current pointer to first element in list */
1383     ah->cal_list_curr = ah->cal_list;
1384 
1385     if (ah->cal_list_curr)
1386         ath9k_hw_reset_calibration(ah, ah->cal_list_curr);
1387 
1388     if (caldata)
1389         caldata->CalValid = 0;
1390 }
1391 
1392 static bool ar9003_hw_init_cal_pcoem(struct ath_hw *ah,
1393                      struct ath9k_channel *chan)
1394 {
1395     struct ath_common *common = ath9k_hw_common(ah);
1396     struct ath9k_hw_cal_data *caldata = ah->caldata;
1397     bool txiqcal_done = false;
1398     bool is_reusable = true, status = true;
1399     bool run_rtt_cal = false, run_agc_cal;
1400     bool rtt = !!(ah->caps.hw_caps & ATH9K_HW_CAP_RTT);
1401     u32 rx_delay = 0;
1402     u32 agc_ctrl = 0, agc_supp_cals = AR_PHY_AGC_CONTROL_OFFSET_CAL |
1403                       AR_PHY_AGC_CONTROL_FLTR_CAL   |
1404                       AR_PHY_AGC_CONTROL_PKDET_CAL;
1405 
1406     /* Use chip chainmask only for calibration */
1407     ar9003_hw_set_chain_masks(ah, ah->caps.rx_chainmask, ah->caps.tx_chainmask);
1408 
1409     if (rtt) {
1410         if (!ar9003_hw_rtt_restore(ah, chan))
1411             run_rtt_cal = true;
1412 
1413         if (run_rtt_cal)
1414             ath_dbg(common, CALIBRATE, "RTT calibration to be done\n");
1415     }
1416 
1417     run_agc_cal = run_rtt_cal;
1418 
1419     if (run_rtt_cal) {
1420         ar9003_hw_rtt_enable(ah);
1421         ar9003_hw_rtt_set_mask(ah, 0x00);
1422         ar9003_hw_rtt_clear_hist(ah);
1423     }
1424 
1425     if (rtt) {
1426         if (!run_rtt_cal) {
1427             agc_ctrl = REG_READ(ah, AR_PHY_AGC_CONTROL);
1428             agc_supp_cals &= agc_ctrl;
1429             agc_ctrl &= ~(AR_PHY_AGC_CONTROL_OFFSET_CAL |
1430                       AR_PHY_AGC_CONTROL_FLTR_CAL |
1431                       AR_PHY_AGC_CONTROL_PKDET_CAL);
1432             REG_WRITE(ah, AR_PHY_AGC_CONTROL, agc_ctrl);
1433         } else {
1434             if (ah->ah_flags & AH_FASTCC)
1435                 run_agc_cal = true;
1436         }
1437     }
1438 
1439     if (ah->enabled_cals & TX_CL_CAL) {
1440         if (caldata && test_bit(TXCLCAL_DONE, &caldata->cal_flags))
1441             REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL,
1442                     AR_PHY_CL_CAL_ENABLE);
1443         else {
1444             REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL,
1445                     AR_PHY_CL_CAL_ENABLE);
1446             run_agc_cal = true;
1447         }
1448     }
1449 
1450     if ((IS_CHAN_HALF_RATE(chan) || IS_CHAN_QUARTER_RATE(chan)) ||
1451         !(ah->enabled_cals & TX_IQ_CAL))
1452         goto skip_tx_iqcal;
1453 
1454     /* Do Tx IQ Calibration */
1455     REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_1,
1456               AR_PHY_TX_IQCAL_CONTROL_1_IQCORR_I_Q_COFF_DELPT,
1457               DELPT);
1458 
1459     /*
1460      * For AR9485 or later chips, TxIQ cal runs as part of
1461      * AGC calibration
1462      */
1463     if (ah->enabled_cals & TX_IQ_ON_AGC_CAL) {
1464         if (caldata && !test_bit(TXIQCAL_DONE, &caldata->cal_flags))
1465             REG_SET_BIT(ah, AR_PHY_TX_IQCAL_CONTROL_0,
1466                     AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL);
1467         else
1468             REG_CLR_BIT(ah, AR_PHY_TX_IQCAL_CONTROL_0,
1469                     AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL);
1470         txiqcal_done = run_agc_cal = true;
1471     }
1472 
1473 skip_tx_iqcal:
1474     if (ath9k_hw_mci_is_enabled(ah) && IS_CHAN_2GHZ(chan) && run_agc_cal)
1475         ar9003_mci_init_cal_req(ah, &is_reusable);
1476 
1477     if (REG_READ(ah, AR_PHY_CL_CAL_CTL) & AR_PHY_CL_CAL_ENABLE) {
1478         rx_delay = REG_READ(ah, AR_PHY_RX_DELAY);
1479         /* Disable BB_active */
1480         REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS);
1481         udelay(5);
1482         REG_WRITE(ah, AR_PHY_RX_DELAY, AR_PHY_RX_DELAY_DELAY);
1483         REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
1484     }
1485 
1486     if (run_agc_cal || !(ah->ah_flags & AH_FASTCC)) {
1487         /* Calibrate the AGC */
1488         REG_WRITE(ah, AR_PHY_AGC_CONTROL,
1489               REG_READ(ah, AR_PHY_AGC_CONTROL) |
1490               AR_PHY_AGC_CONTROL_CAL);
1491 
1492         /* Poll for offset calibration complete */
1493         status = ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL,
1494                        AR_PHY_AGC_CONTROL_CAL,
1495                        0, AH_WAIT_TIMEOUT);
1496 
1497         ar9003_hw_do_pcoem_manual_peak_cal(ah, chan, run_rtt_cal);
1498     }
1499 
1500     if (REG_READ(ah, AR_PHY_CL_CAL_CTL) & AR_PHY_CL_CAL_ENABLE) {
1501         REG_WRITE(ah, AR_PHY_RX_DELAY, rx_delay);
1502         udelay(5);
1503     }
1504 
1505     if (ath9k_hw_mci_is_enabled(ah) && IS_CHAN_2GHZ(chan) && run_agc_cal)
1506         ar9003_mci_init_cal_done(ah);
1507 
1508     if (rtt && !run_rtt_cal) {
1509         agc_ctrl |= agc_supp_cals;
1510         REG_WRITE(ah, AR_PHY_AGC_CONTROL, agc_ctrl);
1511     }
1512 
1513     if (!status) {
1514         if (run_rtt_cal)
1515             ar9003_hw_rtt_disable(ah);
1516 
1517         ath_dbg(common, CALIBRATE,
1518             "offset calibration failed to complete in %d ms; noisy environment?\n",
1519             AH_WAIT_TIMEOUT / 1000);
1520         return false;
1521     }
1522 
1523     if (txiqcal_done)
1524         ar9003_hw_tx_iq_cal_post_proc(ah, 0, is_reusable);
1525     else if (caldata && test_bit(TXIQCAL_DONE, &caldata->cal_flags))
1526         ar9003_hw_tx_iq_cal_reload(ah);
1527 
1528     ar9003_hw_cl_cal_post_proc(ah, is_reusable);
1529 
1530     if (run_rtt_cal && caldata) {
1531         if (is_reusable) {
1532             if (!ath9k_hw_rfbus_req(ah)) {
1533                 ath_err(ath9k_hw_common(ah),
1534                     "Could not stop baseband\n");
1535             } else {
1536                 ar9003_hw_rtt_fill_hist(ah);
1537 
1538                 if (test_bit(SW_PKDET_DONE, &caldata->cal_flags))
1539                     ar9003_hw_rtt_load_hist(ah);
1540             }
1541 
1542             ath9k_hw_rfbus_done(ah);
1543         }
1544 
1545         ar9003_hw_rtt_disable(ah);
1546     }
1547 
1548     /* Revert chainmask to runtime parameters */
1549     ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask);
1550 
1551     ar9003_hw_init_cal_common(ah);
1552 
1553     return true;
1554 }
1555 
1556 static bool do_ar9003_agc_cal(struct ath_hw *ah)
1557 {
1558     struct ath_common *common = ath9k_hw_common(ah);
1559     bool status;
1560 
1561     REG_WRITE(ah, AR_PHY_AGC_CONTROL,
1562           REG_READ(ah, AR_PHY_AGC_CONTROL) |
1563           AR_PHY_AGC_CONTROL_CAL);
1564 
1565     status = ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL,
1566                    AR_PHY_AGC_CONTROL_CAL,
1567                    0, AH_WAIT_TIMEOUT);
1568     if (!status) {
1569         ath_dbg(common, CALIBRATE,
1570             "offset calibration failed to complete in %d ms,"
1571             "noisy environment?\n",
1572             AH_WAIT_TIMEOUT / 1000);
1573         return false;
1574     }
1575 
1576     return true;
1577 }
1578 
1579 static bool ar9003_hw_init_cal_soc(struct ath_hw *ah,
1580                    struct ath9k_channel *chan)
1581 {
1582     bool txiqcal_done = false;
1583     bool status = true;
1584     bool run_agc_cal = false, sep_iq_cal = false;
1585     int i = 0;
1586 
1587     /* Use chip chainmask only for calibration */
1588     ar9003_hw_set_chain_masks(ah, ah->caps.rx_chainmask, ah->caps.tx_chainmask);
1589 
1590     if (ah->enabled_cals & TX_CL_CAL) {
1591         REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
1592         run_agc_cal = true;
1593     }
1594 
1595     if (IS_CHAN_HALF_RATE(chan) || IS_CHAN_QUARTER_RATE(chan))
1596         goto skip_tx_iqcal;
1597 
1598     /* Do Tx IQ Calibration */
1599     REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_1,
1600               AR_PHY_TX_IQCAL_CONTROL_1_IQCORR_I_Q_COFF_DELPT,
1601               DELPT);
1602 
1603     /*
1604      * For AR9485 or later chips, TxIQ cal runs as part of
1605      * AGC calibration. Specifically, AR9550 in SoC chips.
1606      */
1607     if (ah->enabled_cals & TX_IQ_ON_AGC_CAL) {
1608         if (REG_READ_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_0,
1609                    AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL)) {
1610                 txiqcal_done = true;
1611         } else {
1612             txiqcal_done = false;
1613         }
1614         run_agc_cal = true;
1615     } else {
1616         sep_iq_cal = true;
1617         run_agc_cal = true;
1618     }
1619 
1620     /*
1621      * In the SoC family, this will run for AR9300, AR9331 and AR9340.
1622      */
1623     if (sep_iq_cal) {
1624         txiqcal_done = ar9003_hw_tx_iq_cal_run(ah);
1625         REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS);
1626         udelay(5);
1627         REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
1628     }
1629 
1630     if (AR_SREV_9550(ah) && IS_CHAN_2GHZ(chan)) {
1631         if (!ar9003_hw_dynamic_osdac_selection(ah, txiqcal_done))
1632             return false;
1633     }
1634 
1635 skip_tx_iqcal:
1636     if (run_agc_cal || !(ah->ah_flags & AH_FASTCC)) {
1637         for (i = 0; i < AR9300_MAX_CHAINS; i++) {
1638             if (!(ah->rxchainmask & (1 << i)))
1639                 continue;
1640 
1641             ar9003_hw_manual_peak_cal(ah, i,
1642                           IS_CHAN_2GHZ(chan));
1643         }
1644 
1645         /*
1646          * For non-AR9550 chips, we just trigger AGC calibration
1647          * in the HW, poll for completion and then process
1648          * the results.
1649          *
1650          * For AR955x, we run it multiple times and use
1651          * median IQ correction.
1652          */
1653         if (!AR_SREV_9550(ah)) {
1654             status = do_ar9003_agc_cal(ah);
1655             if (!status)
1656                 return false;
1657 
1658             if (txiqcal_done)
1659                 ar9003_hw_tx_iq_cal_post_proc(ah, 0, false);
1660         } else {
1661             if (!txiqcal_done) {
1662                 status = do_ar9003_agc_cal(ah);
1663                 if (!status)
1664                     return false;
1665             } else {
1666                 for (i = 0; i < MAXIQCAL; i++) {
1667                     status = do_ar9003_agc_cal(ah);
1668                     if (!status)
1669                         return false;
1670                     ar9003_hw_tx_iq_cal_post_proc(ah, i, false);
1671                 }
1672             }
1673         }
1674     }
1675 
1676     /* Revert chainmask to runtime parameters */
1677     ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask);
1678 
1679     ar9003_hw_init_cal_common(ah);
1680 
1681     return true;
1682 }
1683 
1684 void ar9003_hw_attach_calib_ops(struct ath_hw *ah)
1685 {
1686     struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
1687     struct ath_hw_ops *ops = ath9k_hw_ops(ah);
1688 
1689     if (AR_SREV_9003_PCOEM(ah))
1690         priv_ops->init_cal = ar9003_hw_init_cal_pcoem;
1691     else
1692         priv_ops->init_cal = ar9003_hw_init_cal_soc;
1693 
1694     priv_ops->init_cal_settings = ar9003_hw_init_cal_settings;
1695     priv_ops->setup_calibration = ar9003_hw_setup_calibration;
1696 
1697     ops->calibrate = ar9003_hw_calibrate;
1698 }