LCOV - code coverage report
Current view: top level - drivers/net/wireless/ath/ath9k - ar9002_calib.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 32 471 6.8 %
Date: 2022-03-28 13:20:08 Functions: 4 19 21.1 %
Branches: 18 311 5.8 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright (c) 2008-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 "ar9002_phy.h"
      20                 :            : 
      21                 :            : #define AR9285_CLCAL_REDO_THRESH    1
      22                 :            : 
      23                 :            : enum ar9002_cal_types {
      24                 :            :         ADC_GAIN_CAL = BIT(0),
      25                 :            :         ADC_DC_CAL = BIT(1),
      26                 :            :         IQ_MISMATCH_CAL = BIT(2),
      27                 :            : };
      28                 :            : 
      29                 :          0 : static bool ar9002_hw_is_cal_supported(struct ath_hw *ah,
      30                 :            :                                 struct ath9k_channel *chan,
      31                 :            :                                 enum ar9002_cal_types cal_type)
      32                 :            : {
      33                 :          0 :         bool supported = false;
      34                 :          0 :         switch (ah->supp_cals & cal_type) {
      35                 :            :         case IQ_MISMATCH_CAL:
      36                 :            :                 supported = true;
      37                 :            :                 break;
      38                 :          0 :         case ADC_GAIN_CAL:
      39                 :            :         case ADC_DC_CAL:
      40                 :            :                 /* Run ADC Gain Cal for non-CCK & non 2GHz-HT20 only */
      41   [ #  #  #  #  :          0 :                 if (!((IS_CHAN_2GHZ(chan) || IS_CHAN_A_FAST_CLOCK(ah, chan)) &&
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
      42                 :            :                       IS_CHAN_HT20(chan)))
      43                 :            :                         supported = true;
      44                 :            :                 break;
      45                 :            :         }
      46                 :            :         return supported;
      47                 :            : }
      48                 :            : 
      49                 :          0 : static void ar9002_hw_setup_calibration(struct ath_hw *ah,
      50                 :            :                                         struct ath9k_cal_list *currCal)
      51                 :            : {
      52                 :          0 :         struct ath_common *common = ath9k_hw_common(ah);
      53                 :            : 
      54                 :          0 :         REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(0),
      55                 :            :                       AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX,
      56                 :            :                       currCal->calData->calCountMax);
      57                 :            : 
      58   [ #  #  #  # ]:          0 :         switch (currCal->calData->calType) {
      59                 :          0 :         case IQ_MISMATCH_CAL:
      60                 :          0 :                 REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ);
      61         [ #  # ]:          0 :                 ath_dbg(common, CALIBRATE,
      62                 :            :                         "starting IQ Mismatch Calibration\n");
      63                 :            :                 break;
      64                 :          0 :         case ADC_GAIN_CAL:
      65                 :          0 :                 REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_GAIN);
      66         [ #  # ]:          0 :                 ath_dbg(common, CALIBRATE, "starting ADC Gain Calibration\n");
      67                 :            :                 break;
      68                 :          0 :         case ADC_DC_CAL:
      69                 :          0 :                 REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_PER);
      70         [ #  # ]:          0 :                 ath_dbg(common, CALIBRATE, "starting ADC DC Calibration\n");
      71                 :            :                 break;
      72                 :            :         }
      73                 :            : 
      74                 :          0 :         REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0),
      75                 :            :                     AR_PHY_TIMING_CTRL4_DO_CAL);
      76                 :          0 : }
      77                 :            : 
      78                 :          0 : static bool ar9002_hw_per_calibration(struct ath_hw *ah,
      79                 :            :                                       struct ath9k_channel *ichan,
      80                 :            :                                       u8 rxchainmask,
      81                 :            :                                       struct ath9k_cal_list *currCal)
      82                 :            : {
      83                 :          0 :         struct ath9k_hw_cal_data *caldata = ah->caldata;
      84                 :          0 :         bool iscaldone = false;
      85                 :            : 
      86         [ #  # ]:          0 :         if (currCal->calState == CAL_RUNNING) {
      87         [ #  # ]:          0 :                 if (!(REG_READ(ah, AR_PHY_TIMING_CTRL4(0)) &
      88                 :            :                       AR_PHY_TIMING_CTRL4_DO_CAL)) {
      89                 :            : 
      90                 :          0 :                         currCal->calData->calCollect(ah);
      91                 :          0 :                         ah->cal_samples++;
      92                 :            : 
      93                 :          0 :                         if (ah->cal_samples >=
      94         [ #  # ]:          0 :                             currCal->calData->calNumSamples) {
      95                 :            :                                 int i, numChains = 0;
      96         [ #  # ]:          0 :                                 for (i = 0; i < AR5416_MAX_CHAINS; i++) {
      97         [ #  # ]:          0 :                                         if (rxchainmask & (1 << i))
      98                 :          0 :                                                 numChains++;
      99                 :            :                                 }
     100                 :            : 
     101                 :          0 :                                 currCal->calData->calPostProc(ah, numChains);
     102                 :          0 :                                 caldata->CalValid |= currCal->calData->calType;
     103                 :          0 :                                 currCal->calState = CAL_DONE;
     104                 :          0 :                                 iscaldone = true;
     105                 :            :                         } else {
     106                 :          0 :                                 ar9002_hw_setup_calibration(ah, currCal);
     107                 :            :                         }
     108                 :            :                 }
     109         [ #  # ]:          0 :         } else if (!(caldata->CalValid & currCal->calData->calType)) {
     110                 :          0 :                 ath9k_hw_reset_calibration(ah, currCal);
     111                 :            :         }
     112                 :            : 
     113                 :          0 :         return iscaldone;
     114                 :            : }
     115                 :            : 
     116                 :          0 : static void ar9002_hw_iqcal_collect(struct ath_hw *ah)
     117                 :            : {
     118                 :          0 :         int i;
     119                 :            : 
     120         [ #  # ]:          0 :         for (i = 0; i < AR5416_MAX_CHAINS; i++) {
     121                 :          0 :                 ah->totalPowerMeasI[i] +=
     122                 :          0 :                         REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
     123                 :          0 :                 ah->totalPowerMeasQ[i] +=
     124                 :          0 :                         REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
     125                 :          0 :                 ah->totalIqCorrMeas[i] +=
     126                 :          0 :                         (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
     127         [ #  # ]:          0 :                 ath_dbg(ath9k_hw_common(ah), CALIBRATE,
     128                 :            :                         "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n",
     129                 :            :                         ah->cal_samples, i, ah->totalPowerMeasI[i],
     130                 :            :                         ah->totalPowerMeasQ[i],
     131                 :            :                         ah->totalIqCorrMeas[i]);
     132                 :            :         }
     133                 :          0 : }
     134                 :            : 
     135                 :          0 : static void ar9002_hw_adc_gaincal_collect(struct ath_hw *ah)
     136                 :            : {
     137                 :          0 :         int i;
     138                 :            : 
     139         [ #  # ]:          0 :         for (i = 0; i < AR5416_MAX_CHAINS; i++) {
     140                 :          0 :                 ah->totalAdcIOddPhase[i] +=
     141                 :          0 :                         REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
     142                 :          0 :                 ah->totalAdcIEvenPhase[i] +=
     143                 :          0 :                         REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
     144                 :          0 :                 ah->totalAdcQOddPhase[i] +=
     145                 :          0 :                         REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
     146                 :          0 :                 ah->totalAdcQEvenPhase[i] +=
     147                 :          0 :                         REG_READ(ah, AR_PHY_CAL_MEAS_3(i));
     148                 :            : 
     149         [ #  # ]:          0 :                 ath_dbg(ath9k_hw_common(ah), CALIBRATE,
     150                 :            :                         "%d: Chn %d oddi=0x%08x; eveni=0x%08x; oddq=0x%08x; evenq=0x%08x;\n",
     151                 :            :                         ah->cal_samples, i,
     152                 :            :                         ah->totalAdcIOddPhase[i],
     153                 :            :                         ah->totalAdcIEvenPhase[i],
     154                 :            :                         ah->totalAdcQOddPhase[i],
     155                 :            :                         ah->totalAdcQEvenPhase[i]);
     156                 :            :         }
     157                 :          0 : }
     158                 :            : 
     159                 :          0 : static void ar9002_hw_adc_dccal_collect(struct ath_hw *ah)
     160                 :            : {
     161                 :          0 :         int i;
     162                 :            : 
     163         [ #  # ]:          0 :         for (i = 0; i < AR5416_MAX_CHAINS; i++) {
     164                 :          0 :                 ah->totalAdcDcOffsetIOddPhase[i] +=
     165                 :          0 :                         (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
     166                 :          0 :                 ah->totalAdcDcOffsetIEvenPhase[i] +=
     167                 :          0 :                         (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
     168                 :          0 :                 ah->totalAdcDcOffsetQOddPhase[i] +=
     169                 :          0 :                         (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
     170                 :          0 :                 ah->totalAdcDcOffsetQEvenPhase[i] +=
     171                 :          0 :                         (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_3(i));
     172                 :            : 
     173         [ #  # ]:          0 :                 ath_dbg(ath9k_hw_common(ah), CALIBRATE,
     174                 :            :                         "%d: Chn %d oddi=0x%08x; eveni=0x%08x; oddq=0x%08x; evenq=0x%08x;\n",
     175                 :            :                         ah->cal_samples, i,
     176                 :            :                         ah->totalAdcDcOffsetIOddPhase[i],
     177                 :            :                         ah->totalAdcDcOffsetIEvenPhase[i],
     178                 :            :                         ah->totalAdcDcOffsetQOddPhase[i],
     179                 :            :                         ah->totalAdcDcOffsetQEvenPhase[i]);
     180                 :            :         }
     181                 :          0 : }
     182                 :            : 
     183                 :          0 : static void ar9002_hw_iqcalibrate(struct ath_hw *ah, u8 numChains)
     184                 :            : {
     185                 :          0 :         struct ath_common *common = ath9k_hw_common(ah);
     186                 :          0 :         u32 powerMeasQ, powerMeasI, iqCorrMeas;
     187                 :          0 :         u32 qCoffDenom, iCoffDenom;
     188                 :          0 :         int32_t qCoff, iCoff;
     189                 :          0 :         int iqCorrNeg, i;
     190                 :            : 
     191         [ #  # ]:          0 :         for (i = 0; i < numChains; i++) {
     192                 :          0 :                 powerMeasI = ah->totalPowerMeasI[i];
     193                 :          0 :                 powerMeasQ = ah->totalPowerMeasQ[i];
     194                 :          0 :                 iqCorrMeas = ah->totalIqCorrMeas[i];
     195                 :            : 
     196         [ #  # ]:          0 :                 ath_dbg(common, CALIBRATE,
     197                 :            :                         "Starting IQ Cal and Correction for Chain %d\n",
     198                 :            :                         i);
     199                 :            : 
     200         [ #  # ]:          0 :                 ath_dbg(common, CALIBRATE,
     201                 :            :                         "Original: Chn %d iq_corr_meas = 0x%08x\n",
     202                 :            :                         i, ah->totalIqCorrMeas[i]);
     203                 :            : 
     204                 :          0 :                 iqCorrNeg = 0;
     205                 :            : 
     206         [ #  # ]:          0 :                 if (iqCorrMeas > 0x80000000) {
     207                 :          0 :                         iqCorrMeas = (0xffffffff - iqCorrMeas) + 1;
     208                 :          0 :                         iqCorrNeg = 1;
     209                 :            :                 }
     210                 :            : 
     211         [ #  # ]:          0 :                 ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_i = 0x%08x\n",
     212                 :            :                         i, powerMeasI);
     213         [ #  # ]:          0 :                 ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_q = 0x%08x\n",
     214                 :            :                         i, powerMeasQ);
     215         [ #  # ]:          0 :                 ath_dbg(common, CALIBRATE, "iqCorrNeg is 0x%08x\n", iqCorrNeg);
     216                 :            : 
     217                 :          0 :                 iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 128;
     218                 :          0 :                 qCoffDenom = powerMeasQ / 64;
     219                 :            : 
     220   [ #  #  #  #  :          0 :                 if ((powerMeasQ != 0) && (iCoffDenom != 0) &&
                   #  # ]
     221                 :            :                     (qCoffDenom != 0)) {
     222                 :          0 :                         iCoff = iqCorrMeas / iCoffDenom;
     223                 :          0 :                         qCoff = powerMeasI / qCoffDenom - 64;
     224         [ #  # ]:          0 :                         ath_dbg(common, CALIBRATE, "Chn %d iCoff = 0x%08x\n",
     225                 :            :                                 i, iCoff);
     226         [ #  # ]:          0 :                         ath_dbg(common, CALIBRATE, "Chn %d qCoff = 0x%08x\n",
     227                 :            :                                 i, qCoff);
     228                 :            : 
     229                 :          0 :                         iCoff = iCoff & 0x3f;
     230         [ #  # ]:          0 :                         ath_dbg(common, CALIBRATE,
     231                 :            :                                 "New: Chn %d iCoff = 0x%08x\n", i, iCoff);
     232         [ #  # ]:          0 :                         if (iqCorrNeg == 0x0)
     233                 :          0 :                                 iCoff = 0x40 - iCoff;
     234                 :            : 
     235                 :          0 :                         if (qCoff > 15)
     236                 :            :                                 qCoff = 15;
     237                 :            :                         else if (qCoff <= -16)
     238                 :            :                                 qCoff = -16;
     239                 :            : 
     240         [ #  # ]:          0 :                         ath_dbg(common, CALIBRATE,
     241                 :            :                                 "Chn %d : iCoff = 0x%x  qCoff = 0x%x\n",
     242                 :            :                                 i, iCoff, qCoff);
     243                 :            : 
     244                 :          0 :                         REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i),
     245                 :            :                                       AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF,
     246                 :            :                                       iCoff);
     247                 :          0 :                         REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i),
     248                 :            :                                       AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF,
     249                 :            :                                       qCoff);
     250         [ #  # ]:          0 :                         ath_dbg(common, CALIBRATE,
     251                 :            :                                 "IQ Cal and Correction done for Chain %d\n",
     252                 :            :                                 i);
     253                 :            :                 }
     254                 :            :         }
     255                 :            : 
     256                 :          0 :         REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0),
     257                 :            :                     AR_PHY_TIMING_CTRL4_IQCORR_ENABLE);
     258                 :          0 : }
     259                 :            : 
     260                 :          0 : static void ar9002_hw_adc_gaincal_calibrate(struct ath_hw *ah, u8 numChains)
     261                 :            : {
     262                 :          0 :         struct ath_common *common = ath9k_hw_common(ah);
     263                 :          0 :         u32 iOddMeasOffset, iEvenMeasOffset, qOddMeasOffset, qEvenMeasOffset;
     264                 :          0 :         u32 qGainMismatch, iGainMismatch, val, i;
     265                 :            : 
     266         [ #  # ]:          0 :         for (i = 0; i < numChains; i++) {
     267                 :          0 :                 iOddMeasOffset = ah->totalAdcIOddPhase[i];
     268                 :          0 :                 iEvenMeasOffset = ah->totalAdcIEvenPhase[i];
     269                 :          0 :                 qOddMeasOffset = ah->totalAdcQOddPhase[i];
     270                 :          0 :                 qEvenMeasOffset = ah->totalAdcQEvenPhase[i];
     271                 :            : 
     272         [ #  # ]:          0 :                 ath_dbg(common, CALIBRATE,
     273                 :            :                         "Starting ADC Gain Cal for Chain %d\n", i);
     274                 :            : 
     275         [ #  # ]:          0 :                 ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_odd_i = 0x%08x\n",
     276                 :            :                         i, iOddMeasOffset);
     277         [ #  # ]:          0 :                 ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_even_i = 0x%08x\n",
     278                 :            :                         i, iEvenMeasOffset);
     279         [ #  # ]:          0 :                 ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_odd_q = 0x%08x\n",
     280                 :            :                         i, qOddMeasOffset);
     281         [ #  # ]:          0 :                 ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_even_q = 0x%08x\n",
     282                 :            :                         i, qEvenMeasOffset);
     283                 :            : 
     284   [ #  #  #  # ]:          0 :                 if (iOddMeasOffset != 0 && qEvenMeasOffset != 0) {
     285                 :          0 :                         iGainMismatch =
     286                 :          0 :                                 ((iEvenMeasOffset * 32) /
     287                 :            :                                  iOddMeasOffset) & 0x3f;
     288                 :          0 :                         qGainMismatch =
     289                 :          0 :                                 ((qOddMeasOffset * 32) /
     290                 :            :                                  qEvenMeasOffset) & 0x3f;
     291                 :            : 
     292         [ #  # ]:          0 :                         ath_dbg(common, CALIBRATE,
     293                 :            :                                 "Chn %d gain_mismatch_i = 0x%08x\n",
     294                 :            :                                 i, iGainMismatch);
     295         [ #  # ]:          0 :                         ath_dbg(common, CALIBRATE,
     296                 :            :                                 "Chn %d gain_mismatch_q = 0x%08x\n",
     297                 :            :                                 i, qGainMismatch);
     298                 :            : 
     299                 :          0 :                         val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i));
     300                 :          0 :                         val &= 0xfffff000;
     301                 :          0 :                         val |= (qGainMismatch) | (iGainMismatch << 6);
     302                 :          0 :                         REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val);
     303                 :            : 
     304         [ #  # ]:          0 :                         ath_dbg(common, CALIBRATE,
     305                 :            :                                 "ADC Gain Cal done for Chain %d\n", i);
     306                 :            :                 }
     307                 :            :         }
     308                 :            : 
     309                 :          0 :         REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0),
     310                 :            :                   REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) |
     311                 :            :                   AR_PHY_NEW_ADC_GAIN_CORR_ENABLE);
     312                 :          0 : }
     313                 :            : 
     314                 :          0 : static void ar9002_hw_adc_dccal_calibrate(struct ath_hw *ah, u8 numChains)
     315                 :            : {
     316                 :          0 :         struct ath_common *common = ath9k_hw_common(ah);
     317                 :          0 :         u32 iOddMeasOffset, iEvenMeasOffset, val, i;
     318                 :          0 :         int32_t qOddMeasOffset, qEvenMeasOffset, qDcMismatch, iDcMismatch;
     319                 :          0 :         const struct ath9k_percal_data *calData =
     320                 :          0 :                 ah->cal_list_curr->calData;
     321                 :          0 :         u32 numSamples =
     322                 :          0 :                 (1 << (calData->calCountMax + 5)) * calData->calNumSamples;
     323                 :            : 
     324         [ #  # ]:          0 :         for (i = 0; i < numChains; i++) {
     325                 :          0 :                 iOddMeasOffset = ah->totalAdcDcOffsetIOddPhase[i];
     326                 :          0 :                 iEvenMeasOffset = ah->totalAdcDcOffsetIEvenPhase[i];
     327                 :          0 :                 qOddMeasOffset = ah->totalAdcDcOffsetQOddPhase[i];
     328                 :          0 :                 qEvenMeasOffset = ah->totalAdcDcOffsetQEvenPhase[i];
     329                 :            : 
     330         [ #  # ]:          0 :                 ath_dbg(common, CALIBRATE,
     331                 :            :                         "Starting ADC DC Offset Cal for Chain %d\n", i);
     332                 :            : 
     333         [ #  # ]:          0 :                 ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_odd_i = %d\n",
     334                 :            :                         i, iOddMeasOffset);
     335         [ #  # ]:          0 :                 ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_even_i = %d\n",
     336                 :            :                         i, iEvenMeasOffset);
     337         [ #  # ]:          0 :                 ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_odd_q = %d\n",
     338                 :            :                         i, qOddMeasOffset);
     339         [ #  # ]:          0 :                 ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_even_q = %d\n",
     340                 :            :                         i, qEvenMeasOffset);
     341                 :            : 
     342                 :          0 :                 iDcMismatch = (((iEvenMeasOffset - iOddMeasOffset) * 2) /
     343                 :          0 :                                numSamples) & 0x1ff;
     344                 :          0 :                 qDcMismatch = (((qOddMeasOffset - qEvenMeasOffset) * 2) /
     345                 :          0 :                                numSamples) & 0x1ff;
     346                 :            : 
     347         [ #  # ]:          0 :                 ath_dbg(common, CALIBRATE,
     348                 :            :                         "Chn %d dc_offset_mismatch_i = 0x%08x\n",
     349                 :            :                         i, iDcMismatch);
     350         [ #  # ]:          0 :                 ath_dbg(common, CALIBRATE,
     351                 :            :                         "Chn %d dc_offset_mismatch_q = 0x%08x\n",
     352                 :            :                         i, qDcMismatch);
     353                 :            : 
     354                 :          0 :                 val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i));
     355                 :          0 :                 val &= 0xc0000fff;
     356                 :          0 :                 val |= (qDcMismatch << 12) | (iDcMismatch << 21);
     357                 :          0 :                 REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val);
     358                 :            : 
     359         [ #  # ]:          0 :                 ath_dbg(common, CALIBRATE,
     360                 :            :                         "ADC DC Offset Cal done for Chain %d\n", i);
     361                 :            :         }
     362                 :            : 
     363                 :          0 :         REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0),
     364                 :            :                   REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) |
     365                 :            :                   AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE);
     366                 :          0 : }
     367                 :            : 
     368                 :          0 : static void ar9287_hw_olc_temp_compensation(struct ath_hw *ah)
     369                 :            : {
     370                 :          0 :         u32 rddata;
     371                 :          0 :         int32_t delta, currPDADC, slope;
     372                 :            : 
     373                 :          0 :         rddata = REG_READ(ah, AR_PHY_TX_PWRCTRL4);
     374                 :          0 :         currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT);
     375                 :            : 
     376   [ #  #  #  # ]:          0 :         if (ah->initPDADC == 0 || currPDADC == 0) {
     377                 :            :                 /*
     378                 :            :                  * Zero value indicates that no frames have been transmitted
     379                 :            :                  * yet, can't do temperature compensation until frames are
     380                 :            :                  * transmitted.
     381                 :            :                  */
     382                 :            :                 return;
     383                 :            :         } else {
     384                 :          0 :                 slope = ah->eep_ops->get_eeprom(ah, EEP_TEMPSENSE_SLOPE);
     385                 :            : 
     386         [ #  # ]:          0 :                 if (slope == 0) { /* to avoid divide by zero case */
     387                 :            :                         delta = 0;
     388                 :            :                 } else {
     389                 :          0 :                         delta = ((currPDADC - ah->initPDADC)*4) / slope;
     390                 :            :                 }
     391                 :          0 :                 REG_RMW_FIELD(ah, AR_PHY_CH0_TX_PWRCTRL11,
     392                 :            :                               AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, delta);
     393                 :          0 :                 REG_RMW_FIELD(ah, AR_PHY_CH1_TX_PWRCTRL11,
     394                 :            :                               AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, delta);
     395                 :            :         }
     396                 :            : }
     397                 :            : 
     398                 :          0 : static void ar9280_hw_olc_temp_compensation(struct ath_hw *ah)
     399                 :            : {
     400                 :          0 :         u32 rddata, i;
     401                 :          0 :         int delta, currPDADC, regval;
     402                 :            : 
     403                 :          0 :         rddata = REG_READ(ah, AR_PHY_TX_PWRCTRL4);
     404                 :          0 :         currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT);
     405                 :            : 
     406   [ #  #  #  # ]:          0 :         if (ah->initPDADC == 0 || currPDADC == 0)
     407                 :            :                 return;
     408                 :            : 
     409         [ #  # ]:          0 :         if (ah->eep_ops->get_eeprom(ah, EEP_DAC_HPWR_5G))
     410                 :          0 :                 delta = (currPDADC - ah->initPDADC + 4) / 8;
     411                 :            :         else
     412                 :          0 :                 delta = (currPDADC - ah->initPDADC + 5) / 10;
     413                 :            : 
     414         [ #  # ]:          0 :         if (delta != ah->PDADCdelta) {
     415                 :          0 :                 ah->PDADCdelta = delta;
     416         [ #  # ]:          0 :                 for (i = 1; i < AR9280_TX_GAIN_TABLE_SIZE; i++) {
     417                 :          0 :                         regval = ah->originalGain[i] - delta;
     418                 :          0 :                         if (regval < 0)
     419                 :            :                                 regval = 0;
     420                 :            : 
     421                 :          0 :                         REG_RMW_FIELD(ah,
     422                 :            :                                       AR_PHY_TX_GAIN_TBL1 + i * 4,
     423                 :            :                                       AR_PHY_TX_GAIN, regval);
     424                 :            :                 }
     425                 :            :         }
     426                 :            : }
     427                 :            : 
     428                 :          0 : static void ar9271_hw_pa_cal(struct ath_hw *ah, bool is_reset)
     429                 :            : {
     430                 :          0 :         u32 regVal;
     431                 :          0 :         unsigned int i;
     432                 :          0 :         u32 regList[][2] = {
     433                 :            :                 { AR9285_AN_TOP3, 0 },
     434                 :            :                 { AR9285_AN_RXTXBB1, 0 },
     435                 :            :                 { AR9285_AN_RF2G1, 0 },
     436                 :            :                 { AR9285_AN_RF2G2, 0 },
     437                 :            :                 { AR9285_AN_TOP2, 0 },
     438                 :            :                 { AR9285_AN_RF2G8, 0 },
     439                 :            :                 { AR9285_AN_RF2G7, 0 },
     440                 :            :                 { AR9285_AN_RF2G3, 0 },
     441                 :            :         };
     442                 :            : 
     443                 :          0 :         REG_READ_ARRAY(ah, regList, ARRAY_SIZE(regList));
     444                 :            : 
     445         [ #  # ]:          0 :         ENABLE_REG_RMW_BUFFER(ah);
     446                 :            :         /* 7834, b1=0 */
     447                 :          0 :         REG_CLR_BIT(ah, AR9285_AN_RF2G6, 1 << 0);
     448                 :            :         /* 9808, b27=1 */
     449                 :          0 :         REG_SET_BIT(ah, 0x9808, 1 << 27);
     450                 :            :         /* 786c,b23,1, pwddac=1 */
     451                 :          0 :         REG_SET_BIT(ah, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC);
     452                 :            :         /* 7854, b5,1, pdrxtxbb=1 */
     453                 :          0 :         REG_SET_BIT(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1);
     454                 :            :         /* 7854, b7,1, pdv2i=1 */
     455                 :          0 :         REG_SET_BIT(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I);
     456                 :            :         /* 7854, b8,1, pddacinterface=1 */
     457                 :          0 :         REG_SET_BIT(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF);
     458                 :            :         /* 7824,b12,0, offcal=0 */
     459                 :          0 :         REG_CLR_BIT(ah, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL);
     460                 :            :         /* 7838, b1,0, pwddb=0 */
     461                 :          0 :         REG_CLR_BIT(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB);
     462                 :            :         /* 7820,b11,0, enpacal=0 */
     463                 :          0 :         REG_CLR_BIT(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL);
     464                 :            :         /* 7820,b25,1, pdpadrv1=0 */
     465                 :          0 :         REG_CLR_BIT(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1);
     466                 :            :         /* 7820,b24,0, pdpadrv2=0 */
     467                 :          0 :         REG_CLR_BIT(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV2);
     468                 :            :         /* 7820,b23,0, pdpaout=0 */
     469                 :          0 :         REG_CLR_BIT(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT);
     470                 :            :         /* 783c,b14-16,7, padrvgn2tab_0=7 */
     471                 :          0 :         REG_RMW_FIELD(ah, AR9285_AN_RF2G8, AR9285_AN_RF2G8_PADRVGN2TAB0, 7);
     472                 :            :         /*
     473                 :            :          * 7838,b29-31,0, padrvgn1tab_0=0
     474                 :            :          * does not matter since we turn it off
     475                 :            :          */
     476                 :          0 :         REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PADRVGN2TAB0, 0);
     477                 :            :         /* 7828, b0-11, ccom=fff */
     478                 :          0 :         REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9271_AN_RF2G3_CCOMP, 0xfff);
     479         [ #  # ]:          0 :         REG_RMW_BUFFER_FLUSH(ah);
     480                 :            : 
     481                 :            :         /* Set:
     482                 :            :          * localmode=1,bmode=1,bmoderxtx=1,synthon=1,
     483                 :            :          * txon=1,paon=1,oscon=1,synthon_force=1
     484                 :            :          */
     485                 :          0 :         REG_WRITE(ah, AR9285_AN_TOP2, 0xca0358a0);
     486                 :          0 :         udelay(30);
     487                 :          0 :         REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9271_AN_RF2G6_OFFS, 0);
     488                 :            : 
     489                 :            :         /* find off_6_1; */
     490         [ #  # ]:          0 :         for (i = 6; i > 0; i--) {
     491                 :          0 :                 regVal = REG_READ(ah, AR9285_AN_RF2G6);
     492                 :          0 :                 regVal |= (1 << (20 + i));
     493                 :          0 :                 REG_WRITE(ah, AR9285_AN_RF2G6, regVal);
     494                 :          0 :                 udelay(1);
     495                 :            :                 /* regVal = REG_READ(ah, 0x7834); */
     496                 :          0 :                 regVal &= (~(0x1 << (20 + i)));
     497                 :          0 :                 regVal |= (MS(REG_READ(ah, AR9285_AN_RF2G9),
     498                 :            :                               AR9285_AN_RXTXBB1_SPARE9)
     499                 :          0 :                             << (20 + i));
     500                 :          0 :                 REG_WRITE(ah, AR9285_AN_RF2G6, regVal);
     501                 :            :         }
     502                 :            : 
     503                 :          0 :         regVal = (regVal >> 20) & 0x7f;
     504                 :            : 
     505                 :            :         /* Update PA cal info */
     506   [ #  #  #  # ]:          0 :         if ((!is_reset) && (ah->pacal_info.prev_offset == regVal)) {
     507         [ #  # ]:          0 :                 if (ah->pacal_info.max_skipcount < MAX_PACAL_SKIPCOUNT)
     508                 :          0 :                         ah->pacal_info.max_skipcount =
     509                 :          0 :                                 2 * ah->pacal_info.max_skipcount;
     510                 :          0 :                 ah->pacal_info.skipcount = ah->pacal_info.max_skipcount;
     511                 :            :         } else {
     512                 :          0 :                 ah->pacal_info.max_skipcount = 1;
     513                 :          0 :                 ah->pacal_info.skipcount = 0;
     514                 :          0 :                 ah->pacal_info.prev_offset = regVal;
     515                 :            :         }
     516                 :            : 
     517                 :            : 
     518         [ #  # ]:          0 :         ENABLE_REG_RMW_BUFFER(ah);
     519                 :            :         /* 7834, b1=1 */
     520                 :          0 :         REG_SET_BIT(ah, AR9285_AN_RF2G6, 1 << 0);
     521                 :            :         /* 9808, b27=0 */
     522                 :          0 :         REG_CLR_BIT(ah, 0x9808, 1 << 27);
     523         [ #  # ]:          0 :         REG_RMW_BUFFER_FLUSH(ah);
     524                 :            : 
     525         [ #  # ]:          0 :         ENABLE_REGWRITE_BUFFER(ah);
     526         [ #  # ]:          0 :         for (i = 0; i < ARRAY_SIZE(regList); i++)
     527                 :          0 :                 REG_WRITE(ah, regList[i][0], regList[i][1]);
     528                 :            : 
     529         [ #  # ]:          0 :         REGWRITE_BUFFER_FLUSH(ah);
     530                 :          0 : }
     531                 :            : 
     532                 :          0 : static inline void ar9285_hw_pa_cal(struct ath_hw *ah, bool is_reset)
     533                 :            : {
     534         [ #  # ]:          0 :         struct ath_common *common = ath9k_hw_common(ah);
     535                 :          0 :         u32 regVal;
     536                 :          0 :         int i, offset, offs_6_1, offs_0;
     537                 :          0 :         u32 ccomp_org, reg_field;
     538                 :          0 :         u32 regList[][2] = {
     539                 :            :                 { 0x786c, 0 },
     540                 :            :                 { 0x7854, 0 },
     541                 :            :                 { 0x7820, 0 },
     542                 :            :                 { 0x7824, 0 },
     543                 :            :                 { 0x7868, 0 },
     544                 :            :                 { 0x783c, 0 },
     545                 :            :                 { 0x7838, 0 },
     546                 :            :         };
     547                 :            : 
     548         [ #  # ]:          0 :         ath_dbg(common, CALIBRATE, "Running PA Calibration\n");
     549                 :            : 
     550                 :            :         /* PA CAL is not needed for high power solution */
     551         [ #  # ]:          0 :         if (ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE) ==
     552                 :            :             AR5416_EEP_TXGAIN_HIGH_POWER)
     553                 :          0 :                 return;
     554                 :            : 
     555         [ #  # ]:          0 :         for (i = 0; i < ARRAY_SIZE(regList); i++)
     556                 :          0 :                 regList[i][1] = REG_READ(ah, regList[i][0]);
     557                 :            : 
     558                 :          0 :         regVal = REG_READ(ah, 0x7834);
     559                 :          0 :         regVal &= (~(0x1));
     560                 :          0 :         REG_WRITE(ah, 0x7834, regVal);
     561                 :          0 :         regVal = REG_READ(ah, 0x9808);
     562                 :          0 :         regVal |= (0x1 << 27);
     563                 :          0 :         REG_WRITE(ah, 0x9808, regVal);
     564                 :            : 
     565                 :          0 :         REG_RMW_FIELD(ah, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC, 1);
     566                 :          0 :         REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1, 1);
     567                 :          0 :         REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I, 1);
     568                 :          0 :         REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF, 1);
     569                 :          0 :         REG_RMW_FIELD(ah, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL, 0);
     570                 :          0 :         REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB, 0);
     571                 :          0 :         REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL, 0);
     572                 :          0 :         REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1, 0);
     573                 :          0 :         REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV2, 0);
     574                 :          0 :         REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT, 0);
     575                 :          0 :         REG_RMW_FIELD(ah, AR9285_AN_RF2G8, AR9285_AN_RF2G8_PADRVGN2TAB0, 7);
     576                 :          0 :         REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PADRVGN2TAB0, 0);
     577                 :          0 :         ccomp_org = MS(REG_READ(ah, AR9285_AN_RF2G6), AR9285_AN_RF2G6_CCOMP);
     578                 :          0 :         REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, 0xf);
     579                 :            : 
     580                 :          0 :         REG_WRITE(ah, AR9285_AN_TOP2, 0xca0358a0);
     581                 :          0 :         udelay(30);
     582                 :          0 :         REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS, 0);
     583                 :          0 :         REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, 0);
     584                 :            : 
     585         [ #  # ]:          0 :         for (i = 6; i > 0; i--) {
     586                 :          0 :                 regVal = REG_READ(ah, 0x7834);
     587                 :          0 :                 regVal |= (1 << (19 + i));
     588                 :          0 :                 REG_WRITE(ah, 0x7834, regVal);
     589                 :          0 :                 udelay(1);
     590                 :          0 :                 regVal = REG_READ(ah, 0x7834);
     591                 :          0 :                 regVal &= (~(0x1 << (19 + i)));
     592                 :          0 :                 reg_field = MS(REG_READ(ah, 0x7840), AR9285_AN_RXTXBB1_SPARE9);
     593                 :          0 :                 regVal |= (reg_field << (19 + i));
     594                 :          0 :                 REG_WRITE(ah, 0x7834, regVal);
     595                 :            :         }
     596                 :            : 
     597                 :          0 :         REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, 1);
     598                 :          0 :         udelay(1);
     599                 :          0 :         reg_field = MS(REG_READ(ah, AR9285_AN_RF2G9), AR9285_AN_RXTXBB1_SPARE9);
     600                 :          0 :         REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, reg_field);
     601                 :          0 :         offs_6_1 = MS(REG_READ(ah, AR9285_AN_RF2G6), AR9285_AN_RF2G6_OFFS);
     602                 :          0 :         offs_0   = MS(REG_READ(ah, AR9285_AN_RF2G3), AR9285_AN_RF2G3_PDVCCOMP);
     603                 :            : 
     604                 :          0 :         offset = (offs_6_1<<1) | offs_0;
     605                 :          0 :         offset = offset - 0;
     606                 :          0 :         offs_6_1 = offset>>1;
     607                 :          0 :         offs_0 = offset & 1;
     608                 :            : 
     609   [ #  #  #  # ]:          0 :         if ((!is_reset) && (ah->pacal_info.prev_offset == offset)) {
     610         [ #  # ]:          0 :                 if (ah->pacal_info.max_skipcount < MAX_PACAL_SKIPCOUNT)
     611                 :          0 :                         ah->pacal_info.max_skipcount =
     612                 :          0 :                                 2 * ah->pacal_info.max_skipcount;
     613                 :          0 :                 ah->pacal_info.skipcount = ah->pacal_info.max_skipcount;
     614                 :            :         } else {
     615                 :          0 :                 ah->pacal_info.max_skipcount = 1;
     616                 :          0 :                 ah->pacal_info.skipcount = 0;
     617                 :          0 :                 ah->pacal_info.prev_offset = offset;
     618                 :            :         }
     619                 :            : 
     620                 :          0 :         REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS, offs_6_1);
     621                 :          0 :         REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, offs_0);
     622                 :            : 
     623                 :          0 :         regVal = REG_READ(ah, 0x7834);
     624                 :          0 :         regVal |= 0x1;
     625                 :          0 :         REG_WRITE(ah, 0x7834, regVal);
     626                 :          0 :         regVal = REG_READ(ah, 0x9808);
     627                 :          0 :         regVal &= (~(0x1 << 27));
     628                 :          0 :         REG_WRITE(ah, 0x9808, regVal);
     629                 :            : 
     630         [ #  # ]:          0 :         for (i = 0; i < ARRAY_SIZE(regList); i++)
     631                 :          0 :                 REG_WRITE(ah, regList[i][0], regList[i][1]);
     632                 :            : 
     633                 :          0 :         REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, ccomp_org);
     634                 :            : }
     635                 :            : 
     636                 :         20 : static void ar9002_hw_pa_cal(struct ath_hw *ah, bool is_reset)
     637                 :            : {
     638         [ -  + ]:         20 :         if (AR_SREV_9271(ah)) {
     639   [ #  #  #  # ]:          0 :                 if (is_reset || !ah->pacal_info.skipcount)
     640                 :          0 :                         ar9271_hw_pa_cal(ah, is_reset);
     641                 :            :                 else
     642                 :          0 :                         ah->pacal_info.skipcount--;
     643         [ -  + ]:         20 :         } else if (AR_SREV_9285_12_OR_LATER(ah)) {
     644   [ #  #  #  # ]:          0 :                 if (is_reset || !ah->pacal_info.skipcount)
     645                 :          0 :                         ar9285_hw_pa_cal(ah, is_reset);
     646                 :            :                 else
     647                 :          0 :                         ah->pacal_info.skipcount--;
     648                 :            :         }
     649                 :         20 : }
     650                 :            : 
     651                 :          0 : static void ar9002_hw_olc_temp_compensation(struct ath_hw *ah)
     652                 :            : {
     653   [ #  #  #  # ]:          0 :         if (OLC_FOR_AR9287_10_LATER)
     654                 :          0 :                 ar9287_hw_olc_temp_compensation(ah);
     655   [ #  #  #  # ]:          0 :         else if (OLC_FOR_AR9280_20_LATER)
     656                 :          0 :                 ar9280_hw_olc_temp_compensation(ah);
     657                 :          0 : }
     658                 :            : 
     659                 :          0 : static int ar9002_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan,
     660                 :            :                                u8 rxchainmask, bool longcal)
     661                 :            : {
     662                 :          0 :         struct ath9k_cal_list *currCal = ah->cal_list_curr;
     663                 :          0 :         bool nfcal, nfcal_pending = false, percal_pending;
     664                 :          0 :         int ret;
     665                 :            : 
     666         [ #  # ]:          0 :         nfcal = !!(REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF);
     667         [ #  # ]:          0 :         if (ah->caldata)
     668                 :          0 :                 nfcal_pending = test_bit(NFCAL_PENDING, &ah->caldata->cal_flags);
     669                 :            : 
     670         [ #  # ]:          0 :         percal_pending = (currCal &&
     671         [ #  # ]:          0 :                           (currCal->calState == CAL_RUNNING ||
     672                 :            :                            currCal->calState == CAL_WAITING));
     673                 :            : 
     674   [ #  #  #  # ]:          0 :         if (percal_pending && !nfcal) {
     675         [ #  # ]:          0 :                 if (!ar9002_hw_per_calibration(ah, chan, rxchainmask, currCal))
     676                 :            :                         return 0;
     677                 :            : 
     678                 :          0 :                 ah->cal_list_curr = currCal = currCal->calNext;
     679         [ #  # ]:          0 :                 if (currCal->calState == CAL_WAITING)
     680                 :          0 :                         ath9k_hw_reset_calibration(ah, currCal);
     681                 :            : 
     682                 :          0 :                 return 0;
     683                 :            :         }
     684                 :            : 
     685                 :            :         /* Do NF cal only at longer intervals */
     686         [ #  # ]:          0 :         if (longcal || nfcal_pending) {
     687                 :            :                 /*
     688                 :            :                  * Get the value from the previous NF cal and update
     689                 :            :                  * history buffer.
     690                 :            :                  */
     691         [ #  # ]:          0 :                 if (ath9k_hw_getnf(ah, chan)) {
     692                 :            :                         /*
     693                 :            :                          * Load the NF from history buffer of the current
     694                 :            :                          * channel.
     695                 :            :                          * NF is slow time-variant, so it is OK to use a
     696                 :            :                          * historical value.
     697                 :            :                          */
     698                 :          0 :                         ret = ath9k_hw_loadnf(ah, ah->curchan);
     699         [ #  # ]:          0 :                         if (ret < 0)
     700                 :            :                                 return ret;
     701                 :            :                 }
     702                 :            : 
     703         [ #  # ]:          0 :                 if (longcal) {
     704                 :          0 :                         ath9k_hw_start_nfcal(ah, false);
     705                 :            :                         /* Do periodic PAOffset Cal */
     706                 :          0 :                         ar9002_hw_pa_cal(ah, false);
     707                 :          0 :                         ar9002_hw_olc_temp_compensation(ah);
     708                 :            :                 }
     709                 :            :         }
     710                 :            : 
     711                 :          0 :         return !percal_pending;
     712                 :            : }
     713                 :            : 
     714                 :            : /* Carrier leakage Calibration fix */
     715                 :            : static bool ar9285_hw_cl_cal(struct ath_hw *ah, struct ath9k_channel *chan)
     716                 :            : {
     717                 :            :         struct ath_common *common = ath9k_hw_common(ah);
     718                 :            : 
     719                 :            :         REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
     720                 :            :         if (IS_CHAN_HT20(chan)) {
     721                 :            :                 REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE);
     722                 :            :                 REG_SET_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN);
     723                 :            :                 REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
     724                 :            :                             AR_PHY_AGC_CONTROL_FLTR_CAL);
     725                 :            :                 REG_CLR_BIT(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE);
     726                 :            :                 REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL);
     727                 :            :                 if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL,
     728                 :            :                                   AR_PHY_AGC_CONTROL_CAL, 0, AH_WAIT_TIMEOUT)) {
     729                 :            :                         ath_dbg(common, CALIBRATE,
     730                 :            :                                 "offset calibration failed to complete in %d ms; noisy environment?\n",
     731                 :            :                                 AH_WAIT_TIMEOUT / 1000);
     732                 :            :                         return false;
     733                 :            :                 }
     734                 :            :                 REG_CLR_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN);
     735                 :            :                 REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE);
     736                 :            :                 REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
     737                 :            :         }
     738                 :            :         REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
     739                 :            :         REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL);
     740                 :            :         REG_SET_BIT(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE);
     741                 :            :         REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL);
     742                 :            :         if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL,
     743                 :            :                           0, AH_WAIT_TIMEOUT)) {
     744                 :            :                 ath_dbg(common, CALIBRATE,
     745                 :            :                         "offset calibration failed to complete in %d ms; noisy environment?\n",
     746                 :            :                         AH_WAIT_TIMEOUT / 1000);
     747                 :            :                 return false;
     748                 :            :         }
     749                 :            : 
     750                 :            :         REG_SET_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
     751                 :            :         REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
     752                 :            :         REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL);
     753                 :            : 
     754                 :            :         return true;
     755                 :            : }
     756                 :            : 
     757                 :          0 : static bool ar9285_hw_clc(struct ath_hw *ah, struct ath9k_channel *chan)
     758                 :            : {
     759                 :          0 :         int i;
     760                 :          0 :         u_int32_t txgain_max;
     761                 :          0 :         u_int32_t clc_gain, gain_mask = 0, clc_num = 0;
     762                 :          0 :         u_int32_t reg_clc_I0, reg_clc_Q0;
     763                 :          0 :         u_int32_t i0_num = 0;
     764                 :          0 :         u_int32_t q0_num = 0;
     765                 :          0 :         u_int32_t total_num = 0;
     766                 :          0 :         u_int32_t reg_rf2g5_org;
     767                 :          0 :         bool retv = true;
     768                 :            : 
     769         [ #  # ]:          0 :         if (!(ar9285_hw_cl_cal(ah, chan)))
     770                 :            :                 return false;
     771                 :            : 
     772                 :          0 :         txgain_max = MS(REG_READ(ah, AR_PHY_TX_PWRCTRL7),
     773                 :            :                         AR_PHY_TX_PWRCTRL_TX_GAIN_TAB_MAX);
     774                 :            : 
     775         [ #  # ]:          0 :         for (i = 0; i < (txgain_max+1); i++) {
     776                 :          0 :                 clc_gain = (REG_READ(ah, (AR_PHY_TX_GAIN_TBL1+(i<<2))) &
     777                 :          0 :                            AR_PHY_TX_GAIN_CLC) >> AR_PHY_TX_GAIN_CLC_S;
     778         [ #  # ]:          0 :                 if (!(gain_mask & (1 << clc_gain))) {
     779                 :          0 :                         gain_mask |= (1 << clc_gain);
     780                 :          0 :                         clc_num++;
     781                 :            :                 }
     782                 :            :         }
     783                 :            : 
     784         [ #  # ]:          0 :         for (i = 0; i < clc_num; i++) {
     785                 :          0 :                 reg_clc_I0 = (REG_READ(ah, (AR_PHY_CLC_TBL1 + (i << 2)))
     786                 :          0 :                               & AR_PHY_CLC_I0) >> AR_PHY_CLC_I0_S;
     787                 :          0 :                 reg_clc_Q0 = (REG_READ(ah, (AR_PHY_CLC_TBL1 + (i << 2)))
     788                 :          0 :                               & AR_PHY_CLC_Q0) >> AR_PHY_CLC_Q0_S;
     789         [ #  # ]:          0 :                 if (reg_clc_I0 == 0)
     790                 :          0 :                         i0_num++;
     791                 :            : 
     792         [ #  # ]:          0 :                 if (reg_clc_Q0 == 0)
     793                 :          0 :                         q0_num++;
     794                 :            :         }
     795                 :          0 :         total_num = i0_num + q0_num;
     796         [ #  # ]:          0 :         if (total_num > AR9285_CLCAL_REDO_THRESH) {
     797                 :          0 :                 reg_rf2g5_org = REG_READ(ah, AR9285_RF2G5);
     798   [ #  #  #  # ]:          0 :                 if (AR_SREV_9285E_20(ah)) {
     799                 :          0 :                         REG_WRITE(ah, AR9285_RF2G5,
     800                 :            :                                   (reg_rf2g5_org & AR9285_RF2G5_IC50TX) |
     801                 :            :                                   AR9285_RF2G5_IC50TX_XE_SET);
     802                 :            :                 } else {
     803                 :          0 :                         REG_WRITE(ah, AR9285_RF2G5,
     804                 :            :                                   (reg_rf2g5_org & AR9285_RF2G5_IC50TX) |
     805                 :            :                                   AR9285_RF2G5_IC50TX_SET);
     806                 :            :                 }
     807                 :          0 :                 retv = ar9285_hw_cl_cal(ah, chan);
     808                 :          0 :                 REG_WRITE(ah, AR9285_RF2G5, reg_rf2g5_org);
     809                 :            :         }
     810                 :            :         return retv;
     811                 :            : }
     812                 :            : 
     813                 :         20 : static bool ar9002_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan)
     814                 :            : {
     815         [ -  + ]:         20 :         struct ath_common *common = ath9k_hw_common(ah);
     816                 :            : 
     817         [ -  + ]:         20 :         if (AR_SREV_9271(ah)) {
     818         [ #  # ]:          0 :                 if (!ar9285_hw_cl_cal(ah, chan))
     819                 :            :                         return false;
     820         [ -  + ]:         20 :         } else if (AR_SREV_9285(ah) && AR_SREV_9285_12_OR_LATER(ah)) {
     821         [ #  # ]:          0 :                 if (!ar9285_hw_clc(ah, chan))
     822                 :            :                         return false;
     823                 :            :         } else {
     824         [ -  + ]:         20 :                 if (AR_SREV_9280_20_OR_LATER(ah)) {
     825         [ #  # ]:          0 :                         if (!AR_SREV_9287_11_OR_LATER(ah))
     826                 :          0 :                                 REG_CLR_BIT(ah, AR_PHY_ADC_CTL,
     827                 :            :                                             AR_PHY_ADC_CTL_OFF_PWDADC);
     828         [ #  # ]:          0 :                         REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
     829                 :            :                                     AR_PHY_AGC_CONTROL_FLTR_CAL);
     830                 :            :                 }
     831                 :            : 
     832                 :            :                 /* Calibrate the AGC */
     833         [ +  - ]:         40 :                 REG_WRITE(ah, AR_PHY_AGC_CONTROL,
     834                 :            :                           REG_READ(ah, AR_PHY_AGC_CONTROL) |
     835                 :            :                           AR_PHY_AGC_CONTROL_CAL);
     836                 :            : 
     837                 :            :                 /* Poll for offset calibration complete */
     838   [ +  -  -  + ]:         40 :                 if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL,
     839                 :            :                                    AR_PHY_AGC_CONTROL_CAL,
     840                 :            :                                    0, AH_WAIT_TIMEOUT)) {
     841         [ #  # ]:          0 :                         ath_dbg(common, CALIBRATE,
     842                 :            :                                 "offset calibration failed to complete in %d ms; noisy environment?\n",
     843                 :            :                                 AH_WAIT_TIMEOUT / 1000);
     844                 :          0 :                         return false;
     845                 :            :                 }
     846                 :            : 
     847         [ -  + ]:         20 :                 if (AR_SREV_9280_20_OR_LATER(ah)) {
     848         [ #  # ]:          0 :                         if (!AR_SREV_9287_11_OR_LATER(ah))
     849                 :          0 :                                 REG_SET_BIT(ah, AR_PHY_ADC_CTL,
     850                 :            :                                             AR_PHY_ADC_CTL_OFF_PWDADC);
     851         [ #  # ]:          0 :                         REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
     852                 :            :                                     AR_PHY_AGC_CONTROL_FLTR_CAL);
     853                 :            :                 }
     854                 :            :         }
     855                 :            : 
     856                 :            :         /* Do PA Calibration */
     857                 :         20 :         ar9002_hw_pa_cal(ah, true);
     858                 :         20 :         ath9k_hw_loadnf(ah, chan);
     859                 :         20 :         ath9k_hw_start_nfcal(ah, true);
     860                 :            : 
     861         [ +  + ]:         20 :         if (ah->caldata)
     862                 :         18 :                 set_bit(NFCAL_PENDING, &ah->caldata->cal_flags);
     863                 :            : 
     864                 :         20 :         ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL;
     865                 :            : 
     866                 :            :         /* Enable IQ, ADC Gain and ADC DC offset CALs */
     867   [ +  -  -  + ]:         20 :         if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) {
     868                 :          0 :                 ah->supp_cals = IQ_MISMATCH_CAL;
     869                 :            : 
     870         [ #  # ]:          0 :                 if (AR_SREV_9160_10_OR_LATER(ah))
     871                 :          0 :                         ah->supp_cals |= ADC_GAIN_CAL | ADC_DC_CAL;
     872                 :            : 
     873         [ #  # ]:          0 :                 if (AR_SREV_9287(ah))
     874                 :          0 :                         ah->supp_cals &= ~ADC_GAIN_CAL;
     875                 :            : 
     876         [ #  # ]:          0 :                 if (ar9002_hw_is_cal_supported(ah, chan, ADC_GAIN_CAL)) {
     877                 :          0 :                         INIT_CAL(&ah->adcgain_caldata);
     878                 :          0 :                         INSERT_CAL(ah, &ah->adcgain_caldata);
     879         [ #  # ]:          0 :                         ath_dbg(common, CALIBRATE,
     880                 :            :                                         "enabling ADC Gain Calibration\n");
     881                 :            :                 }
     882                 :            : 
     883         [ #  # ]:          0 :                 if (ar9002_hw_is_cal_supported(ah, chan, ADC_DC_CAL)) {
     884                 :          0 :                         INIT_CAL(&ah->adcdc_caldata);
     885         [ #  # ]:          0 :                         INSERT_CAL(ah, &ah->adcdc_caldata);
     886         [ #  # ]:          0 :                         ath_dbg(common, CALIBRATE,
     887                 :            :                                         "enabling ADC DC Calibration\n");
     888                 :            :                 }
     889                 :            : 
     890      [ #  #  # ]:          0 :                 if (ar9002_hw_is_cal_supported(ah, chan, IQ_MISMATCH_CAL)) {
     891                 :          0 :                         INIT_CAL(&ah->iq_caldata);
     892         [ #  # ]:          0 :                         INSERT_CAL(ah, &ah->iq_caldata);
     893         [ #  # ]:          0 :                         ath_dbg(common, CALIBRATE, "enabling IQ Calibration\n");
     894                 :            :                 }
     895                 :            : 
     896                 :          0 :                 ah->cal_list_curr = ah->cal_list;
     897                 :            : 
     898         [ #  # ]:          0 :                 if (ah->cal_list_curr)
     899                 :          0 :                         ath9k_hw_reset_calibration(ah, ah->cal_list_curr);
     900                 :            :         }
     901                 :            : 
     902         [ +  + ]:         20 :         if (ah->caldata)
     903                 :         18 :                 ah->caldata->CalValid = 0;
     904                 :            : 
     905                 :            :         return true;
     906                 :            : }
     907                 :            : 
     908                 :            : static const struct ath9k_percal_data iq_cal_multi_sample = {
     909                 :            :         IQ_MISMATCH_CAL,
     910                 :            :         MAX_CAL_SAMPLES,
     911                 :            :         PER_MIN_LOG_COUNT,
     912                 :            :         ar9002_hw_iqcal_collect,
     913                 :            :         ar9002_hw_iqcalibrate
     914                 :            : };
     915                 :            : static const struct ath9k_percal_data iq_cal_single_sample = {
     916                 :            :         IQ_MISMATCH_CAL,
     917                 :            :         MIN_CAL_SAMPLES,
     918                 :            :         PER_MAX_LOG_COUNT,
     919                 :            :         ar9002_hw_iqcal_collect,
     920                 :            :         ar9002_hw_iqcalibrate
     921                 :            : };
     922                 :            : static const struct ath9k_percal_data adc_gain_cal_multi_sample = {
     923                 :            :         ADC_GAIN_CAL,
     924                 :            :         MAX_CAL_SAMPLES,
     925                 :            :         PER_MIN_LOG_COUNT,
     926                 :            :         ar9002_hw_adc_gaincal_collect,
     927                 :            :         ar9002_hw_adc_gaincal_calibrate
     928                 :            : };
     929                 :            : static const struct ath9k_percal_data adc_gain_cal_single_sample = {
     930                 :            :         ADC_GAIN_CAL,
     931                 :            :         MIN_CAL_SAMPLES,
     932                 :            :         PER_MAX_LOG_COUNT,
     933                 :            :         ar9002_hw_adc_gaincal_collect,
     934                 :            :         ar9002_hw_adc_gaincal_calibrate
     935                 :            : };
     936                 :            : static const struct ath9k_percal_data adc_dc_cal_multi_sample = {
     937                 :            :         ADC_DC_CAL,
     938                 :            :         MAX_CAL_SAMPLES,
     939                 :            :         PER_MIN_LOG_COUNT,
     940                 :            :         ar9002_hw_adc_dccal_collect,
     941                 :            :         ar9002_hw_adc_dccal_calibrate
     942                 :            : };
     943                 :            : static const struct ath9k_percal_data adc_dc_cal_single_sample = {
     944                 :            :         ADC_DC_CAL,
     945                 :            :         MIN_CAL_SAMPLES,
     946                 :            :         PER_MAX_LOG_COUNT,
     947                 :            :         ar9002_hw_adc_dccal_collect,
     948                 :            :         ar9002_hw_adc_dccal_calibrate
     949                 :            : };
     950                 :            : 
     951                 :         22 : static void ar9002_hw_init_cal_settings(struct ath_hw *ah)
     952                 :            : {
     953         [ -  + ]:         22 :         if (AR_SREV_9100(ah)) {
     954                 :          0 :                 ah->iq_caldata.calData = &iq_cal_multi_sample;
     955                 :          0 :                 ah->supp_cals = IQ_MISMATCH_CAL;
     956                 :          0 :                 return;
     957                 :            :         }
     958                 :            : 
     959         [ -  + ]:         22 :         if (AR_SREV_9160_10_OR_LATER(ah)) {
     960         [ #  # ]:          0 :                 if (AR_SREV_9280_20_OR_LATER(ah)) {
     961                 :          0 :                         ah->iq_caldata.calData = &iq_cal_single_sample;
     962                 :          0 :                         ah->adcgain_caldata.calData =
     963                 :            :                                 &adc_gain_cal_single_sample;
     964                 :          0 :                         ah->adcdc_caldata.calData =
     965                 :            :                                 &adc_dc_cal_single_sample;
     966                 :            :                 } else {
     967                 :          0 :                         ah->iq_caldata.calData = &iq_cal_multi_sample;
     968                 :          0 :                         ah->adcgain_caldata.calData =
     969                 :            :                                 &adc_gain_cal_multi_sample;
     970                 :          0 :                         ah->adcdc_caldata.calData =
     971                 :            :                                 &adc_dc_cal_multi_sample;
     972                 :            :                 }
     973                 :          0 :                 ah->supp_cals = ADC_GAIN_CAL | ADC_DC_CAL | IQ_MISMATCH_CAL;
     974                 :            : 
     975         [ #  # ]:          0 :                 if (AR_SREV_9287(ah))
     976                 :          0 :                         ah->supp_cals &= ~ADC_GAIN_CAL;
     977                 :            :         }
     978                 :            : }
     979                 :            : 
     980                 :         22 : void ar9002_hw_attach_calib_ops(struct ath_hw *ah)
     981                 :            : {
     982                 :         22 :         struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
     983                 :         22 :         struct ath_hw_ops *ops = ath9k_hw_ops(ah);
     984                 :            : 
     985                 :         22 :         priv_ops->init_cal_settings = ar9002_hw_init_cal_settings;
     986                 :         22 :         priv_ops->init_cal = ar9002_hw_init_cal;
     987                 :         22 :         priv_ops->setup_calibration = ar9002_hw_setup_calibration;
     988                 :            : 
     989                 :         22 :         ops->calibrate = ar9002_hw_calibrate;
     990                 :         22 : }

Generated by: LCOV version 1.14