linux/drivers/net/wireless/ath/ath9k/calib.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2008-2009 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 "ath9k.h"
  18
  19/* We can tune this as we go by monitoring really low values */
  20#define ATH9K_NF_TOO_LOW        -60
  21
  22/* AR5416 may return very high value (like -31 dBm), in those cases the nf
  23 * is incorrect and we should use the static NF value. Later we can try to
  24 * find out why they are reporting these values */
  25
  26static bool ath9k_hw_nf_in_range(struct ath_hw *ah, s16 nf)
  27{
  28        if (nf > ATH9K_NF_TOO_LOW) {
  29                DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
  30                        "noise floor value detected (%d) is "
  31                        "lower than what we think is a "
  32                        "reasonable value (%d)\n",
  33                        nf, ATH9K_NF_TOO_LOW);
  34                return false;
  35        }
  36        return true;
  37}
  38
  39static int16_t ath9k_hw_get_nf_hist_mid(int16_t *nfCalBuffer)
  40{
  41        int16_t nfval;
  42        int16_t sort[ATH9K_NF_CAL_HIST_MAX];
  43        int i, j;
  44
  45        for (i = 0; i < ATH9K_NF_CAL_HIST_MAX; i++)
  46                sort[i] = nfCalBuffer[i];
  47
  48        for (i = 0; i < ATH9K_NF_CAL_HIST_MAX - 1; i++) {
  49                for (j = 1; j < ATH9K_NF_CAL_HIST_MAX - i; j++) {
  50                        if (sort[j] > sort[j - 1]) {
  51                                nfval = sort[j];
  52                                sort[j] = sort[j - 1];
  53                                sort[j - 1] = nfval;
  54                        }
  55                }
  56        }
  57        nfval = sort[(ATH9K_NF_CAL_HIST_MAX - 1) >> 1];
  58
  59        return nfval;
  60}
  61
  62static void ath9k_hw_update_nfcal_hist_buffer(struct ath9k_nfcal_hist *h,
  63                                              int16_t *nfarray)
  64{
  65        int i;
  66
  67        for (i = 0; i < NUM_NF_READINGS; i++) {
  68                h[i].nfCalBuffer[h[i].currIndex] = nfarray[i];
  69
  70                if (++h[i].currIndex >= ATH9K_NF_CAL_HIST_MAX)
  71                        h[i].currIndex = 0;
  72
  73                if (h[i].invalidNFcount > 0) {
  74                        if (nfarray[i] < AR_PHY_CCA_MIN_BAD_VALUE ||
  75                            nfarray[i] > AR_PHY_CCA_MAX_HIGH_VALUE) {
  76                                h[i].invalidNFcount = ATH9K_NF_CAL_HIST_MAX;
  77                        } else {
  78                                h[i].invalidNFcount--;
  79                                h[i].privNF = nfarray[i];
  80                        }
  81                } else {
  82                        h[i].privNF =
  83                                ath9k_hw_get_nf_hist_mid(h[i].nfCalBuffer);
  84                }
  85        }
  86        return;
  87}
  88
  89static void ath9k_hw_do_getnf(struct ath_hw *ah,
  90                              int16_t nfarray[NUM_NF_READINGS])
  91{
  92        int16_t nf;
  93
  94        if (AR_SREV_9280_10_OR_LATER(ah))
  95                nf = MS(REG_READ(ah, AR_PHY_CCA), AR9280_PHY_MINCCA_PWR);
  96        else
  97                nf = MS(REG_READ(ah, AR_PHY_CCA), AR_PHY_MINCCA_PWR);
  98
  99        if (nf & 0x100)
 100                nf = 0 - ((nf ^ 0x1ff) + 1);
 101        DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
 102                "NF calibrated [ctl] [chain 0] is %d\n", nf);
 103        nfarray[0] = nf;
 104
 105        if (!AR_SREV_9285(ah)) {
 106                if (AR_SREV_9280_10_OR_LATER(ah))
 107                        nf = MS(REG_READ(ah, AR_PHY_CH1_CCA),
 108                                        AR9280_PHY_CH1_MINCCA_PWR);
 109                else
 110                        nf = MS(REG_READ(ah, AR_PHY_CH1_CCA),
 111                                        AR_PHY_CH1_MINCCA_PWR);
 112
 113                if (nf & 0x100)
 114                        nf = 0 - ((nf ^ 0x1ff) + 1);
 115                DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
 116                                "NF calibrated [ctl] [chain 1] is %d\n", nf);
 117                nfarray[1] = nf;
 118
 119                if (!AR_SREV_9280(ah) && !AR_SREV_9287(ah)) {
 120                        nf = MS(REG_READ(ah, AR_PHY_CH2_CCA),
 121                                        AR_PHY_CH2_MINCCA_PWR);
 122                        if (nf & 0x100)
 123                                nf = 0 - ((nf ^ 0x1ff) + 1);
 124                        DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
 125                                "NF calibrated [ctl] [chain 2] is %d\n", nf);
 126                        nfarray[2] = nf;
 127                }
 128        }
 129
 130        if (AR_SREV_9280_10_OR_LATER(ah))
 131                nf = MS(REG_READ(ah, AR_PHY_EXT_CCA),
 132                        AR9280_PHY_EXT_MINCCA_PWR);
 133        else
 134                nf = MS(REG_READ(ah, AR_PHY_EXT_CCA),
 135                        AR_PHY_EXT_MINCCA_PWR);
 136
 137        if (nf & 0x100)
 138                nf = 0 - ((nf ^ 0x1ff) + 1);
 139        DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
 140                "NF calibrated [ext] [chain 0] is %d\n", nf);
 141        nfarray[3] = nf;
 142
 143        if (!AR_SREV_9285(ah)) {
 144                if (AR_SREV_9280_10_OR_LATER(ah))
 145                        nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA),
 146                                        AR9280_PHY_CH1_EXT_MINCCA_PWR);
 147                else
 148                        nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA),
 149                                        AR_PHY_CH1_EXT_MINCCA_PWR);
 150
 151                if (nf & 0x100)
 152                        nf = 0 - ((nf ^ 0x1ff) + 1);
 153                DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
 154                                "NF calibrated [ext] [chain 1] is %d\n", nf);
 155                nfarray[4] = nf;
 156
 157                if (!AR_SREV_9280(ah) && !AR_SREV_9287(ah)) {
 158                        nf = MS(REG_READ(ah, AR_PHY_CH2_EXT_CCA),
 159                                        AR_PHY_CH2_EXT_MINCCA_PWR);
 160                        if (nf & 0x100)
 161                                nf = 0 - ((nf ^ 0x1ff) + 1);
 162                        DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
 163                                "NF calibrated [ext] [chain 2] is %d\n", nf);
 164                        nfarray[5] = nf;
 165                }
 166        }
 167}
 168
 169static bool getNoiseFloorThresh(struct ath_hw *ah,
 170                                enum ieee80211_band band,
 171                                int16_t *nft)
 172{
 173        switch (band) {
 174        case IEEE80211_BAND_5GHZ:
 175                *nft = (int8_t)ah->eep_ops->get_eeprom(ah, EEP_NFTHRESH_5);
 176                break;
 177        case IEEE80211_BAND_2GHZ:
 178                *nft = (int8_t)ah->eep_ops->get_eeprom(ah, EEP_NFTHRESH_2);
 179                break;
 180        default:
 181                BUG_ON(1);
 182                return false;
 183        }
 184
 185        return true;
 186}
 187
 188static void ath9k_hw_setup_calibration(struct ath_hw *ah,
 189                                       struct ath9k_cal_list *currCal)
 190{
 191        REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(0),
 192                      AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX,
 193                      currCal->calData->calCountMax);
 194
 195        switch (currCal->calData->calType) {
 196        case IQ_MISMATCH_CAL:
 197                REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ);
 198                DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
 199                        "starting IQ Mismatch Calibration\n");
 200                break;
 201        case ADC_GAIN_CAL:
 202                REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_GAIN);
 203                DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
 204                        "starting ADC Gain Calibration\n");
 205                break;
 206        case ADC_DC_CAL:
 207                REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_PER);
 208                DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
 209                        "starting ADC DC Calibration\n");
 210                break;
 211        case ADC_DC_INIT_CAL:
 212                REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_INIT);
 213                DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
 214                        "starting Init ADC DC Calibration\n");
 215                break;
 216        }
 217
 218        REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0),
 219                    AR_PHY_TIMING_CTRL4_DO_CAL);
 220}
 221
 222static void ath9k_hw_reset_calibration(struct ath_hw *ah,
 223                                       struct ath9k_cal_list *currCal)
 224{
 225        int i;
 226
 227        ath9k_hw_setup_calibration(ah, currCal);
 228
 229        currCal->calState = CAL_RUNNING;
 230
 231        for (i = 0; i < AR5416_MAX_CHAINS; i++) {
 232                ah->meas0.sign[i] = 0;
 233                ah->meas1.sign[i] = 0;
 234                ah->meas2.sign[i] = 0;
 235                ah->meas3.sign[i] = 0;
 236        }
 237
 238        ah->cal_samples = 0;
 239}
 240
 241static bool ath9k_hw_per_calibration(struct ath_hw *ah,
 242                                     struct ath9k_channel *ichan,
 243                                     u8 rxchainmask,
 244                                     struct ath9k_cal_list *currCal)
 245{
 246        bool iscaldone = false;
 247
 248        if (currCal->calState == CAL_RUNNING) {
 249                if (!(REG_READ(ah, AR_PHY_TIMING_CTRL4(0)) &
 250                      AR_PHY_TIMING_CTRL4_DO_CAL)) {
 251
 252                        currCal->calData->calCollect(ah);
 253                        ah->cal_samples++;
 254
 255                        if (ah->cal_samples >= currCal->calData->calNumSamples) {
 256                                int i, numChains = 0;
 257                                for (i = 0; i < AR5416_MAX_CHAINS; i++) {
 258                                        if (rxchainmask & (1 << i))
 259                                                numChains++;
 260                                }
 261
 262                                currCal->calData->calPostProc(ah, numChains);
 263                                ichan->CalValid |= currCal->calData->calType;
 264                                currCal->calState = CAL_DONE;
 265                                iscaldone = true;
 266                        } else {
 267                                ath9k_hw_setup_calibration(ah, currCal);
 268                        }
 269                }
 270        } else if (!(ichan->CalValid & currCal->calData->calType)) {
 271                ath9k_hw_reset_calibration(ah, currCal);
 272        }
 273
 274        return iscaldone;
 275}
 276
 277/* Assumes you are talking about the currently configured channel */
 278static bool ath9k_hw_iscal_supported(struct ath_hw *ah,
 279                                     enum ath9k_cal_types calType)
 280{
 281        struct ieee80211_conf *conf = &ah->ah_sc->hw->conf;
 282
 283        switch (calType & ah->supp_cals) {
 284        case IQ_MISMATCH_CAL: /* Both 2 GHz and 5 GHz support OFDM */
 285                return true;
 286        case ADC_GAIN_CAL:
 287        case ADC_DC_CAL:
 288                if (!(conf->channel->band == IEEE80211_BAND_2GHZ &&
 289                      conf_is_ht20(conf)))
 290                        return true;
 291                break;
 292        }
 293        return false;
 294}
 295
 296static void ath9k_hw_iqcal_collect(struct ath_hw *ah)
 297{
 298        int i;
 299
 300        for (i = 0; i < AR5416_MAX_CHAINS; i++) {
 301                ah->totalPowerMeasI[i] +=
 302                        REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
 303                ah->totalPowerMeasQ[i] +=
 304                        REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
 305                ah->totalIqCorrMeas[i] +=
 306                        (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
 307                DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
 308                        "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n",
 309                        ah->cal_samples, i, ah->totalPowerMeasI[i],
 310                        ah->totalPowerMeasQ[i],
 311                        ah->totalIqCorrMeas[i]);
 312        }
 313}
 314
 315static void ath9k_hw_adc_gaincal_collect(struct ath_hw *ah)
 316{
 317        int i;
 318
 319        for (i = 0; i < AR5416_MAX_CHAINS; i++) {
 320                ah->totalAdcIOddPhase[i] +=
 321                        REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
 322                ah->totalAdcIEvenPhase[i] +=
 323                        REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
 324                ah->totalAdcQOddPhase[i] +=
 325                        REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
 326                ah->totalAdcQEvenPhase[i] +=
 327                        REG_READ(ah, AR_PHY_CAL_MEAS_3(i));
 328
 329                DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
 330                        "%d: Chn %d oddi=0x%08x; eveni=0x%08x; "
 331                        "oddq=0x%08x; evenq=0x%08x;\n",
 332                        ah->cal_samples, i,
 333                        ah->totalAdcIOddPhase[i],
 334                        ah->totalAdcIEvenPhase[i],
 335                        ah->totalAdcQOddPhase[i],
 336                        ah->totalAdcQEvenPhase[i]);
 337        }
 338}
 339
 340static void ath9k_hw_adc_dccal_collect(struct ath_hw *ah)
 341{
 342        int i;
 343
 344        for (i = 0; i < AR5416_MAX_CHAINS; i++) {
 345                ah->totalAdcDcOffsetIOddPhase[i] +=
 346                        (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
 347                ah->totalAdcDcOffsetIEvenPhase[i] +=
 348                        (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
 349                ah->totalAdcDcOffsetQOddPhase[i] +=
 350                        (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
 351                ah->totalAdcDcOffsetQEvenPhase[i] +=
 352                        (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_3(i));
 353
 354                DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
 355                        "%d: Chn %d oddi=0x%08x; eveni=0x%08x; "
 356                        "oddq=0x%08x; evenq=0x%08x;\n",
 357                        ah->cal_samples, i,
 358                        ah->totalAdcDcOffsetIOddPhase[i],
 359                        ah->totalAdcDcOffsetIEvenPhase[i],
 360                        ah->totalAdcDcOffsetQOddPhase[i],
 361                        ah->totalAdcDcOffsetQEvenPhase[i]);
 362        }
 363}
 364
 365static void ath9k_hw_iqcalibrate(struct ath_hw *ah, u8 numChains)
 366{
 367        u32 powerMeasQ, powerMeasI, iqCorrMeas;
 368        u32 qCoffDenom, iCoffDenom;
 369        int32_t qCoff, iCoff;
 370        int iqCorrNeg, i;
 371
 372        for (i = 0; i < numChains; i++) {
 373                powerMeasI = ah->totalPowerMeasI[i];
 374                powerMeasQ = ah->totalPowerMeasQ[i];
 375                iqCorrMeas = ah->totalIqCorrMeas[i];
 376
 377                DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
 378                        "Starting IQ Cal and Correction for Chain %d\n",
 379                        i);
 380
 381                DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
 382                        "Orignal: Chn %diq_corr_meas = 0x%08x\n",
 383                        i, ah->totalIqCorrMeas[i]);
 384
 385                iqCorrNeg = 0;
 386
 387                if (iqCorrMeas > 0x80000000) {
 388                        iqCorrMeas = (0xffffffff - iqCorrMeas) + 1;
 389                        iqCorrNeg = 1;
 390                }
 391
 392                DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
 393                        "Chn %d pwr_meas_i = 0x%08x\n", i, powerMeasI);
 394                DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
 395                        "Chn %d pwr_meas_q = 0x%08x\n", i, powerMeasQ);
 396                DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, "iqCorrNeg is 0x%08x\n",
 397                        iqCorrNeg);
 398
 399                iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 128;
 400                qCoffDenom = powerMeasQ / 64;
 401
 402                if (powerMeasQ != 0) {
 403                        iCoff = iqCorrMeas / iCoffDenom;
 404                        qCoff = powerMeasI / qCoffDenom - 64;
 405                        DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
 406                                "Chn %d iCoff = 0x%08x\n", i, iCoff);
 407                        DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
 408                                "Chn %d qCoff = 0x%08x\n", i, qCoff);
 409
 410                        iCoff = iCoff & 0x3f;
 411                        DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
 412                                "New: Chn %d iCoff = 0x%08x\n", i, iCoff);
 413                        if (iqCorrNeg == 0x0)
 414                                iCoff = 0x40 - iCoff;
 415
 416                        if (qCoff > 15)
 417                                qCoff = 15;
 418                        else if (qCoff <= -16)
 419                                qCoff = 16;
 420
 421                        DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
 422                                "Chn %d : iCoff = 0x%x  qCoff = 0x%x\n",
 423                                i, iCoff, qCoff);
 424
 425                        REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i),
 426                                      AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF,
 427                                      iCoff);
 428                        REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i),
 429                                      AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF,
 430                                      qCoff);
 431                        DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
 432                                "IQ Cal and Correction done for Chain %d\n",
 433                                i);
 434                }
 435        }
 436
 437        REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0),
 438                    AR_PHY_TIMING_CTRL4_IQCORR_ENABLE);
 439}
 440
 441static void ath9k_hw_adc_gaincal_calibrate(struct ath_hw *ah, u8 numChains)
 442{
 443        u32 iOddMeasOffset, iEvenMeasOffset, qOddMeasOffset, qEvenMeasOffset;
 444        u32 qGainMismatch, iGainMismatch, val, i;
 445
 446        for (i = 0; i < numChains; i++) {
 447                iOddMeasOffset = ah->totalAdcIOddPhase[i];
 448                iEvenMeasOffset = ah->totalAdcIEvenPhase[i];
 449                qOddMeasOffset = ah->totalAdcQOddPhase[i];
 450                qEvenMeasOffset = ah->totalAdcQEvenPhase[i];
 451
 452                DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
 453                        "Starting ADC Gain Cal for Chain %d\n", i);
 454
 455                DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
 456                        "Chn %d pwr_meas_odd_i = 0x%08x\n", i,
 457                        iOddMeasOffset);
 458                DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
 459                        "Chn %d pwr_meas_even_i = 0x%08x\n", i,
 460                        iEvenMeasOffset);
 461                DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
 462                        "Chn %d pwr_meas_odd_q = 0x%08x\n", i,
 463                        qOddMeasOffset);
 464                DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
 465                        "Chn %d pwr_meas_even_q = 0x%08x\n", i,
 466                        qEvenMeasOffset);
 467
 468                if (iOddMeasOffset != 0 && qEvenMeasOffset != 0) {
 469                        iGainMismatch =
 470                                ((iEvenMeasOffset * 32) /
 471                                 iOddMeasOffset) & 0x3f;
 472                        qGainMismatch =
 473                                ((qOddMeasOffset * 32) /
 474                                 qEvenMeasOffset) & 0x3f;
 475
 476                        DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
 477                                "Chn %d gain_mismatch_i = 0x%08x\n", i,
 478                                iGainMismatch);
 479                        DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
 480                                "Chn %d gain_mismatch_q = 0x%08x\n", i,
 481                                qGainMismatch);
 482
 483                        val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i));
 484                        val &= 0xfffff000;
 485                        val |= (qGainMismatch) | (iGainMismatch << 6);
 486                        REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val);
 487
 488                        DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
 489                                "ADC Gain Cal done for Chain %d\n", i);
 490                }
 491        }
 492
 493        REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0),
 494                  REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) |
 495                  AR_PHY_NEW_ADC_GAIN_CORR_ENABLE);
 496}
 497
 498static void ath9k_hw_adc_dccal_calibrate(struct ath_hw *ah, u8 numChains)
 499{
 500        u32 iOddMeasOffset, iEvenMeasOffset, val, i;
 501        int32_t qOddMeasOffset, qEvenMeasOffset, qDcMismatch, iDcMismatch;
 502        const struct ath9k_percal_data *calData =
 503                ah->cal_list_curr->calData;
 504        u32 numSamples =
 505                (1 << (calData->calCountMax + 5)) * calData->calNumSamples;
 506
 507        for (i = 0; i < numChains; i++) {
 508                iOddMeasOffset = ah->totalAdcDcOffsetIOddPhase[i];
 509                iEvenMeasOffset = ah->totalAdcDcOffsetIEvenPhase[i];
 510                qOddMeasOffset = ah->totalAdcDcOffsetQOddPhase[i];
 511                qEvenMeasOffset = ah->totalAdcDcOffsetQEvenPhase[i];
 512
 513                DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
 514                        "Starting ADC DC Offset Cal for Chain %d\n", i);
 515
 516                DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
 517                        "Chn %d pwr_meas_odd_i = %d\n", i,
 518                        iOddMeasOffset);
 519                DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
 520                        "Chn %d pwr_meas_even_i = %d\n", i,
 521                        iEvenMeasOffset);
 522                DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
 523                        "Chn %d pwr_meas_odd_q = %d\n", i,
 524                        qOddMeasOffset);
 525                DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
 526                        "Chn %d pwr_meas_even_q = %d\n", i,
 527                        qEvenMeasOffset);
 528
 529                iDcMismatch = (((iEvenMeasOffset - iOddMeasOffset) * 2) /
 530                               numSamples) & 0x1ff;
 531                qDcMismatch = (((qOddMeasOffset - qEvenMeasOffset) * 2) /
 532                               numSamples) & 0x1ff;
 533
 534                DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
 535                        "Chn %d dc_offset_mismatch_i = 0x%08x\n", i,
 536                        iDcMismatch);
 537                DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
 538                        "Chn %d dc_offset_mismatch_q = 0x%08x\n", i,
 539                        qDcMismatch);
 540
 541                val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i));
 542                val &= 0xc0000fff;
 543                val |= (qDcMismatch << 12) | (iDcMismatch << 21);
 544                REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val);
 545
 546                DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
 547                        "ADC DC Offset Cal done for Chain %d\n", i);
 548        }
 549
 550        REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0),
 551                  REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) |
 552                  AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE);
 553}
 554
 555/* This is done for the currently configured channel */
 556bool ath9k_hw_reset_calvalid(struct ath_hw *ah)
 557{
 558        struct ieee80211_conf *conf = &ah->ah_sc->hw->conf;
 559        struct ath9k_cal_list *currCal = ah->cal_list_curr;
 560
 561        if (!ah->curchan)
 562                return true;
 563
 564        if (!AR_SREV_9100(ah) && !AR_SREV_9160_10_OR_LATER(ah))
 565                return true;
 566
 567        if (currCal == NULL)
 568                return true;
 569
 570        if (currCal->calState != CAL_DONE) {
 571                DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
 572                        "Calibration state incorrect, %d\n",
 573                        currCal->calState);
 574                return true;
 575        }
 576
 577        if (!ath9k_hw_iscal_supported(ah, currCal->calData->calType))
 578                return true;
 579
 580        DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
 581                "Resetting Cal %d state for channel %u\n",
 582                currCal->calData->calType, conf->channel->center_freq);
 583
 584        ah->curchan->CalValid &= ~currCal->calData->calType;
 585        currCal->calState = CAL_WAITING;
 586
 587        return false;
 588}
 589
 590void ath9k_hw_start_nfcal(struct ath_hw *ah)
 591{
 592        REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
 593                    AR_PHY_AGC_CONTROL_ENABLE_NF);
 594        REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
 595                    AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
 596        REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
 597}
 598
 599void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan)
 600{
 601        struct ath9k_nfcal_hist *h;
 602        int i, j;
 603        int32_t val;
 604        const u32 ar5416_cca_regs[6] = {
 605                AR_PHY_CCA,
 606                AR_PHY_CH1_CCA,
 607                AR_PHY_CH2_CCA,
 608                AR_PHY_EXT_CCA,
 609                AR_PHY_CH1_EXT_CCA,
 610                AR_PHY_CH2_EXT_CCA
 611        };
 612        u8 chainmask, rx_chain_status;
 613
 614        rx_chain_status = REG_READ(ah, AR_PHY_RX_CHAINMASK);
 615        if (AR_SREV_9285(ah))
 616                chainmask = 0x9;
 617        else if (AR_SREV_9280(ah) || AR_SREV_9287(ah)) {
 618                if ((rx_chain_status & 0x2) || (rx_chain_status & 0x4))
 619                        chainmask = 0x1B;
 620                else
 621                        chainmask = 0x09;
 622        } else {
 623                if (rx_chain_status & 0x4)
 624                        chainmask = 0x3F;
 625                else if (rx_chain_status & 0x2)
 626                        chainmask = 0x1B;
 627                else
 628                        chainmask = 0x09;
 629        }
 630
 631        h = ah->nfCalHist;
 632
 633        for (i = 0; i < NUM_NF_READINGS; i++) {
 634                if (chainmask & (1 << i)) {
 635                        val = REG_READ(ah, ar5416_cca_regs[i]);
 636                        val &= 0xFFFFFE00;
 637                        val |= (((u32) (h[i].privNF) << 1) & 0x1ff);
 638                        REG_WRITE(ah, ar5416_cca_regs[i], val);
 639                }
 640        }
 641
 642        REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
 643                    AR_PHY_AGC_CONTROL_ENABLE_NF);
 644        REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
 645                    AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
 646        REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
 647
 648        for (j = 0; j < 1000; j++) {
 649                if ((REG_READ(ah, AR_PHY_AGC_CONTROL) &
 650                     AR_PHY_AGC_CONTROL_NF) == 0)
 651                        break;
 652                udelay(10);
 653        }
 654
 655        for (i = 0; i < NUM_NF_READINGS; i++) {
 656                if (chainmask & (1 << i)) {
 657                        val = REG_READ(ah, ar5416_cca_regs[i]);
 658                        val &= 0xFFFFFE00;
 659                        val |= (((u32) (-50) << 1) & 0x1ff);
 660                        REG_WRITE(ah, ar5416_cca_regs[i], val);
 661                }
 662        }
 663}
 664
 665int16_t ath9k_hw_getnf(struct ath_hw *ah,
 666                       struct ath9k_channel *chan)
 667{
 668        int16_t nf, nfThresh;
 669        int16_t nfarray[NUM_NF_READINGS] = { 0 };
 670        struct ath9k_nfcal_hist *h;
 671        struct ieee80211_channel *c = chan->chan;
 672
 673        chan->channelFlags &= (~CHANNEL_CW_INT);
 674        if (REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) {
 675                DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
 676                        "NF did not complete in calibration window\n");
 677                nf = 0;
 678                chan->rawNoiseFloor = nf;
 679                return chan->rawNoiseFloor;
 680        } else {
 681                ath9k_hw_do_getnf(ah, nfarray);
 682                nf = nfarray[0];
 683                if (getNoiseFloorThresh(ah, c->band, &nfThresh)
 684                    && nf > nfThresh) {
 685                        DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
 686                                "noise floor failed detected; "
 687                                "detected %d, threshold %d\n",
 688                                nf, nfThresh);
 689                        chan->channelFlags |= CHANNEL_CW_INT;
 690                }
 691        }
 692
 693        h = ah->nfCalHist;
 694
 695        ath9k_hw_update_nfcal_hist_buffer(h, nfarray);
 696        chan->rawNoiseFloor = h[0].privNF;
 697
 698        return chan->rawNoiseFloor;
 699}
 700
 701void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah)
 702{
 703        int i, j;
 704        s16 noise_floor;
 705
 706        if (AR_SREV_9280(ah))
 707                noise_floor = AR_PHY_CCA_MAX_AR9280_GOOD_VALUE;
 708        else if (AR_SREV_9285(ah))
 709                noise_floor = AR_PHY_CCA_MAX_AR9285_GOOD_VALUE;
 710        else if (AR_SREV_9287(ah))
 711                noise_floor = AR_PHY_CCA_MAX_AR9287_GOOD_VALUE;
 712        else
 713                noise_floor = AR_PHY_CCA_MAX_AR5416_GOOD_VALUE;
 714
 715        for (i = 0; i < NUM_NF_READINGS; i++) {
 716                ah->nfCalHist[i].currIndex = 0;
 717                ah->nfCalHist[i].privNF = noise_floor;
 718                ah->nfCalHist[i].invalidNFcount =
 719                        AR_PHY_CCA_FILTERWINDOW_LENGTH;
 720                for (j = 0; j < ATH9K_NF_CAL_HIST_MAX; j++) {
 721                        ah->nfCalHist[i].nfCalBuffer[j] = noise_floor;
 722                }
 723        }
 724}
 725
 726s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan)
 727{
 728        s16 nf;
 729
 730        if (chan->rawNoiseFloor == 0)
 731                nf = -96;
 732        else
 733                nf = chan->rawNoiseFloor;
 734
 735        if (!ath9k_hw_nf_in_range(ah, nf))
 736                nf = ATH_DEFAULT_NOISE_FLOOR;
 737
 738        return nf;
 739}
 740
 741static void ath9k_olc_temp_compensation(struct ath_hw *ah)
 742{
 743        u32 rddata, i;
 744        int delta, currPDADC, regval, slope;
 745
 746        rddata = REG_READ(ah, AR_PHY_TX_PWRCTRL4);
 747        currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT);
 748
 749
 750        if (OLC_FOR_AR9287_10_LATER) {
 751                if (ah->initPDADC == 0 || currPDADC == 0) {
 752                        return;
 753                } else {
 754                        slope = ah->eep_ops->get_eeprom(ah, EEP_TEMPSENSE_SLOPE);
 755                        if (slope == 0)
 756                                delta = 0;
 757                        else
 758                                delta = ((currPDADC - ah->initPDADC)*4) / slope;
 759                        REG_RMW_FIELD(ah, AR_PHY_CH0_TX_PWRCTRL11,
 760                                        AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, delta);
 761                        REG_RMW_FIELD(ah, AR_PHY_CH1_TX_PWRCTRL11,
 762                                        AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, delta);
 763                }
 764        } else {
 765                if (ah->eep_ops->get_eeprom(ah, EEP_DAC_HPWR_5G))
 766                        delta = (currPDADC - ah->initPDADC + 4) / 8;
 767                else
 768                        delta = (currPDADC - ah->initPDADC + 5) / 10;
 769
 770                if (delta != ah->PDADCdelta) {
 771                        ah->PDADCdelta = delta;
 772                        for (i = 1; i < AR9280_TX_GAIN_TABLE_SIZE; i++) {
 773                                regval = ah->originalGain[i] - delta;
 774                                if (regval < 0)
 775                                        regval = 0;
 776
 777                                REG_RMW_FIELD(ah, AR_PHY_TX_GAIN_TBL1 + i * 4,
 778                                                AR_PHY_TX_GAIN, regval);
 779                        }
 780                }
 781        }
 782}
 783
 784static void ath9k_hw_9271_pa_cal(struct ath_hw *ah)
 785{
 786        u32 regVal;
 787        unsigned int i;
 788        u32 regList [][2] = {
 789                { 0x786c, 0 },
 790                { 0x7854, 0 },
 791                { 0x7820, 0 },
 792                { 0x7824, 0 },
 793                { 0x7868, 0 },
 794                { 0x783c, 0 },
 795                { 0x7838, 0 } ,
 796                { 0x7828, 0 } ,
 797        };
 798
 799        for (i = 0; i < ARRAY_SIZE(regList); i++)
 800                regList[i][1] = REG_READ(ah, regList[i][0]);
 801
 802        regVal = REG_READ(ah, 0x7834);
 803        regVal &= (~(0x1));
 804        REG_WRITE(ah, 0x7834, regVal);
 805        regVal = REG_READ(ah, 0x9808);
 806        regVal |= (0x1 << 27);
 807        REG_WRITE(ah, 0x9808, regVal);
 808
 809        /* 786c,b23,1, pwddac=1 */
 810        REG_RMW_FIELD(ah, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC, 1);
 811        /* 7854, b5,1, pdrxtxbb=1 */
 812        REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1, 1);
 813        /* 7854, b7,1, pdv2i=1 */
 814        REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I, 1);
 815        /* 7854, b8,1, pddacinterface=1 */
 816        REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF, 1);
 817        /* 7824,b12,0, offcal=0 */
 818        REG_RMW_FIELD(ah, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL, 0);
 819        /* 7838, b1,0, pwddb=0 */
 820        REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB, 0);
 821        /* 7820,b11,0, enpacal=0 */
 822        REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL, 0);
 823        /* 7820,b25,1, pdpadrv1=0 */
 824        REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1, 0);
 825        /* 7820,b24,0, pdpadrv2=0 */
 826        REG_RMW_FIELD(ah, AR9285_AN_RF2G1,AR9285_AN_RF2G1_PDPADRV2,0);
 827        /* 7820,b23,0, pdpaout=0 */
 828        REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT, 0);
 829        /* 783c,b14-16,7, padrvgn2tab_0=7 */
 830        REG_RMW_FIELD(ah, AR9285_AN_RF2G8,AR9285_AN_RF2G8_PADRVGN2TAB0, 7);
 831        /*
 832         * 7838,b29-31,0, padrvgn1tab_0=0
 833         * does not matter since we turn it off
 834         */
 835        REG_RMW_FIELD(ah, AR9285_AN_RF2G7,AR9285_AN_RF2G7_PADRVGN2TAB0, 0);
 836
 837        REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9271_AN_RF2G3_CCOMP, 0xfff);
 838
 839        /* Set:
 840         * localmode=1,bmode=1,bmoderxtx=1,synthon=1,
 841         * txon=1,paon=1,oscon=1,synthon_force=1
 842         */
 843        REG_WRITE(ah, AR9285_AN_TOP2, 0xca0358a0);
 844        udelay(30);
 845        REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9271_AN_RF2G6_OFFS, 0);
 846
 847        /* find off_6_1; */
 848        for (i = 6; i >= 0; i--) {
 849                regVal = REG_READ(ah, 0x7834);
 850                regVal |= (1 << (20 + i));
 851                REG_WRITE(ah, 0x7834, regVal);
 852                udelay(1);
 853                //regVal = REG_READ(ah, 0x7834);
 854                regVal &= (~(0x1 << (20 + i)));
 855                regVal |= (MS(REG_READ(ah, 0x7840), AR9285_AN_RXTXBB1_SPARE9)
 856                            << (20 + i));
 857                REG_WRITE(ah, 0x7834, regVal);
 858        }
 859
 860        /*  Empirical offset correction  */
 861#if 0
 862        REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9271_AN_RF2G6_OFFS, 0x20);
 863#endif
 864
 865        regVal = REG_READ(ah, 0x7834);
 866        regVal |= 0x1;
 867        REG_WRITE(ah, 0x7834, regVal);
 868        regVal = REG_READ(ah, 0x9808);
 869        regVal &= (~(0x1 << 27));
 870        REG_WRITE(ah, 0x9808, regVal);
 871
 872        for (i = 0; i < ARRAY_SIZE(regList); i++)
 873                REG_WRITE(ah, regList[i][0], regList[i][1]);
 874}
 875
 876static inline void ath9k_hw_9285_pa_cal(struct ath_hw *ah, bool is_reset)
 877{
 878
 879        u32 regVal;
 880        int i, offset, offs_6_1, offs_0;
 881        u32 ccomp_org, reg_field;
 882        u32 regList[][2] = {
 883                { 0x786c, 0 },
 884                { 0x7854, 0 },
 885                { 0x7820, 0 },
 886                { 0x7824, 0 },
 887                { 0x7868, 0 },
 888                { 0x783c, 0 },
 889                { 0x7838, 0 },
 890        };
 891
 892        DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, "Running PA Calibration\n");
 893
 894        /* PA CAL is not needed for high power solution */
 895        if (ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE) ==
 896            AR5416_EEP_TXGAIN_HIGH_POWER)
 897                return;
 898
 899        if (AR_SREV_9285_11(ah)) {
 900                REG_WRITE(ah, AR9285_AN_TOP4, (AR9285_AN_TOP4_DEFAULT | 0x14));
 901                udelay(10);
 902        }
 903
 904        for (i = 0; i < ARRAY_SIZE(regList); i++)
 905                regList[i][1] = REG_READ(ah, regList[i][0]);
 906
 907        regVal = REG_READ(ah, 0x7834);
 908        regVal &= (~(0x1));
 909        REG_WRITE(ah, 0x7834, regVal);
 910        regVal = REG_READ(ah, 0x9808);
 911        regVal |= (0x1 << 27);
 912        REG_WRITE(ah, 0x9808, regVal);
 913
 914        REG_RMW_FIELD(ah, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC, 1);
 915        REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1, 1);
 916        REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I, 1);
 917        REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF, 1);
 918        REG_RMW_FIELD(ah, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL, 0);
 919        REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB, 0);
 920        REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL, 0);
 921        REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1, 0);
 922        REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV2, 0);
 923        REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT, 0);
 924        REG_RMW_FIELD(ah, AR9285_AN_RF2G8, AR9285_AN_RF2G8_PADRVGN2TAB0, 7);
 925        REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PADRVGN2TAB0, 0);
 926        ccomp_org = MS(REG_READ(ah, AR9285_AN_RF2G6), AR9285_AN_RF2G6_CCOMP);
 927        REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, 0xf);
 928
 929        REG_WRITE(ah, AR9285_AN_TOP2, 0xca0358a0);
 930        udelay(30);
 931        REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS, 0);
 932        REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, 0);
 933
 934        for (i = 6; i > 0; i--) {
 935                regVal = REG_READ(ah, 0x7834);
 936                regVal |= (1 << (19 + i));
 937                REG_WRITE(ah, 0x7834, regVal);
 938                udelay(1);
 939                regVal = REG_READ(ah, 0x7834);
 940                regVal &= (~(0x1 << (19 + i)));
 941                reg_field = MS(REG_READ(ah, 0x7840), AR9285_AN_RXTXBB1_SPARE9);
 942                regVal |= (reg_field << (19 + i));
 943                REG_WRITE(ah, 0x7834, regVal);
 944        }
 945
 946        REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, 1);
 947        udelay(1);
 948        reg_field = MS(REG_READ(ah, AR9285_AN_RF2G9), AR9285_AN_RXTXBB1_SPARE9);
 949        REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, reg_field);
 950        offs_6_1 = MS(REG_READ(ah, AR9285_AN_RF2G6), AR9285_AN_RF2G6_OFFS);
 951        offs_0   = MS(REG_READ(ah, AR9285_AN_RF2G3), AR9285_AN_RF2G3_PDVCCOMP);
 952
 953        offset = (offs_6_1<<1) | offs_0;
 954        offset = offset - 0;
 955        offs_6_1 = offset>>1;
 956        offs_0 = offset & 1;
 957
 958        if ((!is_reset) && (ah->pacal_info.prev_offset == offset)) {
 959                if (ah->pacal_info.max_skipcount < MAX_PACAL_SKIPCOUNT)
 960                        ah->pacal_info.max_skipcount =
 961                                2 * ah->pacal_info.max_skipcount;
 962                ah->pacal_info.skipcount = ah->pacal_info.max_skipcount;
 963        } else {
 964                ah->pacal_info.max_skipcount = 1;
 965                ah->pacal_info.skipcount = 0;
 966                ah->pacal_info.prev_offset = offset;
 967        }
 968
 969        REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS, offs_6_1);
 970        REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, offs_0);
 971
 972        regVal = REG_READ(ah, 0x7834);
 973        regVal |= 0x1;
 974        REG_WRITE(ah, 0x7834, regVal);
 975        regVal = REG_READ(ah, 0x9808);
 976        regVal &= (~(0x1 << 27));
 977        REG_WRITE(ah, 0x9808, regVal);
 978
 979        for (i = 0; i < ARRAY_SIZE(regList); i++)
 980                REG_WRITE(ah, regList[i][0], regList[i][1]);
 981
 982        REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, ccomp_org);
 983
 984        if (AR_SREV_9285_11(ah))
 985                REG_WRITE(ah, AR9285_AN_TOP4, AR9285_AN_TOP4_DEFAULT);
 986
 987}
 988
 989bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan,
 990                        u8 rxchainmask, bool longcal)
 991{
 992        bool iscaldone = true;
 993        struct ath9k_cal_list *currCal = ah->cal_list_curr;
 994
 995        if (currCal &&
 996            (currCal->calState == CAL_RUNNING ||
 997             currCal->calState == CAL_WAITING)) {
 998                iscaldone = ath9k_hw_per_calibration(ah, chan,
 999                                                     rxchainmask, currCal);
1000                if (iscaldone) {
1001                        ah->cal_list_curr = currCal = currCal->calNext;
1002
1003                        if (currCal->calState == CAL_WAITING) {
1004                                iscaldone = false;
1005                                ath9k_hw_reset_calibration(ah, currCal);
1006                        }
1007                }
1008        }
1009
1010        /* Do NF cal only at longer intervals */
1011        if (longcal) {
1012                /* Do periodic PAOffset Cal */
1013                if (AR_SREV_9271(ah))
1014                        ath9k_hw_9271_pa_cal(ah);
1015                else if (AR_SREV_9285_11_OR_LATER(ah)) {
1016                        if (!ah->pacal_info.skipcount)
1017                                ath9k_hw_9285_pa_cal(ah, false);
1018                        else
1019                                ah->pacal_info.skipcount--;
1020                }
1021
1022                if (OLC_FOR_AR9280_20_LATER || OLC_FOR_AR9287_10_LATER)
1023                        ath9k_olc_temp_compensation(ah);
1024
1025                /* Get the value from the previous NF cal and update history buffer */
1026                ath9k_hw_getnf(ah, chan);
1027
1028                /*
1029                 * Load the NF from history buffer of the current channel.
1030                 * NF is slow time-variant, so it is OK to use a historical value.
1031                 */
1032                ath9k_hw_loadnf(ah, ah->curchan);
1033
1034                ath9k_hw_start_nfcal(ah);
1035        }
1036
1037        return iscaldone;
1038}
1039
1040static bool ar9285_clc(struct ath_hw *ah, struct ath9k_channel *chan)
1041{
1042        REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
1043        if (IS_CHAN_HT20(chan)) {
1044                REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE);
1045                REG_SET_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN);
1046                REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
1047                            AR_PHY_AGC_CONTROL_FLTR_CAL);
1048                REG_CLR_BIT(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE);
1049                REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL);
1050                if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL,
1051                                  AR_PHY_AGC_CONTROL_CAL, 0, AH_WAIT_TIMEOUT)) {
1052                        DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, "offset "
1053                                "calibration failed to complete in "
1054                                "1ms; noisy ??\n");
1055                        return false;
1056                }
1057                REG_CLR_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN);
1058                REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE);
1059                REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
1060        }
1061        REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
1062        REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL);
1063        REG_SET_BIT(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE);
1064        REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL);
1065        if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL,
1066                          0, AH_WAIT_TIMEOUT)) {
1067                DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, "offset calibration "
1068                                "failed to complete in 1ms; noisy ??\n");
1069                return false;
1070        }
1071
1072        REG_SET_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
1073        REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
1074        REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL);
1075
1076        return true;
1077}
1078
1079bool ath9k_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan)
1080{
1081        if (AR_SREV_9285_12_OR_LATER(ah)) {
1082                if (!ar9285_clc(ah, chan))
1083                        return false;
1084        } else {
1085                if (AR_SREV_9280_10_OR_LATER(ah)) {
1086                        if (!AR_SREV_9287_10_OR_LATER(ah))
1087                                REG_CLR_BIT(ah, AR_PHY_ADC_CTL,
1088                                            AR_PHY_ADC_CTL_OFF_PWDADC);
1089                        REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
1090                                    AR_PHY_AGC_CONTROL_FLTR_CAL);
1091                }
1092
1093                /* Calibrate the AGC */
1094                REG_WRITE(ah, AR_PHY_AGC_CONTROL,
1095                          REG_READ(ah, AR_PHY_AGC_CONTROL) |
1096                          AR_PHY_AGC_CONTROL_CAL);
1097
1098                /* Poll for offset calibration complete */
1099                if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL,
1100                                   0, AH_WAIT_TIMEOUT)) {
1101                        DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
1102                                "offset calibration failed to complete in 1ms; "
1103                                "noisy environment?\n");
1104                        return false;
1105                }
1106
1107                if (AR_SREV_9280_10_OR_LATER(ah)) {
1108                        if (!AR_SREV_9287_10_OR_LATER(ah))
1109                                REG_SET_BIT(ah, AR_PHY_ADC_CTL,
1110                                            AR_PHY_ADC_CTL_OFF_PWDADC);
1111                        REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
1112                                    AR_PHY_AGC_CONTROL_FLTR_CAL);
1113                }
1114        }
1115
1116        /* Do PA Calibration */
1117        if (AR_SREV_9285_11_OR_LATER(ah))
1118                ath9k_hw_9285_pa_cal(ah, true);
1119
1120        /* Do NF Calibration after DC offset and other calibrations */
1121        REG_WRITE(ah, AR_PHY_AGC_CONTROL,
1122                  REG_READ(ah, AR_PHY_AGC_CONTROL) | AR_PHY_AGC_CONTROL_NF);
1123
1124        ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL;
1125
1126        /* Enable IQ, ADC Gain and ADC DC offset CALs */
1127        if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) {
1128                if (ath9k_hw_iscal_supported(ah, ADC_GAIN_CAL)) {
1129                        INIT_CAL(&ah->adcgain_caldata);
1130                        INSERT_CAL(ah, &ah->adcgain_caldata);
1131                        DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
1132                                "enabling ADC Gain Calibration.\n");
1133                }
1134                if (ath9k_hw_iscal_supported(ah, ADC_DC_CAL)) {
1135                        INIT_CAL(&ah->adcdc_caldata);
1136                        INSERT_CAL(ah, &ah->adcdc_caldata);
1137                        DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
1138                                "enabling ADC DC Calibration.\n");
1139                }
1140                if (ath9k_hw_iscal_supported(ah, IQ_MISMATCH_CAL)) {
1141                        INIT_CAL(&ah->iq_caldata);
1142                        INSERT_CAL(ah, &ah->iq_caldata);
1143                        DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
1144                                "enabling IQ Calibration.\n");
1145                }
1146
1147                ah->cal_list_curr = ah->cal_list;
1148
1149                if (ah->cal_list_curr)
1150                        ath9k_hw_reset_calibration(ah, ah->cal_list_curr);
1151        }
1152
1153        chan->CalValid = 0;
1154
1155        return true;
1156}
1157
1158const struct ath9k_percal_data iq_cal_multi_sample = {
1159        IQ_MISMATCH_CAL,
1160        MAX_CAL_SAMPLES,
1161        PER_MIN_LOG_COUNT,
1162        ath9k_hw_iqcal_collect,
1163        ath9k_hw_iqcalibrate
1164};
1165const struct ath9k_percal_data iq_cal_single_sample = {
1166        IQ_MISMATCH_CAL,
1167        MIN_CAL_SAMPLES,
1168        PER_MAX_LOG_COUNT,
1169        ath9k_hw_iqcal_collect,
1170        ath9k_hw_iqcalibrate
1171};
1172const struct ath9k_percal_data adc_gain_cal_multi_sample = {
1173        ADC_GAIN_CAL,
1174        MAX_CAL_SAMPLES,
1175        PER_MIN_LOG_COUNT,
1176        ath9k_hw_adc_gaincal_collect,
1177        ath9k_hw_adc_gaincal_calibrate
1178};
1179const struct ath9k_percal_data adc_gain_cal_single_sample = {
1180        ADC_GAIN_CAL,
1181        MIN_CAL_SAMPLES,
1182        PER_MAX_LOG_COUNT,
1183        ath9k_hw_adc_gaincal_collect,
1184        ath9k_hw_adc_gaincal_calibrate
1185};
1186const struct ath9k_percal_data adc_dc_cal_multi_sample = {
1187        ADC_DC_CAL,
1188        MAX_CAL_SAMPLES,
1189        PER_MIN_LOG_COUNT,
1190        ath9k_hw_adc_dccal_collect,
1191        ath9k_hw_adc_dccal_calibrate
1192};
1193const struct ath9k_percal_data adc_dc_cal_single_sample = {
1194        ADC_DC_CAL,
1195        MIN_CAL_SAMPLES,
1196        PER_MAX_LOG_COUNT,
1197        ath9k_hw_adc_dccal_collect,
1198        ath9k_hw_adc_dccal_calibrate
1199};
1200const struct ath9k_percal_data adc_init_dc_cal = {
1201        ADC_DC_INIT_CAL,
1202        MIN_CAL_SAMPLES,
1203        INIT_LOG_COUNT,
1204        ath9k_hw_adc_dccal_collect,
1205        ath9k_hw_adc_dccal_calibrate
1206};
1207