linux/drivers/net/wireless/ath/ath9k/ar9003_calib.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2010-2011 Atheros Communications Inc.
   3 *
   4 * Permission to use, copy, modify, and/or distribute this software for any
   5 * purpose with or without fee is hereby granted, provided that the above
   6 * copyright notice and this permission notice appear in all copies.
   7 *
   8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15 */
  16
  17#include "hw.h"
  18#include "hw-ops.h"
  19#include "ar9003_phy.h"
  20#include "ar9003_rtt.h"
  21#include "ar9003_mci.h"
  22
  23#define MAX_MEASUREMENT MAX_IQCAL_MEASUREMENT
  24#define MAX_MAG_DELTA   11
  25#define MAX_PHS_DELTA   10
  26
  27struct coeff {
  28        int mag_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT];
  29        int phs_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT];
  30        int iqc_coeff[2];
  31};
  32
  33enum ar9003_cal_types {
  34        IQ_MISMATCH_CAL = BIT(0),
  35};
  36
  37static void ar9003_hw_setup_calibration(struct ath_hw *ah,
  38                                        struct ath9k_cal_list *currCal)
  39{
  40        struct ath_common *common = ath9k_hw_common(ah);
  41
  42        /* Select calibration to run */
  43        switch (currCal->calData->calType) {
  44        case IQ_MISMATCH_CAL:
  45                /*
  46                 * Start calibration with
  47                 * 2^(INIT_IQCAL_LOG_COUNT_MAX+1) samples
  48                 */
  49                REG_RMW_FIELD(ah, AR_PHY_TIMING4,
  50                              AR_PHY_TIMING4_IQCAL_LOG_COUNT_MAX,
  51                              currCal->calData->calCountMax);
  52                REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ);
  53
  54                ath_dbg(common, CALIBRATE,
  55                        "starting IQ Mismatch Calibration\n");
  56
  57                /* Kick-off cal */
  58                REG_SET_BIT(ah, AR_PHY_TIMING4, AR_PHY_TIMING4_DO_CAL);
  59                break;
  60        default:
  61                ath_err(common, "Invalid calibration type\n");
  62                break;
  63        }
  64}
  65
  66/*
  67 * Generic calibration routine.
  68 * Recalibrate the lower PHY chips to account for temperature/environment
  69 * changes.
  70 */
  71static bool ar9003_hw_per_calibration(struct ath_hw *ah,
  72                                      struct ath9k_channel *ichan,
  73                                      u8 rxchainmask,
  74                                      struct ath9k_cal_list *currCal)
  75{
  76        struct ath9k_hw_cal_data *caldata = ah->caldata;
  77        /* Cal is assumed not done until explicitly set below */
  78        bool iscaldone = false;
  79
  80        /* Calibration in progress. */
  81        if (currCal->calState == CAL_RUNNING) {
  82                /* Check to see if it has finished. */
  83                if (!(REG_READ(ah, AR_PHY_TIMING4) & AR_PHY_TIMING4_DO_CAL)) {
  84                        /*
  85                        * Accumulate cal measures for active chains
  86                        */
  87                        currCal->calData->calCollect(ah);
  88                        ah->cal_samples++;
  89
  90                        if (ah->cal_samples >=
  91                            currCal->calData->calNumSamples) {
  92                                unsigned int i, numChains = 0;
  93                                for (i = 0; i < AR9300_MAX_CHAINS; i++) {
  94                                        if (rxchainmask & (1 << i))
  95                                                numChains++;
  96                                }
  97
  98                                /*
  99                                * Process accumulated data
 100                                */
 101                                currCal->calData->calPostProc(ah, numChains);
 102
 103                                /* Calibration has finished. */
 104                                caldata->CalValid |= currCal->calData->calType;
 105                                currCal->calState = CAL_DONE;
 106                                iscaldone = true;
 107                        } else {
 108                        /*
 109                         * Set-up collection of another sub-sample until we
 110                         * get desired number
 111                         */
 112                        ar9003_hw_setup_calibration(ah, currCal);
 113                        }
 114                }
 115        } else if (!(caldata->CalValid & currCal->calData->calType)) {
 116                /* If current cal is marked invalid in channel, kick it off */
 117                ath9k_hw_reset_calibration(ah, currCal);
 118        }
 119
 120        return iscaldone;
 121}
 122
 123static bool ar9003_hw_calibrate(struct ath_hw *ah,
 124                                struct ath9k_channel *chan,
 125                                u8 rxchainmask,
 126                                bool longcal)
 127{
 128        bool iscaldone = true;
 129        struct ath9k_cal_list *currCal = ah->cal_list_curr;
 130
 131        /*
 132         * For given calibration:
 133         * 1. Call generic cal routine
 134         * 2. When this cal is done (isCalDone) if we have more cals waiting
 135         *    (eg after reset), mask this to upper layers by not propagating
 136         *    isCalDone if it is set to TRUE.
 137         *    Instead, change isCalDone to FALSE and setup the waiting cal(s)
 138         *    to be run.
 139         */
 140        if (currCal &&
 141            (currCal->calState == CAL_RUNNING ||
 142             currCal->calState == CAL_WAITING)) {
 143                iscaldone = ar9003_hw_per_calibration(ah, chan,
 144                                                      rxchainmask, currCal);
 145                if (iscaldone) {
 146                        ah->cal_list_curr = currCal = currCal->calNext;
 147
 148                        if (currCal->calState == CAL_WAITING) {
 149                                iscaldone = false;
 150                                ath9k_hw_reset_calibration(ah, currCal);
 151                        }
 152                }
 153        }
 154
 155        /*
 156         * Do NF cal only at longer intervals. Get the value from
 157         * the previous NF cal and update history buffer.
 158         */
 159        if (longcal && ath9k_hw_getnf(ah, chan)) {
 160                /*
 161                 * Load the NF from history buffer of the current channel.
 162                 * NF is slow time-variant, so it is OK to use a historical
 163                 * value.
 164                 */
 165                ath9k_hw_loadnf(ah, ah->curchan);
 166
 167                /* start NF calibration, without updating BB NF register */
 168                ath9k_hw_start_nfcal(ah, false);
 169        }
 170
 171        return iscaldone;
 172}
 173
 174static void ar9003_hw_iqcal_collect(struct ath_hw *ah)
 175{
 176        int i;
 177
 178        /* Accumulate IQ cal measures for active chains */
 179        for (i = 0; i < AR5416_MAX_CHAINS; i++) {
 180                if (ah->txchainmask & BIT(i)) {
 181                        ah->totalPowerMeasI[i] +=
 182                                REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
 183                        ah->totalPowerMeasQ[i] +=
 184                                REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
 185                        ah->totalIqCorrMeas[i] +=
 186                                (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
 187                        ath_dbg(ath9k_hw_common(ah), CALIBRATE,
 188                                "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n",
 189                                ah->cal_samples, i, ah->totalPowerMeasI[i],
 190                                ah->totalPowerMeasQ[i],
 191                                ah->totalIqCorrMeas[i]);
 192                }
 193        }
 194}
 195
 196static void ar9003_hw_iqcalibrate(struct ath_hw *ah, u8 numChains)
 197{
 198        struct ath_common *common = ath9k_hw_common(ah);
 199        u32 powerMeasQ, powerMeasI, iqCorrMeas;
 200        u32 qCoffDenom, iCoffDenom;
 201        int32_t qCoff, iCoff;
 202        int iqCorrNeg, i;
 203        static const u_int32_t offset_array[3] = {
 204                AR_PHY_RX_IQCAL_CORR_B0,
 205                AR_PHY_RX_IQCAL_CORR_B1,
 206                AR_PHY_RX_IQCAL_CORR_B2,
 207        };
 208
 209        for (i = 0; i < numChains; i++) {
 210                powerMeasI = ah->totalPowerMeasI[i];
 211                powerMeasQ = ah->totalPowerMeasQ[i];
 212                iqCorrMeas = ah->totalIqCorrMeas[i];
 213
 214                ath_dbg(common, CALIBRATE,
 215                        "Starting IQ Cal and Correction for Chain %d\n", i);
 216
 217                ath_dbg(common, CALIBRATE,
 218                        "Original: Chn %d iq_corr_meas = 0x%08x\n",
 219                        i, ah->totalIqCorrMeas[i]);
 220
 221                iqCorrNeg = 0;
 222
 223                if (iqCorrMeas > 0x80000000) {
 224                        iqCorrMeas = (0xffffffff - iqCorrMeas) + 1;
 225                        iqCorrNeg = 1;
 226                }
 227
 228                ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_i = 0x%08x\n",
 229                        i, powerMeasI);
 230                ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_q = 0x%08x\n",
 231                        i, powerMeasQ);
 232                ath_dbg(common, CALIBRATE, "iqCorrNeg is 0x%08x\n", iqCorrNeg);
 233
 234                iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 256;
 235                qCoffDenom = powerMeasQ / 64;
 236
 237                if ((iCoffDenom != 0) && (qCoffDenom != 0)) {
 238                        iCoff = iqCorrMeas / iCoffDenom;
 239                        qCoff = powerMeasI / qCoffDenom - 64;
 240                        ath_dbg(common, CALIBRATE, "Chn %d iCoff = 0x%08x\n",
 241                                i, iCoff);
 242                        ath_dbg(common, CALIBRATE, "Chn %d qCoff = 0x%08x\n",
 243                                i, qCoff);
 244
 245                        /* Force bounds on iCoff */
 246                        if (iCoff >= 63)
 247                                iCoff = 63;
 248                        else if (iCoff <= -63)
 249                                iCoff = -63;
 250
 251                        /* Negate iCoff if iqCorrNeg == 0 */
 252                        if (iqCorrNeg == 0x0)
 253                                iCoff = -iCoff;
 254
 255                        /* Force bounds on qCoff */
 256                        if (qCoff >= 63)
 257                                qCoff = 63;
 258                        else if (qCoff <= -63)
 259                                qCoff = -63;
 260
 261                        iCoff = iCoff & 0x7f;
 262                        qCoff = qCoff & 0x7f;
 263
 264                        ath_dbg(common, CALIBRATE,
 265                                "Chn %d : iCoff = 0x%x  qCoff = 0x%x\n",
 266                                i, iCoff, qCoff);
 267                        ath_dbg(common, CALIBRATE,
 268                                "Register offset (0x%04x) before update = 0x%x\n",
 269                                offset_array[i],
 270                                REG_READ(ah, offset_array[i]));
 271
 272                        if (AR_SREV_9565(ah) &&
 273                            (iCoff == 63 || qCoff == 63 ||
 274                             iCoff == -63 || qCoff == -63))
 275                                return;
 276
 277                        REG_RMW_FIELD(ah, offset_array[i],
 278                                      AR_PHY_RX_IQCAL_CORR_IQCORR_Q_I_COFF,
 279                                      iCoff);
 280                        REG_RMW_FIELD(ah, offset_array[i],
 281                                      AR_PHY_RX_IQCAL_CORR_IQCORR_Q_Q_COFF,
 282                                      qCoff);
 283                        ath_dbg(common, CALIBRATE,
 284                                "Register offset (0x%04x) QI COFF (bitfields 0x%08x) after update = 0x%x\n",
 285                                offset_array[i],
 286                                AR_PHY_RX_IQCAL_CORR_IQCORR_Q_I_COFF,
 287                                REG_READ(ah, offset_array[i]));
 288                        ath_dbg(common, CALIBRATE,
 289                                "Register offset (0x%04x) QQ COFF (bitfields 0x%08x) after update = 0x%x\n",
 290                                offset_array[i],
 291                                AR_PHY_RX_IQCAL_CORR_IQCORR_Q_Q_COFF,
 292                                REG_READ(ah, offset_array[i]));
 293
 294                        ath_dbg(common, CALIBRATE,
 295                                "IQ Cal and Correction done for Chain %d\n", i);
 296                }
 297        }
 298
 299        REG_SET_BIT(ah, AR_PHY_RX_IQCAL_CORR_B0,
 300                    AR_PHY_RX_IQCAL_CORR_IQCORR_ENABLE);
 301        ath_dbg(common, CALIBRATE,
 302                "IQ Cal and Correction (offset 0x%04x) enabled (bit position 0x%08x). New Value 0x%08x\n",
 303                (unsigned) (AR_PHY_RX_IQCAL_CORR_B0),
 304                AR_PHY_RX_IQCAL_CORR_IQCORR_ENABLE,
 305                REG_READ(ah, AR_PHY_RX_IQCAL_CORR_B0));
 306}
 307
 308static const struct ath9k_percal_data iq_cal_single_sample = {
 309        IQ_MISMATCH_CAL,
 310        MIN_CAL_SAMPLES,
 311        PER_MAX_LOG_COUNT,
 312        ar9003_hw_iqcal_collect,
 313        ar9003_hw_iqcalibrate
 314};
 315
 316static void ar9003_hw_init_cal_settings(struct ath_hw *ah)
 317{
 318        ah->iq_caldata.calData = &iq_cal_single_sample;
 319
 320        if (AR_SREV_9300_20_OR_LATER(ah)) {
 321                ah->enabled_cals |= TX_IQ_CAL;
 322                if (AR_SREV_9485_OR_LATER(ah) && !AR_SREV_9340(ah))
 323                        ah->enabled_cals |= TX_IQ_ON_AGC_CAL;
 324        }
 325
 326        ah->supp_cals = IQ_MISMATCH_CAL;
 327}
 328
 329/*
 330 * solve 4x4 linear equation used in loopback iq cal.
 331 */
 332static bool ar9003_hw_solve_iq_cal(struct ath_hw *ah,
 333                                   s32 sin_2phi_1,
 334                                   s32 cos_2phi_1,
 335                                   s32 sin_2phi_2,
 336                                   s32 cos_2phi_2,
 337                                   s32 mag_a0_d0,
 338                                   s32 phs_a0_d0,
 339                                   s32 mag_a1_d0,
 340                                   s32 phs_a1_d0,
 341                                   s32 solved_eq[])
 342{
 343        s32 f1 = cos_2phi_1 - cos_2phi_2,
 344            f3 = sin_2phi_1 - sin_2phi_2,
 345            f2;
 346        s32 mag_tx, phs_tx, mag_rx, phs_rx;
 347        const s32 result_shift = 1 << 15;
 348        struct ath_common *common = ath9k_hw_common(ah);
 349
 350        f2 = (f1 * f1 + f3 * f3) / result_shift;
 351
 352        if (!f2) {
 353                ath_dbg(common, CALIBRATE, "Divide by 0\n");
 354                return false;
 355        }
 356
 357        /* mag mismatch, tx */
 358        mag_tx = f1 * (mag_a0_d0  - mag_a1_d0) + f3 * (phs_a0_d0 - phs_a1_d0);
 359        /* phs mismatch, tx */
 360        phs_tx = f3 * (-mag_a0_d0 + mag_a1_d0) + f1 * (phs_a0_d0 - phs_a1_d0);
 361
 362        mag_tx = (mag_tx / f2);
 363        phs_tx = (phs_tx / f2);
 364
 365        /* mag mismatch, rx */
 366        mag_rx = mag_a0_d0 - (cos_2phi_1 * mag_tx + sin_2phi_1 * phs_tx) /
 367                 result_shift;
 368        /* phs mismatch, rx */
 369        phs_rx = phs_a0_d0 + (sin_2phi_1 * mag_tx - cos_2phi_1 * phs_tx) /
 370                 result_shift;
 371
 372        solved_eq[0] = mag_tx;
 373        solved_eq[1] = phs_tx;
 374        solved_eq[2] = mag_rx;
 375        solved_eq[3] = phs_rx;
 376
 377        return true;
 378}
 379
 380static s32 ar9003_hw_find_mag_approx(struct ath_hw *ah, s32 in_re, s32 in_im)
 381{
 382        s32 abs_i = abs(in_re),
 383            abs_q = abs(in_im),
 384            max_abs, min_abs;
 385
 386        if (abs_i > abs_q) {
 387                max_abs = abs_i;
 388                min_abs = abs_q;
 389        } else {
 390                max_abs = abs_q;
 391                min_abs = abs_i;
 392        }
 393
 394        return max_abs - (max_abs / 32) + (min_abs / 8) + (min_abs / 4);
 395}
 396
 397#define DELPT 32
 398
 399static bool ar9003_hw_calc_iq_corr(struct ath_hw *ah,
 400                                   s32 chain_idx,
 401                                   const s32 iq_res[],
 402                                   s32 iqc_coeff[])
 403{
 404        s32 i2_m_q2_a0_d0, i2_p_q2_a0_d0, iq_corr_a0_d0,
 405            i2_m_q2_a0_d1, i2_p_q2_a0_d1, iq_corr_a0_d1,
 406            i2_m_q2_a1_d0, i2_p_q2_a1_d0, iq_corr_a1_d0,
 407            i2_m_q2_a1_d1, i2_p_q2_a1_d1, iq_corr_a1_d1;
 408        s32 mag_a0_d0, mag_a1_d0, mag_a0_d1, mag_a1_d1,
 409            phs_a0_d0, phs_a1_d0, phs_a0_d1, phs_a1_d1,
 410            sin_2phi_1, cos_2phi_1,
 411            sin_2phi_2, cos_2phi_2;
 412        s32 mag_tx, phs_tx, mag_rx, phs_rx;
 413        s32 solved_eq[4], mag_corr_tx, phs_corr_tx, mag_corr_rx, phs_corr_rx,
 414            q_q_coff, q_i_coff;
 415        const s32 res_scale = 1 << 15;
 416        const s32 delpt_shift = 1 << 8;
 417        s32 mag1, mag2;
 418        struct ath_common *common = ath9k_hw_common(ah);
 419
 420        i2_m_q2_a0_d0 = iq_res[0] & 0xfff;
 421        i2_p_q2_a0_d0 = (iq_res[0] >> 12) & 0xfff;
 422        iq_corr_a0_d0 = ((iq_res[0] >> 24) & 0xff) + ((iq_res[1] & 0xf) << 8);
 423
 424        if (i2_m_q2_a0_d0 > 0x800)
 425                i2_m_q2_a0_d0 = -((0xfff - i2_m_q2_a0_d0) + 1);
 426
 427        if (i2_p_q2_a0_d0 > 0x800)
 428                i2_p_q2_a0_d0 = -((0xfff - i2_p_q2_a0_d0) + 1);
 429
 430        if (iq_corr_a0_d0 > 0x800)
 431                iq_corr_a0_d0 = -((0xfff - iq_corr_a0_d0) + 1);
 432
 433        i2_m_q2_a0_d1 = (iq_res[1] >> 4) & 0xfff;
 434        i2_p_q2_a0_d1 = (iq_res[2] & 0xfff);
 435        iq_corr_a0_d1 = (iq_res[2] >> 12) & 0xfff;
 436
 437        if (i2_m_q2_a0_d1 > 0x800)
 438                i2_m_q2_a0_d1 = -((0xfff - i2_m_q2_a0_d1) + 1);
 439
 440        if (i2_p_q2_a0_d1 > 0x800)
 441                i2_p_q2_a0_d1 = -((0xfff - i2_p_q2_a0_d1) + 1);
 442
 443        if (iq_corr_a0_d1 > 0x800)
 444                iq_corr_a0_d1 = -((0xfff - iq_corr_a0_d1) + 1);
 445
 446        i2_m_q2_a1_d0 = ((iq_res[2] >> 24) & 0xff) + ((iq_res[3] & 0xf) << 8);
 447        i2_p_q2_a1_d0 = (iq_res[3] >> 4) & 0xfff;
 448        iq_corr_a1_d0 = iq_res[4] & 0xfff;
 449
 450        if (i2_m_q2_a1_d0 > 0x800)
 451                i2_m_q2_a1_d0 = -((0xfff - i2_m_q2_a1_d0) + 1);
 452
 453        if (i2_p_q2_a1_d0 > 0x800)
 454                i2_p_q2_a1_d0 = -((0xfff - i2_p_q2_a1_d0) + 1);
 455
 456        if (iq_corr_a1_d0 > 0x800)
 457                iq_corr_a1_d0 = -((0xfff - iq_corr_a1_d0) + 1);
 458
 459        i2_m_q2_a1_d1 = (iq_res[4] >> 12) & 0xfff;
 460        i2_p_q2_a1_d1 = ((iq_res[4] >> 24) & 0xff) + ((iq_res[5] & 0xf) << 8);
 461        iq_corr_a1_d1 = (iq_res[5] >> 4) & 0xfff;
 462
 463        if (i2_m_q2_a1_d1 > 0x800)
 464                i2_m_q2_a1_d1 = -((0xfff - i2_m_q2_a1_d1) + 1);
 465
 466        if (i2_p_q2_a1_d1 > 0x800)
 467                i2_p_q2_a1_d1 = -((0xfff - i2_p_q2_a1_d1) + 1);
 468
 469        if (iq_corr_a1_d1 > 0x800)
 470                iq_corr_a1_d1 = -((0xfff - iq_corr_a1_d1) + 1);
 471
 472        if ((i2_p_q2_a0_d0 == 0) || (i2_p_q2_a0_d1 == 0) ||
 473            (i2_p_q2_a1_d0 == 0) || (i2_p_q2_a1_d1 == 0)) {
 474                ath_dbg(common, CALIBRATE,
 475                        "Divide by 0:\n"
 476                        "a0_d0=%d\n"
 477                        "a0_d1=%d\n"
 478                        "a2_d0=%d\n"
 479                        "a1_d1=%d\n",
 480                        i2_p_q2_a0_d0, i2_p_q2_a0_d1,
 481                        i2_p_q2_a1_d0, i2_p_q2_a1_d1);
 482                return false;
 483        }
 484
 485        mag_a0_d0 = (i2_m_q2_a0_d0 * res_scale) / i2_p_q2_a0_d0;
 486        phs_a0_d0 = (iq_corr_a0_d0 * res_scale) / i2_p_q2_a0_d0;
 487
 488        mag_a0_d1 = (i2_m_q2_a0_d1 * res_scale) / i2_p_q2_a0_d1;
 489        phs_a0_d1 = (iq_corr_a0_d1 * res_scale) / i2_p_q2_a0_d1;
 490
 491        mag_a1_d0 = (i2_m_q2_a1_d0 * res_scale) / i2_p_q2_a1_d0;
 492        phs_a1_d0 = (iq_corr_a1_d0 * res_scale) / i2_p_q2_a1_d0;
 493
 494        mag_a1_d1 = (i2_m_q2_a1_d1 * res_scale) / i2_p_q2_a1_d1;
 495        phs_a1_d1 = (iq_corr_a1_d1 * res_scale) / i2_p_q2_a1_d1;
 496
 497        /* w/o analog phase shift */
 498        sin_2phi_1 = (((mag_a0_d0 - mag_a0_d1) * delpt_shift) / DELPT);
 499        /* w/o analog phase shift */
 500        cos_2phi_1 = (((phs_a0_d1 - phs_a0_d0) * delpt_shift) / DELPT);
 501        /* w/  analog phase shift */
 502        sin_2phi_2 = (((mag_a1_d0 - mag_a1_d1) * delpt_shift) / DELPT);
 503        /* w/  analog phase shift */
 504        cos_2phi_2 = (((phs_a1_d1 - phs_a1_d0) * delpt_shift) / DELPT);
 505
 506        /*
 507         * force sin^2 + cos^2 = 1;
 508         * find magnitude by approximation
 509         */
 510        mag1 = ar9003_hw_find_mag_approx(ah, cos_2phi_1, sin_2phi_1);
 511        mag2 = ar9003_hw_find_mag_approx(ah, cos_2phi_2, sin_2phi_2);
 512
 513        if ((mag1 == 0) || (mag2 == 0)) {
 514                ath_dbg(common, CALIBRATE, "Divide by 0: mag1=%d, mag2=%d\n",
 515                        mag1, mag2);
 516                return false;
 517        }
 518
 519        /* normalization sin and cos by mag */
 520        sin_2phi_1 = (sin_2phi_1 * res_scale / mag1);
 521        cos_2phi_1 = (cos_2phi_1 * res_scale / mag1);
 522        sin_2phi_2 = (sin_2phi_2 * res_scale / mag2);
 523        cos_2phi_2 = (cos_2phi_2 * res_scale / mag2);
 524
 525        /* calculate IQ mismatch */
 526        if (!ar9003_hw_solve_iq_cal(ah,
 527                             sin_2phi_1, cos_2phi_1,
 528                             sin_2phi_2, cos_2phi_2,
 529                             mag_a0_d0, phs_a0_d0,
 530                             mag_a1_d0,
 531                             phs_a1_d0, solved_eq)) {
 532                ath_dbg(common, CALIBRATE,
 533                        "Call to ar9003_hw_solve_iq_cal() failed\n");
 534                return false;
 535        }
 536
 537        mag_tx = solved_eq[0];
 538        phs_tx = solved_eq[1];
 539        mag_rx = solved_eq[2];
 540        phs_rx = solved_eq[3];
 541
 542        ath_dbg(common, CALIBRATE,
 543                "chain %d: mag mismatch=%d phase mismatch=%d\n",
 544                chain_idx, mag_tx/res_scale, phs_tx/res_scale);
 545
 546        if (res_scale == mag_tx) {
 547                ath_dbg(common, CALIBRATE,
 548                        "Divide by 0: mag_tx=%d, res_scale=%d\n",
 549                        mag_tx, res_scale);
 550                return false;
 551        }
 552
 553        /* calculate and quantize Tx IQ correction factor */
 554        mag_corr_tx = (mag_tx * res_scale) / (res_scale - mag_tx);
 555        phs_corr_tx = -phs_tx;
 556
 557        q_q_coff = (mag_corr_tx * 128 / res_scale);
 558        q_i_coff = (phs_corr_tx * 256 / res_scale);
 559
 560        ath_dbg(common, CALIBRATE, "tx chain %d: mag corr=%d  phase corr=%d\n",
 561                chain_idx, q_q_coff, q_i_coff);
 562
 563        if (q_i_coff < -63)
 564                q_i_coff = -63;
 565        if (q_i_coff > 63)
 566                q_i_coff = 63;
 567        if (q_q_coff < -63)
 568                q_q_coff = -63;
 569        if (q_q_coff > 63)
 570                q_q_coff = 63;
 571
 572        iqc_coeff[0] = (q_q_coff * 128) + q_i_coff;
 573
 574        ath_dbg(common, CALIBRATE, "tx chain %d: iq corr coeff=%x\n",
 575                chain_idx, iqc_coeff[0]);
 576
 577        if (-mag_rx == res_scale) {
 578                ath_dbg(common, CALIBRATE,
 579                        "Divide by 0: mag_rx=%d, res_scale=%d\n",
 580                        mag_rx, res_scale);
 581                return false;
 582        }
 583
 584        /* calculate and quantize Rx IQ correction factors */
 585        mag_corr_rx = (-mag_rx * res_scale) / (res_scale + mag_rx);
 586        phs_corr_rx = -phs_rx;
 587
 588        q_q_coff = (mag_corr_rx * 128 / res_scale);
 589        q_i_coff = (phs_corr_rx * 256 / res_scale);
 590
 591        ath_dbg(common, CALIBRATE, "rx chain %d: mag corr=%d  phase corr=%d\n",
 592                chain_idx, q_q_coff, q_i_coff);
 593
 594        if (q_i_coff < -63)
 595                q_i_coff = -63;
 596        if (q_i_coff > 63)
 597                q_i_coff = 63;
 598        if (q_q_coff < -63)
 599                q_q_coff = -63;
 600        if (q_q_coff > 63)
 601                q_q_coff = 63;
 602
 603        iqc_coeff[1] = (q_q_coff * 128) + q_i_coff;
 604
 605        ath_dbg(common, CALIBRATE, "rx chain %d: iq corr coeff=%x\n",
 606                chain_idx, iqc_coeff[1]);
 607
 608        return true;
 609}
 610
 611static void ar9003_hw_detect_outlier(int *mp_coeff, int nmeasurement,
 612                                     int max_delta)
 613{
 614        int mp_max = -64, max_idx = 0;
 615        int mp_min = 63, min_idx = 0;
 616        int mp_avg = 0, i, outlier_idx = 0, mp_count = 0;
 617
 618        /* find min/max mismatch across all calibrated gains */
 619        for (i = 0; i < nmeasurement; i++) {
 620                if (mp_coeff[i] > mp_max) {
 621                        mp_max = mp_coeff[i];
 622                        max_idx = i;
 623                } else if (mp_coeff[i] < mp_min) {
 624                        mp_min = mp_coeff[i];
 625                        min_idx = i;
 626                }
 627        }
 628
 629        /* find average (exclude max abs value) */
 630        for (i = 0; i < nmeasurement; i++) {
 631                if ((abs(mp_coeff[i]) < abs(mp_max)) ||
 632                    (abs(mp_coeff[i]) < abs(mp_min))) {
 633                        mp_avg += mp_coeff[i];
 634                        mp_count++;
 635                }
 636        }
 637
 638        /*
 639         * finding mean magnitude/phase if possible, otherwise
 640         * just use the last value as the mean
 641         */
 642        if (mp_count)
 643                mp_avg /= mp_count;
 644        else
 645                mp_avg = mp_coeff[nmeasurement - 1];
 646
 647        /* detect outlier */
 648        if (abs(mp_max - mp_min) > max_delta) {
 649                if (abs(mp_max - mp_avg) > abs(mp_min - mp_avg))
 650                        outlier_idx = max_idx;
 651                else
 652                        outlier_idx = min_idx;
 653
 654                mp_coeff[outlier_idx] = mp_avg;
 655        }
 656}
 657
 658static void ar9003_hw_tx_iqcal_load_avg_2_passes(struct ath_hw *ah,
 659                                                 struct coeff *coeff,
 660                                                 bool is_reusable)
 661{
 662        int i, im, nmeasurement;
 663        u32 tx_corr_coeff[MAX_MEASUREMENT][AR9300_MAX_CHAINS];
 664        struct ath9k_hw_cal_data *caldata = ah->caldata;
 665
 666        memset(tx_corr_coeff, 0, sizeof(tx_corr_coeff));
 667        for (i = 0; i < MAX_MEASUREMENT / 2; i++) {
 668                tx_corr_coeff[i * 2][0] = tx_corr_coeff[(i * 2) + 1][0] =
 669                                        AR_PHY_TX_IQCAL_CORR_COEFF_B0(i);
 670                if (!AR_SREV_9485(ah)) {
 671                        tx_corr_coeff[i * 2][1] =
 672                        tx_corr_coeff[(i * 2) + 1][1] =
 673                                        AR_PHY_TX_IQCAL_CORR_COEFF_B1(i);
 674
 675                        tx_corr_coeff[i * 2][2] =
 676                        tx_corr_coeff[(i * 2) + 1][2] =
 677                                        AR_PHY_TX_IQCAL_CORR_COEFF_B2(i);
 678                }
 679        }
 680
 681        /* Load the average of 2 passes */
 682        for (i = 0; i < AR9300_MAX_CHAINS; i++) {
 683                if (!(ah->txchainmask & (1 << i)))
 684                        continue;
 685                nmeasurement = REG_READ_FIELD(ah,
 686                                AR_PHY_TX_IQCAL_STATUS_B0,
 687                                AR_PHY_CALIBRATED_GAINS_0);
 688
 689                if (nmeasurement > MAX_MEASUREMENT)
 690                        nmeasurement = MAX_MEASUREMENT;
 691
 692                /* detect outlier only if nmeasurement > 1 */
 693                if (nmeasurement > 1) {
 694                        /* Detect magnitude outlier */
 695                        ar9003_hw_detect_outlier(coeff->mag_coeff[i],
 696                                        nmeasurement, MAX_MAG_DELTA);
 697
 698                        /* Detect phase outlier */
 699                        ar9003_hw_detect_outlier(coeff->phs_coeff[i],
 700                                        nmeasurement, MAX_PHS_DELTA);
 701                }
 702
 703                for (im = 0; im < nmeasurement; im++) {
 704
 705                        coeff->iqc_coeff[0] = (coeff->mag_coeff[i][im] & 0x7f) |
 706                                ((coeff->phs_coeff[i][im] & 0x7f) << 7);
 707
 708                        if ((im % 2) == 0)
 709                                REG_RMW_FIELD(ah, tx_corr_coeff[im][i],
 710                                        AR_PHY_TX_IQCAL_CORR_COEFF_00_COEFF_TABLE,
 711                                        coeff->iqc_coeff[0]);
 712                        else
 713                                REG_RMW_FIELD(ah, tx_corr_coeff[im][i],
 714                                        AR_PHY_TX_IQCAL_CORR_COEFF_01_COEFF_TABLE,
 715                                        coeff->iqc_coeff[0]);
 716
 717                        if (caldata)
 718                                caldata->tx_corr_coeff[im][i] =
 719                                        coeff->iqc_coeff[0];
 720                }
 721                if (caldata)
 722                        caldata->num_measures[i] = nmeasurement;
 723        }
 724
 725        REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_3,
 726                      AR_PHY_TX_IQCAL_CONTROL_3_IQCORR_EN, 0x1);
 727        REG_RMW_FIELD(ah, AR_PHY_RX_IQCAL_CORR_B0,
 728                      AR_PHY_RX_IQCAL_CORR_B0_LOOPBACK_IQCORR_EN, 0x1);
 729
 730        if (caldata)
 731                caldata->done_txiqcal_once = is_reusable;
 732
 733        return;
 734}
 735
 736static bool ar9003_hw_tx_iq_cal_run(struct ath_hw *ah)
 737{
 738        struct ath_common *common = ath9k_hw_common(ah);
 739        u8 tx_gain_forced;
 740
 741        tx_gain_forced = REG_READ_FIELD(ah, AR_PHY_TX_FORCED_GAIN,
 742                                        AR_PHY_TXGAIN_FORCE);
 743        if (tx_gain_forced)
 744                REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN,
 745                              AR_PHY_TXGAIN_FORCE, 0);
 746
 747        REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_START,
 748                      AR_PHY_TX_IQCAL_START_DO_CAL, 1);
 749
 750        if (!ath9k_hw_wait(ah, AR_PHY_TX_IQCAL_START,
 751                        AR_PHY_TX_IQCAL_START_DO_CAL, 0,
 752                        AH_WAIT_TIMEOUT)) {
 753                ath_dbg(common, CALIBRATE, "Tx IQ Cal is not completed\n");
 754                return false;
 755        }
 756        return true;
 757}
 758
 759static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah, bool is_reusable)
 760{
 761        struct ath_common *common = ath9k_hw_common(ah);
 762        const u32 txiqcal_status[AR9300_MAX_CHAINS] = {
 763                AR_PHY_TX_IQCAL_STATUS_B0,
 764                AR_PHY_TX_IQCAL_STATUS_B1,
 765                AR_PHY_TX_IQCAL_STATUS_B2,
 766        };
 767        const u_int32_t chan_info_tab[] = {
 768                AR_PHY_CHAN_INFO_TAB_0,
 769                AR_PHY_CHAN_INFO_TAB_1,
 770                AR_PHY_CHAN_INFO_TAB_2,
 771        };
 772        struct coeff coeff;
 773        s32 iq_res[6];
 774        int i, im, j;
 775        int nmeasurement;
 776
 777        for (i = 0; i < AR9300_MAX_CHAINS; i++) {
 778                if (!(ah->txchainmask & (1 << i)))
 779                        continue;
 780
 781                nmeasurement = REG_READ_FIELD(ah,
 782                                AR_PHY_TX_IQCAL_STATUS_B0,
 783                                AR_PHY_CALIBRATED_GAINS_0);
 784                if (nmeasurement > MAX_MEASUREMENT)
 785                        nmeasurement = MAX_MEASUREMENT;
 786
 787                for (im = 0; im < nmeasurement; im++) {
 788                        ath_dbg(common, CALIBRATE,
 789                                "Doing Tx IQ Cal for chain %d\n", i);
 790
 791                        if (REG_READ(ah, txiqcal_status[i]) &
 792                                        AR_PHY_TX_IQCAL_STATUS_FAILED) {
 793                                ath_dbg(common, CALIBRATE,
 794                                        "Tx IQ Cal failed for chain %d\n", i);
 795                                goto tx_iqcal_fail;
 796                        }
 797
 798                        for (j = 0; j < 3; j++) {
 799                                u32 idx = 2 * j, offset = 4 * (3 * im + j);
 800
 801                                REG_RMW_FIELD(ah,
 802                                                AR_PHY_CHAN_INFO_MEMORY,
 803                                                AR_PHY_CHAN_INFO_TAB_S2_READ,
 804                                                0);
 805
 806                                /* 32 bits */
 807                                iq_res[idx] = REG_READ(ah,
 808                                                chan_info_tab[i] +
 809                                                offset);
 810
 811                                REG_RMW_FIELD(ah,
 812                                                AR_PHY_CHAN_INFO_MEMORY,
 813                                                AR_PHY_CHAN_INFO_TAB_S2_READ,
 814                                                1);
 815
 816                                /* 16 bits */
 817                                iq_res[idx + 1] = 0xffff & REG_READ(ah,
 818                                                chan_info_tab[i] + offset);
 819
 820                                ath_dbg(common, CALIBRATE,
 821                                        "IQ_RES[%d]=0x%x IQ_RES[%d]=0x%x\n",
 822                                        idx, iq_res[idx], idx + 1,
 823                                        iq_res[idx + 1]);
 824                        }
 825
 826                        if (!ar9003_hw_calc_iq_corr(ah, i, iq_res,
 827                                                coeff.iqc_coeff)) {
 828                                ath_dbg(common, CALIBRATE,
 829                                        "Failed in calculation of IQ correction\n");
 830                                goto tx_iqcal_fail;
 831                        }
 832
 833                        coeff.mag_coeff[i][im] = coeff.iqc_coeff[0] & 0x7f;
 834                        coeff.phs_coeff[i][im] =
 835                                (coeff.iqc_coeff[0] >> 7) & 0x7f;
 836
 837                        if (coeff.mag_coeff[i][im] > 63)
 838                                coeff.mag_coeff[i][im] -= 128;
 839                        if (coeff.phs_coeff[i][im] > 63)
 840                                coeff.phs_coeff[i][im] -= 128;
 841                }
 842        }
 843        ar9003_hw_tx_iqcal_load_avg_2_passes(ah, &coeff, is_reusable);
 844
 845        return;
 846
 847tx_iqcal_fail:
 848        ath_dbg(common, CALIBRATE, "Tx IQ Cal failed\n");
 849        return;
 850}
 851
 852static void ar9003_hw_tx_iq_cal_reload(struct ath_hw *ah)
 853{
 854        struct ath9k_hw_cal_data *caldata = ah->caldata;
 855        u32 tx_corr_coeff[MAX_MEASUREMENT][AR9300_MAX_CHAINS];
 856        int i, im;
 857
 858        memset(tx_corr_coeff, 0, sizeof(tx_corr_coeff));
 859        for (i = 0; i < MAX_MEASUREMENT / 2; i++) {
 860                tx_corr_coeff[i * 2][0] = tx_corr_coeff[(i * 2) + 1][0] =
 861                                        AR_PHY_TX_IQCAL_CORR_COEFF_B0(i);
 862                if (!AR_SREV_9485(ah)) {
 863                        tx_corr_coeff[i * 2][1] =
 864                        tx_corr_coeff[(i * 2) + 1][1] =
 865                                        AR_PHY_TX_IQCAL_CORR_COEFF_B1(i);
 866
 867                        tx_corr_coeff[i * 2][2] =
 868                        tx_corr_coeff[(i * 2) + 1][2] =
 869                                        AR_PHY_TX_IQCAL_CORR_COEFF_B2(i);
 870                }
 871        }
 872
 873        for (i = 0; i < AR9300_MAX_CHAINS; i++) {
 874                if (!(ah->txchainmask & (1 << i)))
 875                        continue;
 876
 877                for (im = 0; im < caldata->num_measures[i]; im++) {
 878                        if ((im % 2) == 0)
 879                                REG_RMW_FIELD(ah, tx_corr_coeff[im][i],
 880                                     AR_PHY_TX_IQCAL_CORR_COEFF_00_COEFF_TABLE,
 881                                     caldata->tx_corr_coeff[im][i]);
 882                        else
 883                                REG_RMW_FIELD(ah, tx_corr_coeff[im][i],
 884                                     AR_PHY_TX_IQCAL_CORR_COEFF_01_COEFF_TABLE,
 885                                     caldata->tx_corr_coeff[im][i]);
 886                }
 887        }
 888
 889        REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_3,
 890                      AR_PHY_TX_IQCAL_CONTROL_3_IQCORR_EN, 0x1);
 891        REG_RMW_FIELD(ah, AR_PHY_RX_IQCAL_CORR_B0,
 892                      AR_PHY_RX_IQCAL_CORR_B0_LOOPBACK_IQCORR_EN, 0x1);
 893}
 894
 895static void ar9003_hw_manual_peak_cal(struct ath_hw *ah, u8 chain, bool is_2g)
 896{
 897        int offset[8], total = 0, test;
 898        int agc_out, i;
 899
 900        REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_GAINSTAGES(chain),
 901                      AR_PHY_65NM_RXRF_GAINSTAGES_RX_OVERRIDE, 0x1);
 902        REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_GAINSTAGES(chain),
 903                      AR_PHY_65NM_RXRF_GAINSTAGES_LNAON_CALDC, 0x0);
 904        if (is_2g)
 905                REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_GAINSTAGES(chain),
 906                              AR_PHY_65NM_RXRF_GAINSTAGES_LNA2G_GAIN_OVR, 0x0);
 907        else
 908                REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_GAINSTAGES(chain),
 909                              AR_PHY_65NM_RXRF_GAINSTAGES_LNA5G_GAIN_OVR, 0x0);
 910
 911        REG_RMW_FIELD(ah, AR_PHY_65NM_RXTX2(chain),
 912                      AR_PHY_65NM_RXTX2_RXON_OVR, 0x1);
 913        REG_RMW_FIELD(ah, AR_PHY_65NM_RXTX2(chain),
 914                      AR_PHY_65NM_RXTX2_RXON, 0x0);
 915
 916        REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
 917                      AR_PHY_65NM_RXRF_AGC_AGC_OVERRIDE, 0x1);
 918        REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
 919                      AR_PHY_65NM_RXRF_AGC_AGC_ON_OVR, 0x1);
 920        REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
 921                      AR_PHY_65NM_RXRF_AGC_AGC_CAL_OVR, 0x1);
 922        if (is_2g)
 923                REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
 924                              AR_PHY_65NM_RXRF_AGC_AGC2G_DBDAC_OVR, 0x0);
 925        else
 926                REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
 927                              AR_PHY_65NM_RXRF_AGC_AGC5G_DBDAC_OVR, 0x0);
 928
 929        for (i = 6; i > 0; i--) {
 930                offset[i] = BIT(i - 1);
 931                test = total + offset[i];
 932
 933                if (is_2g)
 934                        REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
 935                                      AR_PHY_65NM_RXRF_AGC_AGC2G_CALDAC_OVR,
 936                                      test);
 937                else
 938                        REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
 939                                      AR_PHY_65NM_RXRF_AGC_AGC5G_CALDAC_OVR,
 940                                      test);
 941                udelay(100);
 942                agc_out = REG_READ_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
 943                                         AR_PHY_65NM_RXRF_AGC_AGC_OUT);
 944                offset[i] = (agc_out) ? 0 : 1;
 945                total += (offset[i] << (i - 1));
 946        }
 947
 948        if (is_2g)
 949                REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
 950                              AR_PHY_65NM_RXRF_AGC_AGC2G_CALDAC_OVR, total);
 951        else
 952                REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
 953                              AR_PHY_65NM_RXRF_AGC_AGC5G_CALDAC_OVR, total);
 954
 955        REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_GAINSTAGES(chain),
 956                      AR_PHY_65NM_RXRF_GAINSTAGES_RX_OVERRIDE, 0);
 957        REG_RMW_FIELD(ah, AR_PHY_65NM_RXTX2(chain),
 958                      AR_PHY_65NM_RXTX2_RXON_OVR, 0);
 959        REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
 960                      AR_PHY_65NM_RXRF_AGC_AGC_CAL_OVR, 0);
 961}
 962
 963static void ar9003_hw_do_manual_peak_cal(struct ath_hw *ah,
 964                                         struct ath9k_channel *chan)
 965{
 966        int i;
 967
 968        if (!AR_SREV_9462(ah) && !AR_SREV_9565(ah) && !AR_SREV_9485(ah))
 969                return;
 970
 971        for (i = 0; i < AR9300_MAX_CHAINS; i++) {
 972                if (!(ah->rxchainmask & (1 << i)))
 973                        continue;
 974                ar9003_hw_manual_peak_cal(ah, i, IS_CHAN_2GHZ(chan));
 975        }
 976}
 977
 978static void ar9003_hw_cl_cal_post_proc(struct ath_hw *ah, bool is_reusable)
 979{
 980        u32 cl_idx[AR9300_MAX_CHAINS] = { AR_PHY_CL_TAB_0,
 981                                          AR_PHY_CL_TAB_1,
 982                                          AR_PHY_CL_TAB_2 };
 983        struct ath9k_hw_cal_data *caldata = ah->caldata;
 984        bool txclcal_done = false;
 985        int i, j;
 986
 987        if (!caldata || !(ah->enabled_cals & TX_CL_CAL))
 988                return;
 989
 990        txclcal_done = !!(REG_READ(ah, AR_PHY_AGC_CONTROL) &
 991                          AR_PHY_AGC_CONTROL_CLC_SUCCESS);
 992
 993        if (caldata->done_txclcal_once) {
 994                for (i = 0; i < AR9300_MAX_CHAINS; i++) {
 995                        if (!(ah->txchainmask & (1 << i)))
 996                                continue;
 997                        for (j = 0; j < MAX_CL_TAB_ENTRY; j++)
 998                                REG_WRITE(ah, CL_TAB_ENTRY(cl_idx[i]),
 999                                          caldata->tx_clcal[i][j]);
1000                }
1001        } else if (is_reusable && txclcal_done) {
1002                for (i = 0; i < AR9300_MAX_CHAINS; i++) {
1003                        if (!(ah->txchainmask & (1 << i)))
1004                                continue;
1005                        for (j = 0; j < MAX_CL_TAB_ENTRY; j++)
1006                                caldata->tx_clcal[i][j] =
1007                                        REG_READ(ah, CL_TAB_ENTRY(cl_idx[i]));
1008                }
1009                caldata->done_txclcal_once = true;
1010        }
1011}
1012
1013static bool ar9003_hw_init_cal(struct ath_hw *ah,
1014                               struct ath9k_channel *chan)
1015{
1016        struct ath_common *common = ath9k_hw_common(ah);
1017        struct ath9k_hw_cal_data *caldata = ah->caldata;
1018        bool txiqcal_done = false;
1019        bool is_reusable = true, status = true;
1020        bool run_rtt_cal = false, run_agc_cal, sep_iq_cal = false;
1021        bool rtt = !!(ah->caps.hw_caps & ATH9K_HW_CAP_RTT);
1022        u32 agc_ctrl = 0, agc_supp_cals = AR_PHY_AGC_CONTROL_OFFSET_CAL |
1023                                          AR_PHY_AGC_CONTROL_FLTR_CAL   |
1024                                          AR_PHY_AGC_CONTROL_PKDET_CAL;
1025
1026        /* Use chip chainmask only for calibration */
1027        ar9003_hw_set_chain_masks(ah, ah->caps.rx_chainmask, ah->caps.tx_chainmask);
1028
1029        if (rtt) {
1030                if (!ar9003_hw_rtt_restore(ah, chan))
1031                        run_rtt_cal = true;
1032
1033                if (run_rtt_cal)
1034                        ath_dbg(common, CALIBRATE, "RTT calibration to be done\n");
1035        }
1036
1037        run_agc_cal = run_rtt_cal;
1038
1039        if (run_rtt_cal) {
1040                ar9003_hw_rtt_enable(ah);
1041                ar9003_hw_rtt_set_mask(ah, 0x00);
1042                ar9003_hw_rtt_clear_hist(ah);
1043        }
1044
1045        if (rtt && !run_rtt_cal) {
1046                agc_ctrl = REG_READ(ah, AR_PHY_AGC_CONTROL);
1047                agc_supp_cals &= agc_ctrl;
1048                agc_ctrl &= ~(AR_PHY_AGC_CONTROL_OFFSET_CAL |
1049                             AR_PHY_AGC_CONTROL_FLTR_CAL |
1050                             AR_PHY_AGC_CONTROL_PKDET_CAL);
1051                REG_WRITE(ah, AR_PHY_AGC_CONTROL, agc_ctrl);
1052        }
1053
1054        if (ah->enabled_cals & TX_CL_CAL) {
1055                if (caldata && caldata->done_txclcal_once)
1056                        REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL,
1057                                    AR_PHY_CL_CAL_ENABLE);
1058                else {
1059                        REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL,
1060                                    AR_PHY_CL_CAL_ENABLE);
1061                        run_agc_cal = true;
1062                }
1063        }
1064
1065        if ((IS_CHAN_HALF_RATE(chan) || IS_CHAN_QUARTER_RATE(chan)) ||
1066            !(ah->enabled_cals & TX_IQ_CAL))
1067                goto skip_tx_iqcal;
1068
1069        /* Do Tx IQ Calibration */
1070        REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_1,
1071                      AR_PHY_TX_IQCAL_CONTROL_1_IQCORR_I_Q_COFF_DELPT,
1072                      DELPT);
1073
1074        /*
1075         * For AR9485 or later chips, TxIQ cal runs as part of
1076         * AGC calibration
1077         */
1078        if (ah->enabled_cals & TX_IQ_ON_AGC_CAL) {
1079                if (caldata && !caldata->done_txiqcal_once)
1080                        REG_SET_BIT(ah, AR_PHY_TX_IQCAL_CONTROL_0,
1081                                    AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL);
1082                else
1083                        REG_CLR_BIT(ah, AR_PHY_TX_IQCAL_CONTROL_0,
1084                                    AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL);
1085                txiqcal_done = run_agc_cal = true;
1086        } else if (caldata && !caldata->done_txiqcal_once) {
1087                run_agc_cal = true;
1088                sep_iq_cal = true;
1089        }
1090
1091skip_tx_iqcal:
1092        if (ath9k_hw_mci_is_enabled(ah) && IS_CHAN_2GHZ(chan) && run_agc_cal)
1093                ar9003_mci_init_cal_req(ah, &is_reusable);
1094
1095        if (sep_iq_cal) {
1096                txiqcal_done = ar9003_hw_tx_iq_cal_run(ah);
1097                REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS);
1098                udelay(5);
1099                REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
1100        }
1101
1102        if (run_agc_cal || !(ah->ah_flags & AH_FASTCC)) {
1103                /* Calibrate the AGC */
1104                REG_WRITE(ah, AR_PHY_AGC_CONTROL,
1105                          REG_READ(ah, AR_PHY_AGC_CONTROL) |
1106                          AR_PHY_AGC_CONTROL_CAL);
1107
1108                /* Poll for offset calibration complete */
1109                status = ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL,
1110                                       AR_PHY_AGC_CONTROL_CAL,
1111                                       0, AH_WAIT_TIMEOUT);
1112
1113                ar9003_hw_do_manual_peak_cal(ah, chan);
1114        }
1115
1116        if (ath9k_hw_mci_is_enabled(ah) && IS_CHAN_2GHZ(chan) && run_agc_cal)
1117                ar9003_mci_init_cal_done(ah);
1118
1119        if (rtt && !run_rtt_cal) {
1120                agc_ctrl |= agc_supp_cals;
1121                REG_WRITE(ah, AR_PHY_AGC_CONTROL, agc_ctrl);
1122        }
1123
1124        if (!status) {
1125                if (run_rtt_cal)
1126                        ar9003_hw_rtt_disable(ah);
1127
1128                ath_dbg(common, CALIBRATE,
1129                        "offset calibration failed to complete in %d ms; noisy environment?\n",
1130                        AH_WAIT_TIMEOUT / 1000);
1131                return false;
1132        }
1133
1134        if (txiqcal_done)
1135                ar9003_hw_tx_iq_cal_post_proc(ah, is_reusable);
1136        else if (caldata && caldata->done_txiqcal_once)
1137                ar9003_hw_tx_iq_cal_reload(ah);
1138
1139        ar9003_hw_cl_cal_post_proc(ah, is_reusable);
1140
1141        if (run_rtt_cal && caldata) {
1142                if (is_reusable) {
1143                        if (!ath9k_hw_rfbus_req(ah))
1144                                ath_err(ath9k_hw_common(ah),
1145                                        "Could not stop baseband\n");
1146                        else
1147                                ar9003_hw_rtt_fill_hist(ah);
1148
1149                        ath9k_hw_rfbus_done(ah);
1150                }
1151
1152                ar9003_hw_rtt_disable(ah);
1153        }
1154
1155        /* Revert chainmask to runtime parameters */
1156        ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask);
1157
1158        /* Initialize list pointers */
1159        ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL;
1160
1161        INIT_CAL(&ah->iq_caldata);
1162        INSERT_CAL(ah, &ah->iq_caldata);
1163        ath_dbg(common, CALIBRATE, "enabling IQ Calibration\n");
1164
1165        /* Initialize current pointer to first element in list */
1166        ah->cal_list_curr = ah->cal_list;
1167
1168        if (ah->cal_list_curr)
1169                ath9k_hw_reset_calibration(ah, ah->cal_list_curr);
1170
1171        if (caldata)
1172                caldata->CalValid = 0;
1173
1174        return true;
1175}
1176
1177void ar9003_hw_attach_calib_ops(struct ath_hw *ah)
1178{
1179        struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
1180        struct ath_hw_ops *ops = ath9k_hw_ops(ah);
1181
1182        priv_ops->init_cal_settings = ar9003_hw_init_cal_settings;
1183        priv_ops->init_cal = ar9003_hw_init_cal;
1184        priv_ops->setup_calibration = ar9003_hw_setup_calibration;
1185
1186        ops->calibrate = ar9003_hw_calibrate;
1187}
1188