LCOV - code coverage report
Current view: top level - drivers/net/wireless/ath/ath9k - ar9003_calib.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 332 763 43.5 %
Date: 2022-03-28 13:20:08 Functions: 14 23 60.9 %
Branches: 212 646 32.8 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright (c) 2010-2011 Atheros Communications Inc.
       3                 :            :  *
       4                 :            :  * Permission to use, copy, modify, and/or distribute this software for any
       5                 :            :  * purpose with or without fee is hereby granted, provided that the above
       6                 :            :  * copyright notice and this permission notice appear in all copies.
       7                 :            :  *
       8                 :            :  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
       9                 :            :  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
      10                 :            :  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
      11                 :            :  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
      12                 :            :  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
      13                 :            :  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
      14                 :            :  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
      15                 :            :  */
      16                 :            : 
      17                 :            : #include "hw.h"
      18                 :            : #include "hw-ops.h"
      19                 :            : #include "ar9003_phy.h"
      20                 :            : #include "ar9003_rtt.h"
      21                 :            : #include "ar9003_mci.h"
      22                 :            : 
      23                 :            : #define MAX_MEASUREMENT MAX_IQCAL_MEASUREMENT
      24                 :            : #define MAX_MAG_DELTA   11
      25                 :            : #define MAX_PHS_DELTA   10
      26                 :            : #define MAXIQCAL        3
      27                 :            : 
      28                 :            : struct coeff {
      29                 :            :         int mag_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT][MAXIQCAL];
      30                 :            :         int phs_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT][MAXIQCAL];
      31                 :            :         int iqc_coeff[2];
      32                 :            : };
      33                 :            : 
      34                 :            : enum ar9003_cal_types {
      35                 :            :         IQ_MISMATCH_CAL = BIT(0),
      36                 :            : };
      37                 :            : 
      38                 :         41 : static void ar9003_hw_setup_calibration(struct ath_hw *ah,
      39                 :            :                                         struct ath9k_cal_list *currCal)
      40                 :            : {
      41         [ +  - ]:         41 :         struct ath_common *common = ath9k_hw_common(ah);
      42                 :            : 
      43                 :            :         /* Select calibration to run */
      44         [ +  - ]:         41 :         switch (currCal->calData->calType) {
      45                 :         41 :         case IQ_MISMATCH_CAL:
      46                 :            :                 /*
      47                 :            :                  * Start calibration with
      48                 :            :                  * 2^(INIT_IQCAL_LOG_COUNT_MAX+1) samples
      49                 :            :                  */
      50                 :         41 :                 REG_RMW_FIELD(ah, AR_PHY_TIMING4,
      51                 :            :                               AR_PHY_TIMING4_IQCAL_LOG_COUNT_MAX,
      52                 :            :                               currCal->calData->calCountMax);
      53                 :         41 :                 REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ);
      54                 :            : 
      55         [ -  + ]:         41 :                 ath_dbg(common, CALIBRATE,
      56                 :            :                         "starting IQ Mismatch Calibration\n");
      57                 :            : 
      58                 :            :                 /* Kick-off cal */
      59                 :         41 :                 REG_SET_BIT(ah, AR_PHY_TIMING4, AR_PHY_TIMING4_DO_CAL);
      60                 :         41 :                 break;
      61                 :          0 :         default:
      62                 :          0 :                 ath_err(common, "Invalid calibration type\n");
      63                 :          0 :                 break;
      64                 :            :         }
      65                 :         41 : }
      66                 :            : 
      67                 :            : /*
      68                 :            :  * Generic calibration routine.
      69                 :            :  * Recalibrate the lower PHY chips to account for temperature/environment
      70                 :            :  * changes.
      71                 :            :  */
      72                 :          0 : static bool ar9003_hw_per_calibration(struct ath_hw *ah,
      73                 :            :                                       struct ath9k_channel *ichan,
      74                 :            :                                       u8 rxchainmask,
      75                 :            :                                       struct ath9k_cal_list *currCal)
      76                 :            : {
      77                 :          0 :         struct ath9k_hw_cal_data *caldata = ah->caldata;
      78                 :          0 :         const struct ath9k_percal_data *cur_caldata = currCal->calData;
      79                 :            : 
      80                 :            :         /* Calibration in progress. */
      81         [ #  # ]:          0 :         if (currCal->calState == CAL_RUNNING) {
      82                 :            :                 /* Check to see if it has finished. */
      83         [ #  # ]:          0 :                 if (REG_READ(ah, AR_PHY_TIMING4) & AR_PHY_TIMING4_DO_CAL)
      84                 :            :                         return false;
      85                 :            : 
      86                 :            :                 /*
      87                 :            :                 * Accumulate cal measures for active chains
      88                 :            :                 */
      89                 :          0 :                 cur_caldata->calCollect(ah);
      90                 :          0 :                 ah->cal_samples++;
      91                 :            : 
      92         [ #  # ]:          0 :                 if (ah->cal_samples >= cur_caldata->calNumSamples) {
      93                 :            :                         unsigned int i, numChains = 0;
      94         [ #  # ]:          0 :                         for (i = 0; i < AR9300_MAX_CHAINS; i++) {
      95         [ #  # ]:          0 :                                 if (rxchainmask & (1 << i))
      96                 :          0 :                                         numChains++;
      97                 :            :                         }
      98                 :            : 
      99                 :            :                         /*
     100                 :            :                         * Process accumulated data
     101                 :            :                         */
     102                 :          0 :                         cur_caldata->calPostProc(ah, numChains);
     103                 :            : 
     104                 :            :                         /* Calibration has finished. */
     105                 :          0 :                         caldata->CalValid |= cur_caldata->calType;
     106                 :          0 :                         currCal->calState = CAL_DONE;
     107                 :          0 :                         return true;
     108                 :            :                 } else {
     109                 :            :                         /*
     110                 :            :                          * Set-up collection of another sub-sample until we
     111                 :            :                          * get desired number
     112                 :            :                          */
     113                 :          0 :                         ar9003_hw_setup_calibration(ah, currCal);
     114                 :            :                 }
     115         [ #  # ]:          0 :         } else if (!(caldata->CalValid & cur_caldata->calType)) {
     116                 :            :                 /* If current cal is marked invalid in channel, kick it off */
     117                 :          0 :                 ath9k_hw_reset_calibration(ah, currCal);
     118                 :            :         }
     119                 :            : 
     120                 :            :         return false;
     121                 :            : }
     122                 :            : 
     123                 :          0 : static int ar9003_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan,
     124                 :            :                                u8 rxchainmask, bool longcal)
     125                 :            : {
     126                 :          0 :         bool iscaldone = true;
     127                 :          0 :         struct ath9k_cal_list *currCal = ah->cal_list_curr;
     128                 :          0 :         int ret;
     129                 :            : 
     130                 :            :         /*
     131                 :            :          * For given calibration:
     132                 :            :          * 1. Call generic cal routine
     133                 :            :          * 2. When this cal is done (isCalDone) if we have more cals waiting
     134                 :            :          *    (eg after reset), mask this to upper layers by not propagating
     135                 :            :          *    isCalDone if it is set to TRUE.
     136                 :            :          *    Instead, change isCalDone to FALSE and setup the waiting cal(s)
     137                 :            :          *    to be run.
     138                 :            :          */
     139         [ #  # ]:          0 :         if (currCal &&
     140         [ #  # ]:          0 :             (currCal->calState == CAL_RUNNING ||
     141                 :            :              currCal->calState == CAL_WAITING)) {
     142                 :          0 :                 iscaldone = ar9003_hw_per_calibration(ah, chan,
     143                 :            :                                                       rxchainmask, currCal);
     144         [ #  # ]:          0 :                 if (iscaldone) {
     145                 :          0 :                         ah->cal_list_curr = currCal = currCal->calNext;
     146                 :            : 
     147         [ #  # ]:          0 :                         if (currCal->calState == CAL_WAITING) {
     148                 :          0 :                                 iscaldone = false;
     149                 :          0 :                                 ath9k_hw_reset_calibration(ah, currCal);
     150                 :            :                         }
     151                 :            :                 }
     152                 :            :         }
     153                 :            : 
     154                 :            :         /*
     155                 :            :          * Do NF cal only at longer intervals. Get the value from
     156                 :            :          * the previous NF cal and update history buffer.
     157                 :            :          */
     158   [ #  #  #  # ]:          0 :         if (longcal && ath9k_hw_getnf(ah, chan)) {
     159                 :            :                 /*
     160                 :            :                  * Load the NF from history buffer of the current channel.
     161                 :            :                  * NF is slow time-variant, so it is OK to use a historical
     162                 :            :                  * value.
     163                 :            :                  */
     164                 :          0 :                 ret = ath9k_hw_loadnf(ah, ah->curchan);
     165         [ #  # ]:          0 :                 if (ret < 0)
     166                 :            :                         return ret;
     167                 :            : 
     168                 :            :                 /* start NF calibration, without updating BB NF register */
     169                 :          0 :                 ath9k_hw_start_nfcal(ah, false);
     170                 :            :         }
     171                 :            : 
     172                 :          0 :         return iscaldone;
     173                 :            : }
     174                 :            : 
     175                 :          0 : static void ar9003_hw_iqcal_collect(struct ath_hw *ah)
     176                 :            : {
     177                 :          0 :         int i;
     178                 :            : 
     179                 :            :         /* Accumulate IQ cal measures for active chains */
     180         [ #  # ]:          0 :         for (i = 0; i < AR5416_MAX_CHAINS; i++) {
     181         [ #  # ]:          0 :                 if (ah->txchainmask & BIT(i)) {
     182                 :          0 :                         ah->totalPowerMeasI[i] +=
     183                 :          0 :                                 REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
     184                 :          0 :                         ah->totalPowerMeasQ[i] +=
     185                 :          0 :                                 REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
     186                 :          0 :                         ah->totalIqCorrMeas[i] +=
     187                 :          0 :                                 (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
     188         [ #  # ]:          0 :                         ath_dbg(ath9k_hw_common(ah), CALIBRATE,
     189                 :            :                                 "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n",
     190                 :            :                                 ah->cal_samples, i, ah->totalPowerMeasI[i],
     191                 :            :                                 ah->totalPowerMeasQ[i],
     192                 :            :                                 ah->totalIqCorrMeas[i]);
     193                 :            :                 }
     194                 :            :         }
     195                 :          0 : }
     196                 :            : 
     197                 :          0 : static void ar9003_hw_iqcalibrate(struct ath_hw *ah, u8 numChains)
     198                 :            : {
     199                 :          0 :         struct ath_common *common = ath9k_hw_common(ah);
     200                 :          0 :         u32 powerMeasQ, powerMeasI, iqCorrMeas;
     201                 :          0 :         u32 qCoffDenom, iCoffDenom;
     202                 :          0 :         int32_t qCoff, iCoff;
     203                 :          0 :         int iqCorrNeg, i;
     204                 :          0 :         static const u_int32_t offset_array[3] = {
     205                 :            :                 AR_PHY_RX_IQCAL_CORR_B0,
     206                 :            :                 AR_PHY_RX_IQCAL_CORR_B1,
     207                 :            :                 AR_PHY_RX_IQCAL_CORR_B2,
     208                 :            :         };
     209                 :            : 
     210         [ #  # ]:          0 :         for (i = 0; i < numChains; i++) {
     211                 :          0 :                 powerMeasI = ah->totalPowerMeasI[i];
     212                 :          0 :                 powerMeasQ = ah->totalPowerMeasQ[i];
     213                 :          0 :                 iqCorrMeas = ah->totalIqCorrMeas[i];
     214                 :            : 
     215         [ #  # ]:          0 :                 ath_dbg(common, CALIBRATE,
     216                 :            :                         "Starting IQ Cal and Correction for Chain %d\n", i);
     217                 :            : 
     218         [ #  # ]:          0 :                 ath_dbg(common, CALIBRATE,
     219                 :            :                         "Original: Chn %d iq_corr_meas = 0x%08x\n",
     220                 :            :                         i, ah->totalIqCorrMeas[i]);
     221                 :            : 
     222                 :          0 :                 iqCorrNeg = 0;
     223                 :            : 
     224         [ #  # ]:          0 :                 if (iqCorrMeas > 0x80000000) {
     225                 :          0 :                         iqCorrMeas = (0xffffffff - iqCorrMeas) + 1;
     226                 :          0 :                         iqCorrNeg = 1;
     227                 :            :                 }
     228                 :            : 
     229         [ #  # ]:          0 :                 ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_i = 0x%08x\n",
     230                 :            :                         i, powerMeasI);
     231         [ #  # ]:          0 :                 ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_q = 0x%08x\n",
     232                 :            :                         i, powerMeasQ);
     233         [ #  # ]:          0 :                 ath_dbg(common, CALIBRATE, "iqCorrNeg is 0x%08x\n", iqCorrNeg);
     234                 :            : 
     235                 :          0 :                 iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 256;
     236                 :          0 :                 qCoffDenom = powerMeasQ / 64;
     237                 :            : 
     238   [ #  #  #  # ]:          0 :                 if ((iCoffDenom != 0) && (qCoffDenom != 0)) {
     239                 :          0 :                         iCoff = iqCorrMeas / iCoffDenom;
     240                 :          0 :                         qCoff = powerMeasI / qCoffDenom - 64;
     241         [ #  # ]:          0 :                         ath_dbg(common, CALIBRATE, "Chn %d iCoff = 0x%08x\n",
     242                 :            :                                 i, iCoff);
     243         [ #  # ]:          0 :                         ath_dbg(common, CALIBRATE, "Chn %d qCoff = 0x%08x\n",
     244                 :            :                                 i, qCoff);
     245                 :            : 
     246                 :            :                         /* Force bounds on iCoff */
     247                 :          0 :                         if (iCoff >= 63)
     248                 :            :                                 iCoff = 63;
     249                 :            :                         else if (iCoff <= -63)
     250                 :            :                                 iCoff = -63;
     251                 :            : 
     252                 :            :                         /* Negate iCoff if iqCorrNeg == 0 */
     253         [ #  # ]:          0 :                         if (iqCorrNeg == 0x0)
     254                 :          0 :                                 iCoff = -iCoff;
     255                 :            : 
     256                 :            :                         /* Force bounds on qCoff */
     257                 :          0 :                         if (qCoff >= 63)
     258                 :            :                                 qCoff = 63;
     259                 :            :                         else if (qCoff <= -63)
     260                 :            :                                 qCoff = -63;
     261                 :            : 
     262                 :          0 :                         iCoff = iCoff & 0x7f;
     263                 :          0 :                         qCoff = qCoff & 0x7f;
     264                 :            : 
     265         [ #  # ]:          0 :                         ath_dbg(common, CALIBRATE,
     266                 :            :                                 "Chn %d : iCoff = 0x%x  qCoff = 0x%x\n",
     267                 :            :                                 i, iCoff, qCoff);
     268         [ #  # ]:          0 :                         ath_dbg(common, CALIBRATE,
     269                 :            :                                 "Register offset (0x%04x) before update = 0x%x\n",
     270                 :            :                                 offset_array[i],
     271                 :            :                                 REG_READ(ah, offset_array[i]));
     272                 :            : 
     273   [ #  #  #  # ]:          0 :                         if (AR_SREV_9565(ah) &&
     274         [ #  # ]:          0 :                             (iCoff == 63 || qCoff == 63 ||
     275                 :            :                              iCoff == -63 || qCoff == -63))
     276                 :            :                                 return;
     277                 :            : 
     278                 :          0 :                         REG_RMW_FIELD(ah, offset_array[i],
     279                 :            :                                       AR_PHY_RX_IQCAL_CORR_IQCORR_Q_I_COFF,
     280                 :            :                                       iCoff);
     281                 :          0 :                         REG_RMW_FIELD(ah, offset_array[i],
     282                 :            :                                       AR_PHY_RX_IQCAL_CORR_IQCORR_Q_Q_COFF,
     283                 :            :                                       qCoff);
     284         [ #  # ]:          0 :                         ath_dbg(common, CALIBRATE,
     285                 :            :                                 "Register offset (0x%04x) QI COFF (bitfields 0x%08x) after update = 0x%x\n",
     286                 :            :                                 offset_array[i],
     287                 :            :                                 AR_PHY_RX_IQCAL_CORR_IQCORR_Q_I_COFF,
     288                 :            :                                 REG_READ(ah, offset_array[i]));
     289         [ #  # ]:          0 :                         ath_dbg(common, CALIBRATE,
     290                 :            :                                 "Register offset (0x%04x) QQ COFF (bitfields 0x%08x) after update = 0x%x\n",
     291                 :            :                                 offset_array[i],
     292                 :            :                                 AR_PHY_RX_IQCAL_CORR_IQCORR_Q_Q_COFF,
     293                 :            :                                 REG_READ(ah, offset_array[i]));
     294                 :            : 
     295         [ #  # ]:          0 :                         ath_dbg(common, CALIBRATE,
     296                 :            :                                 "IQ Cal and Correction done for Chain %d\n", i);
     297                 :            :                 }
     298                 :            :         }
     299                 :            : 
     300                 :          0 :         REG_SET_BIT(ah, AR_PHY_RX_IQCAL_CORR_B0,
     301                 :            :                     AR_PHY_RX_IQCAL_CORR_IQCORR_ENABLE);
     302         [ #  # ]:          0 :         ath_dbg(common, CALIBRATE,
     303                 :            :                 "IQ Cal and Correction (offset 0x%04x) enabled (bit position 0x%08x). New Value 0x%08x\n",
     304                 :            :                 (unsigned) (AR_PHY_RX_IQCAL_CORR_B0),
     305                 :            :                 AR_PHY_RX_IQCAL_CORR_IQCORR_ENABLE,
     306                 :            :                 REG_READ(ah, AR_PHY_RX_IQCAL_CORR_B0));
     307                 :            : }
     308                 :            : 
     309                 :            : static const struct ath9k_percal_data iq_cal_single_sample = {
     310                 :            :         IQ_MISMATCH_CAL,
     311                 :            :         MIN_CAL_SAMPLES,
     312                 :            :         PER_MAX_LOG_COUNT,
     313                 :            :         ar9003_hw_iqcal_collect,
     314                 :            :         ar9003_hw_iqcalibrate
     315                 :            : };
     316                 :            : 
     317                 :          5 : static void ar9003_hw_init_cal_settings(struct ath_hw *ah)
     318                 :            : {
     319                 :          5 :         ah->iq_caldata.calData = &iq_cal_single_sample;
     320                 :            : 
     321         [ +  - ]:          5 :         if (AR_SREV_9300_20_OR_LATER(ah)) {
     322                 :          5 :                 ah->enabled_cals |= TX_IQ_CAL;
     323   [ +  +  +  - ]:          5 :                 if (AR_SREV_9485_OR_LATER(ah) && !AR_SREV_9340(ah))
     324                 :          3 :                         ah->enabled_cals |= TX_IQ_ON_AGC_CAL;
     325                 :            :         }
     326                 :            : 
     327                 :          5 :         ah->supp_cals = IQ_MISMATCH_CAL;
     328                 :          5 : }
     329                 :            : 
     330                 :            : #define OFF_UPPER_LT 24
     331                 :            : #define OFF_LOWER_LT 7
     332                 :            : 
     333                 :          0 : static bool ar9003_hw_dynamic_osdac_selection(struct ath_hw *ah,
     334                 :            :                                               bool txiqcal_done)
     335                 :            : {
     336         [ #  # ]:          0 :         struct ath_common *common = ath9k_hw_common(ah);
     337                 :          0 :         int ch0_done, osdac_ch0, dc_off_ch0_i1, dc_off_ch0_q1, dc_off_ch0_i2,
     338                 :            :                 dc_off_ch0_q2, dc_off_ch0_i3, dc_off_ch0_q3;
     339                 :          0 :         int ch1_done, osdac_ch1, dc_off_ch1_i1, dc_off_ch1_q1, dc_off_ch1_i2,
     340                 :            :                 dc_off_ch1_q2, dc_off_ch1_i3, dc_off_ch1_q3;
     341                 :          0 :         int ch2_done, osdac_ch2, dc_off_ch2_i1, dc_off_ch2_q1, dc_off_ch2_i2,
     342                 :            :                 dc_off_ch2_q2, dc_off_ch2_i3, dc_off_ch2_q3;
     343                 :          0 :         bool status;
     344                 :          0 :         u32 temp, val;
     345                 :            : 
     346                 :            :         /*
     347                 :            :          * Clear offset and IQ calibration, run AGC cal.
     348                 :            :          */
     349         [ #  # ]:          0 :         REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
     350                 :            :                     AR_PHY_AGC_CONTROL_OFFSET_CAL);
     351         [ #  # ]:          0 :         REG_CLR_BIT(ah, AR_PHY_TX_IQCAL_CONTROL_0,
     352                 :            :                     AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL);
     353         [ #  # ]:          0 :         REG_WRITE(ah, AR_PHY_AGC_CONTROL,
     354                 :            :                   REG_READ(ah, AR_PHY_AGC_CONTROL) | AR_PHY_AGC_CONTROL_CAL);
     355                 :            : 
     356         [ #  # ]:          0 :         status = ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL,
     357                 :            :                                AR_PHY_AGC_CONTROL_CAL,
     358                 :            :                                0, AH_WAIT_TIMEOUT);
     359         [ #  # ]:          0 :         if (!status) {
     360         [ #  # ]:          0 :                 ath_dbg(common, CALIBRATE,
     361                 :            :                         "AGC cal without offset cal failed to complete in 1ms");
     362                 :          0 :                 return false;
     363                 :            :         }
     364                 :            : 
     365                 :            :         /*
     366                 :            :          * Allow only offset calibration and disable the others
     367                 :            :          * (Carrier Leak calibration, TX Filter calibration and
     368                 :            :          *  Peak Detector offset calibration).
     369                 :            :          */
     370         [ #  # ]:          0 :         REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
     371                 :            :                     AR_PHY_AGC_CONTROL_OFFSET_CAL);
     372                 :          0 :         REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL,
     373                 :            :                     AR_PHY_CL_CAL_ENABLE);
     374         [ #  # ]:          0 :         REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
     375                 :            :                     AR_PHY_AGC_CONTROL_FLTR_CAL);
     376         [ #  # ]:          0 :         REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
     377                 :            :                     AR_PHY_AGC_CONTROL_PKDET_CAL);
     378                 :            : 
     379                 :          0 :         ch0_done = 0;
     380                 :          0 :         ch1_done = 0;
     381                 :          0 :         ch2_done = 0;
     382                 :            : 
     383   [ #  #  #  #  :          0 :         while ((ch0_done == 0) || (ch1_done == 0) || (ch2_done == 0)) {
                   #  # ]
     384                 :          0 :                 osdac_ch0 = (REG_READ(ah, AR_PHY_65NM_CH0_BB1) >> 30) & 0x3;
     385                 :          0 :                 osdac_ch1 = (REG_READ(ah, AR_PHY_65NM_CH1_BB1) >> 30) & 0x3;
     386                 :          0 :                 osdac_ch2 = (REG_READ(ah, AR_PHY_65NM_CH2_BB1) >> 30) & 0x3;
     387                 :            : 
     388                 :          0 :                 REG_SET_BIT(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
     389                 :            : 
     390         [ #  # ]:          0 :                 REG_WRITE(ah, AR_PHY_AGC_CONTROL,
     391                 :            :                           REG_READ(ah, AR_PHY_AGC_CONTROL) | AR_PHY_AGC_CONTROL_CAL);
     392                 :            : 
     393         [ #  # ]:          0 :                 status = ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL,
     394                 :            :                                        AR_PHY_AGC_CONTROL_CAL,
     395                 :            :                                        0, AH_WAIT_TIMEOUT);
     396         [ #  # ]:          0 :                 if (!status) {
     397         [ #  # ]:          0 :                         ath_dbg(common, CALIBRATE,
     398                 :            :                                 "DC offset cal failed to complete in 1ms");
     399                 :          0 :                         return false;
     400                 :            :                 }
     401                 :            : 
     402                 :          0 :                 REG_CLR_BIT(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
     403                 :            : 
     404                 :            :                 /*
     405                 :            :                  * High gain.
     406                 :            :                  */
     407                 :          0 :                 REG_WRITE(ah, AR_PHY_65NM_CH0_BB3,
     408                 :            :                           ((REG_READ(ah, AR_PHY_65NM_CH0_BB3) & 0xfffffcff) | (1 << 8)));
     409                 :          0 :                 REG_WRITE(ah, AR_PHY_65NM_CH1_BB3,
     410                 :            :                           ((REG_READ(ah, AR_PHY_65NM_CH1_BB3) & 0xfffffcff) | (1 << 8)));
     411                 :          0 :                 REG_WRITE(ah, AR_PHY_65NM_CH2_BB3,
     412                 :            :                           ((REG_READ(ah, AR_PHY_65NM_CH2_BB3) & 0xfffffcff) | (1 << 8)));
     413                 :            : 
     414                 :          0 :                 temp = REG_READ(ah, AR_PHY_65NM_CH0_BB3);
     415                 :          0 :                 dc_off_ch0_i1 = (temp >> 26) & 0x1f;
     416                 :          0 :                 dc_off_ch0_q1 = (temp >> 21) & 0x1f;
     417                 :            : 
     418                 :          0 :                 temp = REG_READ(ah, AR_PHY_65NM_CH1_BB3);
     419                 :          0 :                 dc_off_ch1_i1 = (temp >> 26) & 0x1f;
     420                 :          0 :                 dc_off_ch1_q1 = (temp >> 21) & 0x1f;
     421                 :            : 
     422                 :          0 :                 temp = REG_READ(ah, AR_PHY_65NM_CH2_BB3);
     423                 :          0 :                 dc_off_ch2_i1 = (temp >> 26) & 0x1f;
     424                 :          0 :                 dc_off_ch2_q1 = (temp >> 21) & 0x1f;
     425                 :            : 
     426                 :            :                 /*
     427                 :            :                  * Low gain.
     428                 :            :                  */
     429                 :          0 :                 REG_WRITE(ah, AR_PHY_65NM_CH0_BB3,
     430                 :            :                           ((REG_READ(ah, AR_PHY_65NM_CH0_BB3) & 0xfffffcff) | (2 << 8)));
     431                 :          0 :                 REG_WRITE(ah, AR_PHY_65NM_CH1_BB3,
     432                 :            :                           ((REG_READ(ah, AR_PHY_65NM_CH1_BB3) & 0xfffffcff) | (2 << 8)));
     433                 :          0 :                 REG_WRITE(ah, AR_PHY_65NM_CH2_BB3,
     434                 :            :                           ((REG_READ(ah, AR_PHY_65NM_CH2_BB3) & 0xfffffcff) | (2 << 8)));
     435                 :            : 
     436                 :          0 :                 temp = REG_READ(ah, AR_PHY_65NM_CH0_BB3);
     437                 :          0 :                 dc_off_ch0_i2 = (temp >> 26) & 0x1f;
     438                 :          0 :                 dc_off_ch0_q2 = (temp >> 21) & 0x1f;
     439                 :            : 
     440                 :          0 :                 temp = REG_READ(ah, AR_PHY_65NM_CH1_BB3);
     441                 :          0 :                 dc_off_ch1_i2 = (temp >> 26) & 0x1f;
     442                 :          0 :                 dc_off_ch1_q2 = (temp >> 21) & 0x1f;
     443                 :            : 
     444                 :          0 :                 temp = REG_READ(ah, AR_PHY_65NM_CH2_BB3);
     445                 :          0 :                 dc_off_ch2_i2 = (temp >> 26) & 0x1f;
     446                 :          0 :                 dc_off_ch2_q2 = (temp >> 21) & 0x1f;
     447                 :            : 
     448                 :            :                 /*
     449                 :            :                  * Loopback.
     450                 :            :                  */
     451                 :          0 :                 REG_WRITE(ah, AR_PHY_65NM_CH0_BB3,
     452                 :            :                           ((REG_READ(ah, AR_PHY_65NM_CH0_BB3) & 0xfffffcff) | (3 << 8)));
     453                 :          0 :                 REG_WRITE(ah, AR_PHY_65NM_CH1_BB3,
     454                 :            :                           ((REG_READ(ah, AR_PHY_65NM_CH1_BB3) & 0xfffffcff) | (3 << 8)));
     455                 :          0 :                 REG_WRITE(ah, AR_PHY_65NM_CH2_BB3,
     456                 :            :                           ((REG_READ(ah, AR_PHY_65NM_CH2_BB3) & 0xfffffcff) | (3 << 8)));
     457                 :            : 
     458                 :          0 :                 temp = REG_READ(ah, AR_PHY_65NM_CH0_BB3);
     459                 :          0 :                 dc_off_ch0_i3 = (temp >> 26) & 0x1f;
     460                 :          0 :                 dc_off_ch0_q3 = (temp >> 21) & 0x1f;
     461                 :            : 
     462                 :          0 :                 temp = REG_READ(ah, AR_PHY_65NM_CH1_BB3);
     463                 :          0 :                 dc_off_ch1_i3 = (temp >> 26) & 0x1f;
     464                 :          0 :                 dc_off_ch1_q3 = (temp >> 21) & 0x1f;
     465                 :            : 
     466                 :          0 :                 temp = REG_READ(ah, AR_PHY_65NM_CH2_BB3);
     467                 :          0 :                 dc_off_ch2_i3 = (temp >> 26) & 0x1f;
     468                 :          0 :                 dc_off_ch2_q3 = (temp >> 21) & 0x1f;
     469                 :            : 
     470   [ #  #  #  # ]:          0 :                 if ((dc_off_ch0_i1 > OFF_UPPER_LT) || (dc_off_ch0_i1 < OFF_LOWER_LT) ||
     471   [ #  #  #  # ]:          0 :                     (dc_off_ch0_i2 > OFF_UPPER_LT) || (dc_off_ch0_i2 < OFF_LOWER_LT) ||
     472   [ #  #  #  # ]:          0 :                     (dc_off_ch0_i3 > OFF_UPPER_LT) || (dc_off_ch0_i3 < OFF_LOWER_LT) ||
     473   [ #  #  #  # ]:          0 :                     (dc_off_ch0_q1 > OFF_UPPER_LT) || (dc_off_ch0_q1 < OFF_LOWER_LT) ||
     474   [ #  #  #  # ]:          0 :                     (dc_off_ch0_q2 > OFF_UPPER_LT) || (dc_off_ch0_q2 < OFF_LOWER_LT) ||
     475         [ #  # ]:          0 :                     (dc_off_ch0_q3 > OFF_UPPER_LT) || (dc_off_ch0_q3 < OFF_LOWER_LT)) {
     476         [ #  # ]:          0 :                         if (osdac_ch0 == 3) {
     477                 :            :                                 ch0_done = 1;
     478                 :            :                         } else {
     479                 :          0 :                                 osdac_ch0++;
     480                 :            : 
     481                 :          0 :                                 val = REG_READ(ah, AR_PHY_65NM_CH0_BB1) & 0x3fffffff;
     482                 :          0 :                                 val |= (osdac_ch0 << 30);
     483                 :          0 :                                 REG_WRITE(ah, AR_PHY_65NM_CH0_BB1, val);
     484                 :            : 
     485                 :          0 :                                 ch0_done = 0;
     486                 :            :                         }
     487                 :            :                 } else {
     488                 :            :                         ch0_done = 1;
     489                 :            :                 }
     490                 :            : 
     491   [ #  #  #  # ]:          0 :                 if ((dc_off_ch1_i1 > OFF_UPPER_LT) || (dc_off_ch1_i1 < OFF_LOWER_LT) ||
     492   [ #  #  #  # ]:          0 :                     (dc_off_ch1_i2 > OFF_UPPER_LT) || (dc_off_ch1_i2 < OFF_LOWER_LT) ||
     493   [ #  #  #  # ]:          0 :                     (dc_off_ch1_i3 > OFF_UPPER_LT) || (dc_off_ch1_i3 < OFF_LOWER_LT) ||
     494   [ #  #  #  # ]:          0 :                     (dc_off_ch1_q1 > OFF_UPPER_LT) || (dc_off_ch1_q1 < OFF_LOWER_LT) ||
     495   [ #  #  #  # ]:          0 :                     (dc_off_ch1_q2 > OFF_UPPER_LT) || (dc_off_ch1_q2 < OFF_LOWER_LT) ||
     496         [ #  # ]:          0 :                     (dc_off_ch1_q3 > OFF_UPPER_LT) || (dc_off_ch1_q3 < OFF_LOWER_LT)) {
     497         [ #  # ]:          0 :                         if (osdac_ch1 == 3) {
     498                 :            :                                 ch1_done = 1;
     499                 :            :                         } else {
     500                 :          0 :                                 osdac_ch1++;
     501                 :            : 
     502                 :          0 :                                 val = REG_READ(ah, AR_PHY_65NM_CH1_BB1) & 0x3fffffff;
     503                 :          0 :                                 val |= (osdac_ch1 << 30);
     504                 :          0 :                                 REG_WRITE(ah, AR_PHY_65NM_CH1_BB1, val);
     505                 :            : 
     506                 :          0 :                                 ch1_done = 0;
     507                 :            :                         }
     508                 :            :                 } else {
     509                 :            :                         ch1_done = 1;
     510                 :            :                 }
     511                 :            : 
     512   [ #  #  #  # ]:          0 :                 if ((dc_off_ch2_i1 > OFF_UPPER_LT) || (dc_off_ch2_i1 < OFF_LOWER_LT) ||
     513   [ #  #  #  # ]:          0 :                     (dc_off_ch2_i2 > OFF_UPPER_LT) || (dc_off_ch2_i2 < OFF_LOWER_LT) ||
     514   [ #  #  #  # ]:          0 :                     (dc_off_ch2_i3 > OFF_UPPER_LT) || (dc_off_ch2_i3 < OFF_LOWER_LT) ||
     515   [ #  #  #  # ]:          0 :                     (dc_off_ch2_q1 > OFF_UPPER_LT) || (dc_off_ch2_q1 < OFF_LOWER_LT) ||
     516   [ #  #  #  # ]:          0 :                     (dc_off_ch2_q2 > OFF_UPPER_LT) || (dc_off_ch2_q2 < OFF_LOWER_LT) ||
     517         [ #  # ]:          0 :                     (dc_off_ch2_q3 > OFF_UPPER_LT) || (dc_off_ch2_q3 < OFF_LOWER_LT)) {
     518         [ #  # ]:          0 :                         if (osdac_ch2 == 3) {
     519                 :            :                                 ch2_done = 1;
     520                 :            :                         } else {
     521                 :          0 :                                 osdac_ch2++;
     522                 :            : 
     523                 :          0 :                                 val = REG_READ(ah, AR_PHY_65NM_CH2_BB1) & 0x3fffffff;
     524                 :          0 :                                 val |= (osdac_ch2 << 30);
     525                 :          0 :                                 REG_WRITE(ah, AR_PHY_65NM_CH2_BB1, val);
     526                 :            : 
     527                 :          0 :                                 ch2_done = 0;
     528                 :            :                         }
     529                 :            :                 } else {
     530                 :            :                         ch2_done = 1;
     531                 :            :                 }
     532                 :            :         }
     533                 :            : 
     534         [ #  # ]:          0 :         REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
     535                 :            :                     AR_PHY_AGC_CONTROL_OFFSET_CAL);
     536                 :          0 :         REG_SET_BIT(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
     537                 :            : 
     538                 :            :         /*
     539                 :            :          * We don't need to check txiqcal_done here since it is always
     540                 :            :          * set for AR9550.
     541                 :            :          */
     542         [ #  # ]:          0 :         REG_SET_BIT(ah, AR_PHY_TX_IQCAL_CONTROL_0,
     543                 :            :                     AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL);
     544                 :            : 
     545                 :          0 :         return true;
     546                 :            : }
     547                 :            : 
     548                 :            : /*
     549                 :            :  * solve 4x4 linear equation used in loopback iq cal.
     550                 :            :  */
     551                 :          0 : static bool ar9003_hw_solve_iq_cal(struct ath_hw *ah,
     552                 :            :                                    s32 sin_2phi_1,
     553                 :            :                                    s32 cos_2phi_1,
     554                 :            :                                    s32 sin_2phi_2,
     555                 :            :                                    s32 cos_2phi_2,
     556                 :            :                                    s32 mag_a0_d0,
     557                 :            :                                    s32 phs_a0_d0,
     558                 :            :                                    s32 mag_a1_d0,
     559                 :            :                                    s32 phs_a1_d0,
     560                 :            :                                    s32 solved_eq[])
     561                 :            : {
     562                 :          0 :         s32 f1 = cos_2phi_1 - cos_2phi_2,
     563                 :          0 :             f3 = sin_2phi_1 - sin_2phi_2,
     564                 :            :             f2;
     565                 :          0 :         s32 mag_tx, phs_tx, mag_rx, phs_rx;
     566                 :          0 :         const s32 result_shift = 1 << 15;
     567         [ #  # ]:          0 :         struct ath_common *common = ath9k_hw_common(ah);
     568                 :            : 
     569                 :          0 :         f2 = ((f1 >> 3) * (f1 >> 3) + (f3 >> 3) * (f3 >> 3)) >> 9;
     570                 :            : 
     571         [ #  # ]:          0 :         if (!f2) {
     572         [ #  # ]:          0 :                 ath_dbg(common, CALIBRATE, "Divide by 0\n");
     573                 :          0 :                 return false;
     574                 :            :         }
     575                 :            : 
     576                 :            :         /* mag mismatch, tx */
     577                 :          0 :         mag_tx = f1 * (mag_a0_d0  - mag_a1_d0) + f3 * (phs_a0_d0 - phs_a1_d0);
     578                 :            :         /* phs mismatch, tx */
     579                 :          0 :         phs_tx = f3 * (-mag_a0_d0 + mag_a1_d0) + f1 * (phs_a0_d0 - phs_a1_d0);
     580                 :            : 
     581                 :          0 :         mag_tx = (mag_tx / f2);
     582                 :          0 :         phs_tx = (phs_tx / f2);
     583                 :            : 
     584                 :            :         /* mag mismatch, rx */
     585                 :          0 :         mag_rx = mag_a0_d0 - (cos_2phi_1 * mag_tx + sin_2phi_1 * phs_tx) /
     586                 :            :                  result_shift;
     587                 :            :         /* phs mismatch, rx */
     588                 :          0 :         phs_rx = phs_a0_d0 + (sin_2phi_1 * mag_tx - cos_2phi_1 * phs_tx) /
     589                 :            :                  result_shift;
     590                 :            : 
     591                 :          0 :         solved_eq[0] = mag_tx;
     592                 :          0 :         solved_eq[1] = phs_tx;
     593                 :          0 :         solved_eq[2] = mag_rx;
     594                 :          0 :         solved_eq[3] = phs_rx;
     595                 :            : 
     596                 :          0 :         return true;
     597                 :            : }
     598                 :            : 
     599                 :          0 : static s32 ar9003_hw_find_mag_approx(struct ath_hw *ah, s32 in_re, s32 in_im)
     600                 :            : {
     601                 :          0 :         s32 abs_i = abs(in_re),
     602                 :          0 :             abs_q = abs(in_im),
     603                 :            :             max_abs, min_abs;
     604                 :            : 
     605                 :          0 :         if (abs_i > abs_q) {
     606                 :            :                 max_abs = abs_i;
     607                 :            :                 min_abs = abs_q;
     608                 :            :         } else {
     609                 :          0 :                 max_abs = abs_q;
     610                 :          0 :                 min_abs = abs_i;
     611                 :            :         }
     612                 :            : 
     613                 :          0 :         return max_abs - (max_abs / 32) + (min_abs / 8) + (min_abs / 4);
     614                 :            : }
     615                 :            : 
     616                 :            : #define DELPT 32
     617                 :            : 
     618                 :         10 : static bool ar9003_hw_calc_iq_corr(struct ath_hw *ah,
     619                 :            :                                    s32 chain_idx,
     620                 :            :                                    const s32 iq_res[],
     621                 :            :                                    s32 iqc_coeff[])
     622                 :            : {
     623                 :         10 :         s32 i2_m_q2_a0_d0, i2_p_q2_a0_d0, iq_corr_a0_d0,
     624                 :            :             i2_m_q2_a0_d1, i2_p_q2_a0_d1, iq_corr_a0_d1,
     625                 :            :             i2_m_q2_a1_d0, i2_p_q2_a1_d0, iq_corr_a1_d0,
     626                 :            :             i2_m_q2_a1_d1, i2_p_q2_a1_d1, iq_corr_a1_d1;
     627                 :         10 :         s32 mag_a0_d0, mag_a1_d0, mag_a0_d1, mag_a1_d1,
     628                 :            :             phs_a0_d0, phs_a1_d0, phs_a0_d1, phs_a1_d1,
     629                 :            :             sin_2phi_1, cos_2phi_1,
     630                 :            :             sin_2phi_2, cos_2phi_2;
     631                 :         10 :         s32 mag_tx, phs_tx, mag_rx, phs_rx;
     632                 :         10 :         s32 solved_eq[4], mag_corr_tx, phs_corr_tx, mag_corr_rx, phs_corr_rx,
     633                 :            :             q_q_coff, q_i_coff;
     634                 :         10 :         const s32 res_scale = 1 << 15;
     635                 :         10 :         const s32 delpt_shift = 1 << 8;
     636                 :         10 :         s32 mag1, mag2;
     637         [ +  + ]:         10 :         struct ath_common *common = ath9k_hw_common(ah);
     638                 :            : 
     639                 :         10 :         i2_m_q2_a0_d0 = iq_res[0] & 0xfff;
     640                 :         10 :         i2_p_q2_a0_d0 = (iq_res[0] >> 12) & 0xfff;
     641                 :         10 :         iq_corr_a0_d0 = ((iq_res[0] >> 24) & 0xff) + ((iq_res[1] & 0xf) << 8);
     642                 :            : 
     643         [ +  + ]:         10 :         if (i2_m_q2_a0_d0 > 0x800)
     644                 :          4 :                 i2_m_q2_a0_d0 = -((0xfff - i2_m_q2_a0_d0) + 1);
     645                 :            : 
     646         [ +  + ]:         10 :         if (i2_p_q2_a0_d0 > 0x800)
     647                 :          4 :                 i2_p_q2_a0_d0 = -((0xfff - i2_p_q2_a0_d0) + 1);
     648                 :            : 
     649         [ +  + ]:         10 :         if (iq_corr_a0_d0 > 0x800)
     650                 :          4 :                 iq_corr_a0_d0 = -((0xfff - iq_corr_a0_d0) + 1);
     651                 :            : 
     652                 :         10 :         i2_m_q2_a0_d1 = (iq_res[1] >> 4) & 0xfff;
     653                 :         10 :         i2_p_q2_a0_d1 = (iq_res[2] & 0xfff);
     654                 :         10 :         iq_corr_a0_d1 = (iq_res[2] >> 12) & 0xfff;
     655                 :            : 
     656         [ +  + ]:         10 :         if (i2_m_q2_a0_d1 > 0x800)
     657                 :          6 :                 i2_m_q2_a0_d1 = -((0xfff - i2_m_q2_a0_d1) + 1);
     658                 :            : 
     659         [ +  + ]:         10 :         if (iq_corr_a0_d1 > 0x800)
     660                 :          2 :                 iq_corr_a0_d1 = -((0xfff - iq_corr_a0_d1) + 1);
     661                 :            : 
     662                 :         10 :         i2_m_q2_a1_d0 = ((iq_res[2] >> 24) & 0xff) + ((iq_res[3] & 0xf) << 8);
     663                 :         10 :         i2_p_q2_a1_d0 = (iq_res[3] >> 4) & 0xfff;
     664                 :         10 :         iq_corr_a1_d0 = iq_res[4] & 0xfff;
     665                 :            : 
     666         [ +  + ]:         10 :         if (i2_m_q2_a1_d0 > 0x800)
     667                 :          1 :                 i2_m_q2_a1_d0 = -((0xfff - i2_m_q2_a1_d0) + 1);
     668                 :            : 
     669         [ +  + ]:         10 :         if (i2_p_q2_a1_d0 > 0x800)
     670                 :          1 :                 i2_p_q2_a1_d0 = -((0xfff - i2_p_q2_a1_d0) + 1);
     671                 :            : 
     672         [ +  + ]:         10 :         if (iq_corr_a1_d0 > 0x800)
     673                 :          4 :                 iq_corr_a1_d0 = -((0xfff - iq_corr_a1_d0) + 1);
     674                 :            : 
     675                 :         10 :         i2_m_q2_a1_d1 = (iq_res[4] >> 12) & 0xfff;
     676                 :         10 :         i2_p_q2_a1_d1 = ((iq_res[4] >> 24) & 0xff) + ((iq_res[5] & 0xf) << 8);
     677                 :         10 :         iq_corr_a1_d1 = (iq_res[5] >> 4) & 0xfff;
     678                 :            : 
     679         [ +  + ]:         10 :         if (i2_m_q2_a1_d1 > 0x800)
     680                 :          4 :                 i2_m_q2_a1_d1 = -((0xfff - i2_m_q2_a1_d1) + 1);
     681                 :            : 
     682         [ +  + ]:         10 :         if (i2_p_q2_a1_d1 > 0x800)
     683                 :          1 :                 i2_p_q2_a1_d1 = -((0xfff - i2_p_q2_a1_d1) + 1);
     684                 :            : 
     685         [ +  + ]:         10 :         if (iq_corr_a1_d1 > 0x800)
     686                 :          5 :                 iq_corr_a1_d1 = -((0xfff - iq_corr_a1_d1) + 1);
     687                 :            : 
     688   [ +  -  +  +  :         10 :         if ((i2_p_q2_a0_d0 == 0) || (i2_p_q2_a0_d1 == 0) ||
                   +  + ]
     689         [ -  + ]:          8 :             (i2_p_q2_a1_d0 == 0) || (i2_p_q2_a1_d1 == 0)) {
     690         [ -  + ]:          2 :                 ath_dbg(common, CALIBRATE,
     691                 :            :                         "Divide by 0:\n"
     692                 :            :                         "a0_d0=%d\n"
     693                 :            :                         "a0_d1=%d\n"
     694                 :            :                         "a2_d0=%d\n"
     695                 :            :                         "a1_d1=%d\n",
     696                 :            :                         i2_p_q2_a0_d0, i2_p_q2_a0_d1,
     697                 :            :                         i2_p_q2_a1_d0, i2_p_q2_a1_d1);
     698                 :          2 :                 return false;
     699                 :            :         }
     700                 :            : 
     701   [ +  +  +  - ]:          8 :         if ((i2_p_q2_a0_d0 < 1024) || (i2_p_q2_a0_d0 > 2047) ||
     702   [ +  -  +  - ]:          1 :             (i2_p_q2_a1_d0 < 0) || (i2_p_q2_a1_d1 < 0) ||
     703         [ -  + ]:          1 :             (i2_p_q2_a0_d0 <= i2_m_q2_a0_d0) ||
     704         [ #  # ]:          0 :             (i2_p_q2_a0_d0 <= iq_corr_a0_d0) ||
     705         [ #  # ]:          0 :             (i2_p_q2_a0_d1 <= i2_m_q2_a0_d1) ||
     706         [ #  # ]:          0 :             (i2_p_q2_a0_d1 <= iq_corr_a0_d1) ||
     707         [ #  # ]:          0 :             (i2_p_q2_a1_d0 <= i2_m_q2_a1_d0) ||
     708         [ #  # ]:          0 :             (i2_p_q2_a1_d0 <= iq_corr_a1_d0) ||
     709         [ #  # ]:          0 :             (i2_p_q2_a1_d1 <= i2_m_q2_a1_d1) ||
     710                 :            :             (i2_p_q2_a1_d1 <= iq_corr_a1_d1)) {
     711                 :            :                 return false;
     712                 :            :         }
     713                 :            : 
     714                 :          0 :         mag_a0_d0 = (i2_m_q2_a0_d0 * res_scale) / i2_p_q2_a0_d0;
     715                 :          0 :         phs_a0_d0 = (iq_corr_a0_d0 * res_scale) / i2_p_q2_a0_d0;
     716                 :            : 
     717                 :          0 :         mag_a0_d1 = (i2_m_q2_a0_d1 * res_scale) / i2_p_q2_a0_d1;
     718                 :          0 :         phs_a0_d1 = (iq_corr_a0_d1 * res_scale) / i2_p_q2_a0_d1;
     719                 :            : 
     720                 :          0 :         mag_a1_d0 = (i2_m_q2_a1_d0 * res_scale) / i2_p_q2_a1_d0;
     721                 :          0 :         phs_a1_d0 = (iq_corr_a1_d0 * res_scale) / i2_p_q2_a1_d0;
     722                 :            : 
     723                 :          0 :         mag_a1_d1 = (i2_m_q2_a1_d1 * res_scale) / i2_p_q2_a1_d1;
     724                 :          0 :         phs_a1_d1 = (iq_corr_a1_d1 * res_scale) / i2_p_q2_a1_d1;
     725                 :            : 
     726                 :            :         /* w/o analog phase shift */
     727                 :          0 :         sin_2phi_1 = (((mag_a0_d0 - mag_a0_d1) * delpt_shift) / DELPT);
     728                 :            :         /* w/o analog phase shift */
     729                 :          0 :         cos_2phi_1 = (((phs_a0_d1 - phs_a0_d0) * delpt_shift) / DELPT);
     730                 :            :         /* w/  analog phase shift */
     731                 :          0 :         sin_2phi_2 = (((mag_a1_d0 - mag_a1_d1) * delpt_shift) / DELPT);
     732                 :            :         /* w/  analog phase shift */
     733                 :          0 :         cos_2phi_2 = (((phs_a1_d1 - phs_a1_d0) * delpt_shift) / DELPT);
     734                 :            : 
     735                 :            :         /*
     736                 :            :          * force sin^2 + cos^2 = 1;
     737                 :            :          * find magnitude by approximation
     738                 :            :          */
     739         [ #  # ]:          0 :         mag1 = ar9003_hw_find_mag_approx(ah, cos_2phi_1, sin_2phi_1);
     740         [ #  # ]:          0 :         mag2 = ar9003_hw_find_mag_approx(ah, cos_2phi_2, sin_2phi_2);
     741                 :            : 
     742   [ #  #  #  # ]:          0 :         if ((mag1 == 0) || (mag2 == 0)) {
     743         [ #  # ]:          0 :                 ath_dbg(common, CALIBRATE, "Divide by 0: mag1=%d, mag2=%d\n",
     744                 :            :                         mag1, mag2);
     745                 :          0 :                 return false;
     746                 :            :         }
     747                 :            : 
     748                 :            :         /* normalization sin and cos by mag */
     749                 :          0 :         sin_2phi_1 = (sin_2phi_1 * res_scale / mag1);
     750                 :          0 :         cos_2phi_1 = (cos_2phi_1 * res_scale / mag1);
     751                 :          0 :         sin_2phi_2 = (sin_2phi_2 * res_scale / mag2);
     752                 :          0 :         cos_2phi_2 = (cos_2phi_2 * res_scale / mag2);
     753                 :            : 
     754                 :            :         /* calculate IQ mismatch */
     755         [ #  # ]:          0 :         if (!ar9003_hw_solve_iq_cal(ah,
     756                 :            :                              sin_2phi_1, cos_2phi_1,
     757                 :            :                              sin_2phi_2, cos_2phi_2,
     758                 :            :                              mag_a0_d0, phs_a0_d0,
     759                 :            :                              mag_a1_d0,
     760                 :            :                              phs_a1_d0, solved_eq)) {
     761         [ #  # ]:          0 :                 ath_dbg(common, CALIBRATE,
     762                 :            :                         "Call to ar9003_hw_solve_iq_cal() failed\n");
     763                 :          0 :                 return false;
     764                 :            :         }
     765                 :            : 
     766                 :          0 :         mag_tx = solved_eq[0];
     767                 :          0 :         phs_tx = solved_eq[1];
     768                 :          0 :         mag_rx = solved_eq[2];
     769                 :          0 :         phs_rx = solved_eq[3];
     770                 :            : 
     771         [ #  # ]:          0 :         ath_dbg(common, CALIBRATE,
     772                 :            :                 "chain %d: mag mismatch=%d phase mismatch=%d\n",
     773                 :            :                 chain_idx, mag_tx/res_scale, phs_tx/res_scale);
     774                 :            : 
     775         [ #  # ]:          0 :         if (res_scale == mag_tx) {
     776         [ #  # ]:          0 :                 ath_dbg(common, CALIBRATE,
     777                 :            :                         "Divide by 0: mag_tx=%d, res_scale=%d\n",
     778                 :            :                         mag_tx, res_scale);
     779                 :          0 :                 return false;
     780                 :            :         }
     781                 :            : 
     782                 :            :         /* calculate and quantize Tx IQ correction factor */
     783                 :          0 :         mag_corr_tx = (mag_tx * res_scale) / (res_scale - mag_tx);
     784                 :          0 :         phs_corr_tx = -phs_tx;
     785                 :            : 
     786                 :          0 :         q_q_coff = (mag_corr_tx * 128 / res_scale);
     787                 :          0 :         q_i_coff = (phs_corr_tx * 256 / res_scale);
     788                 :            : 
     789         [ #  # ]:          0 :         ath_dbg(common, CALIBRATE, "tx chain %d: mag corr=%d  phase corr=%d\n",
     790                 :            :                 chain_idx, q_q_coff, q_i_coff);
     791                 :            : 
     792         [ #  # ]:          0 :         if (q_i_coff < -63)
     793                 :            :                 q_i_coff = -63;
     794                 :          0 :         if (q_i_coff > 63)
     795                 :            :                 q_i_coff = 63;
     796         [ #  # ]:          0 :         if (q_q_coff < -63)
     797                 :            :                 q_q_coff = -63;
     798                 :          0 :         if (q_q_coff > 63)
     799                 :            :                 q_q_coff = 63;
     800                 :            : 
     801                 :          0 :         iqc_coeff[0] = (q_q_coff * 128) + (0x7f & q_i_coff);
     802                 :            : 
     803         [ #  # ]:          0 :         ath_dbg(common, CALIBRATE, "tx chain %d: iq corr coeff=%x\n",
     804                 :            :                 chain_idx, iqc_coeff[0]);
     805                 :            : 
     806         [ #  # ]:          0 :         if (-mag_rx == res_scale) {
     807         [ #  # ]:          0 :                 ath_dbg(common, CALIBRATE,
     808                 :            :                         "Divide by 0: mag_rx=%d, res_scale=%d\n",
     809                 :            :                         mag_rx, res_scale);
     810                 :          0 :                 return false;
     811                 :            :         }
     812                 :            : 
     813                 :            :         /* calculate and quantize Rx IQ correction factors */
     814                 :          0 :         mag_corr_rx = (-mag_rx * res_scale) / (res_scale + mag_rx);
     815                 :          0 :         phs_corr_rx = -phs_rx;
     816                 :            : 
     817                 :          0 :         q_q_coff = (mag_corr_rx * 128 / res_scale);
     818                 :          0 :         q_i_coff = (phs_corr_rx * 256 / res_scale);
     819                 :            : 
     820         [ #  # ]:          0 :         ath_dbg(common, CALIBRATE, "rx chain %d: mag corr=%d  phase corr=%d\n",
     821                 :            :                 chain_idx, q_q_coff, q_i_coff);
     822                 :            : 
     823         [ #  # ]:          0 :         if (q_i_coff < -63)
     824                 :            :                 q_i_coff = -63;
     825                 :          0 :         if (q_i_coff > 63)
     826                 :            :                 q_i_coff = 63;
     827         [ #  # ]:          0 :         if (q_q_coff < -63)
     828                 :            :                 q_q_coff = -63;
     829                 :          0 :         if (q_q_coff > 63)
     830                 :            :                 q_q_coff = 63;
     831                 :            : 
     832                 :          0 :         iqc_coeff[1] = (q_q_coff * 128) + (0x7f & q_i_coff);
     833                 :            : 
     834         [ #  # ]:          0 :         ath_dbg(common, CALIBRATE, "rx chain %d: iq corr coeff=%x\n",
     835                 :            :                 chain_idx, iqc_coeff[1]);
     836                 :            : 
     837                 :            :         return true;
     838                 :            : }
     839                 :            : 
     840                 :          0 : static void ar9003_hw_detect_outlier(int mp_coeff[][MAXIQCAL],
     841                 :            :                                      int nmeasurement,
     842                 :            :                                      int max_delta)
     843                 :            : {
     844                 :          0 :         int mp_max = -64, max_idx = 0;
     845                 :          0 :         int mp_min = 63, min_idx = 0;
     846                 :          0 :         int mp_avg = 0, i, outlier_idx = 0, mp_count = 0;
     847                 :            : 
     848                 :            :         /* find min/max mismatch across all calibrated gains */
     849         [ #  # ]:          0 :         for (i = 0; i < nmeasurement; i++) {
     850         [ #  # ]:          0 :                 if (mp_coeff[i][0] > mp_max) {
     851                 :            :                         mp_max = mp_coeff[i][0];
     852                 :            :                         max_idx = i;
     853         [ #  # ]:          0 :                 } else if (mp_coeff[i][0] < mp_min) {
     854                 :          0 :                         mp_min = mp_coeff[i][0];
     855                 :          0 :                         min_idx = i;
     856                 :            :                 }
     857                 :            :         }
     858                 :            : 
     859                 :            :         /* find average (exclude max abs value) */
     860         [ #  # ]:          0 :         for (i = 0; i < nmeasurement; i++) {
     861         [ #  # ]:          0 :                 if ((abs(mp_coeff[i][0]) < abs(mp_max)) ||
     862         [ #  # ]:          0 :                     (abs(mp_coeff[i][0]) < abs(mp_min))) {
     863                 :          0 :                         mp_avg += mp_coeff[i][0];
     864                 :          0 :                         mp_count++;
     865                 :            :                 }
     866                 :            :         }
     867                 :            : 
     868                 :            :         /*
     869                 :            :          * finding mean magnitude/phase if possible, otherwise
     870                 :            :          * just use the last value as the mean
     871                 :            :          */
     872         [ #  # ]:          0 :         if (mp_count)
     873                 :          0 :                 mp_avg /= mp_count;
     874                 :            :         else
     875                 :          0 :                 mp_avg = mp_coeff[nmeasurement - 1][0];
     876                 :            : 
     877                 :            :         /* detect outlier */
     878         [ #  # ]:          0 :         if (abs(mp_max - mp_min) > max_delta) {
     879         [ #  # ]:          0 :                 if (abs(mp_max - mp_avg) > abs(mp_min - mp_avg))
     880                 :            :                         outlier_idx = max_idx;
     881                 :            :                 else
     882                 :          0 :                         outlier_idx = min_idx;
     883                 :            : 
     884                 :          0 :                 mp_coeff[outlier_idx][0] = mp_avg;
     885                 :            :         }
     886                 :          0 : }
     887                 :            : 
     888                 :          1 : static void ar9003_hw_tx_iq_cal_outlier_detection(struct ath_hw *ah,
     889                 :            :                                                   struct coeff *coeff,
     890                 :            :                                                   bool is_reusable)
     891                 :            : {
     892                 :          1 :         int i, im, nmeasurement;
     893                 :          1 :         int magnitude, phase;
     894                 :          1 :         u32 tx_corr_coeff[MAX_MEASUREMENT][AR9300_MAX_CHAINS];
     895                 :          1 :         struct ath9k_hw_cal_data *caldata = ah->caldata;
     896                 :            : 
     897                 :          1 :         memset(tx_corr_coeff, 0, sizeof(tx_corr_coeff));
     898         [ +  + ]:          5 :         for (i = 0; i < MAX_MEASUREMENT / 2; i++) {
     899                 :          8 :                 tx_corr_coeff[i * 2][0] = tx_corr_coeff[(i * 2) + 1][0] =
     900         [ +  - ]:          4 :                                         AR_PHY_TX_IQCAL_CORR_COEFF_B0(i);
     901         [ +  - ]:          4 :                 if (!AR_SREV_9485(ah)) {
     902                 :          4 :                         tx_corr_coeff[i * 2][1] =
     903                 :          4 :                         tx_corr_coeff[(i * 2) + 1][1] =
     904                 :          4 :                                         AR_PHY_TX_IQCAL_CORR_COEFF_B1(i);
     905                 :            : 
     906                 :          4 :                         tx_corr_coeff[i * 2][2] =
     907                 :          4 :                         tx_corr_coeff[(i * 2) + 1][2] =
     908                 :          4 :                                         AR_PHY_TX_IQCAL_CORR_COEFF_B2(i);
     909                 :            :                 }
     910                 :            :         }
     911                 :            : 
     912                 :            :         /* Load the average of 2 passes */
     913         [ +  + ]:          4 :         for (i = 0; i < AR9300_MAX_CHAINS; i++) {
     914         [ +  + ]:          3 :                 if (!(ah->txchainmask & (1 << i)))
     915                 :          1 :                         continue;
     916         [ +  - ]:          4 :                 nmeasurement = REG_READ_FIELD(ah,
     917                 :            :                                 AR_PHY_TX_IQCAL_STATUS_B0,
     918                 :            :                                 AR_PHY_CALIBRATED_GAINS_0);
     919                 :            : 
     920                 :          2 :                 if (nmeasurement > MAX_MEASUREMENT)
     921                 :            :                         nmeasurement = MAX_MEASUREMENT;
     922                 :            : 
     923                 :            :                 /*
     924                 :            :                  * Skip normal outlier detection for AR9550.
     925                 :            :                  */
     926         [ +  - ]:          2 :                 if (!AR_SREV_9550(ah)) {
     927                 :            :                         /* detect outlier only if nmeasurement > 1 */
     928         [ -  + ]:          2 :                         if (nmeasurement > 1) {
     929                 :            :                                 /* Detect magnitude outlier */
     930                 :          0 :                                 ar9003_hw_detect_outlier(coeff->mag_coeff[i],
     931                 :            :                                                          nmeasurement,
     932                 :            :                                                          MAX_MAG_DELTA);
     933                 :            : 
     934                 :            :                                 /* Detect phase outlier */
     935                 :          0 :                                 ar9003_hw_detect_outlier(coeff->phs_coeff[i],
     936                 :            :                                                          nmeasurement,
     937                 :            :                                                          MAX_PHS_DELTA);
     938                 :            :                         }
     939                 :            :                 }
     940                 :            : 
     941         [ -  + ]:          2 :                 for (im = 0; im < nmeasurement; im++) {
     942                 :          0 :                         magnitude = coeff->mag_coeff[i][im][0];
     943                 :          0 :                         phase = coeff->phs_coeff[i][im][0];
     944                 :            : 
     945                 :          0 :                         coeff->iqc_coeff[0] =
     946                 :          0 :                                 (phase & 0x7f) | ((magnitude & 0x7f) << 7);
     947                 :            : 
     948         [ #  # ]:          0 :                         if ((im % 2) == 0)
     949                 :          0 :                                 REG_RMW_FIELD(ah, tx_corr_coeff[im][i],
     950                 :            :                                         AR_PHY_TX_IQCAL_CORR_COEFF_00_COEFF_TABLE,
     951                 :            :                                         coeff->iqc_coeff[0]);
     952                 :            :                         else
     953                 :          0 :                                 REG_RMW_FIELD(ah, tx_corr_coeff[im][i],
     954                 :            :                                         AR_PHY_TX_IQCAL_CORR_COEFF_01_COEFF_TABLE,
     955                 :            :                                         coeff->iqc_coeff[0]);
     956                 :            : 
     957         [ #  # ]:          0 :                         if (caldata)
     958                 :          0 :                                 caldata->tx_corr_coeff[im][i] =
     959                 :          0 :                                         coeff->iqc_coeff[0];
     960                 :            :                 }
     961         [ +  - ]:          2 :                 if (caldata)
     962                 :          2 :                         caldata->num_measures[i] = nmeasurement;
     963                 :            :         }
     964                 :            : 
     965                 :          1 :         REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_3,
     966                 :            :                       AR_PHY_TX_IQCAL_CONTROL_3_IQCORR_EN, 0x1);
     967                 :          1 :         REG_RMW_FIELD(ah, AR_PHY_RX_IQCAL_CORR_B0,
     968                 :            :                       AR_PHY_RX_IQCAL_CORR_B0_LOOPBACK_IQCORR_EN, 0x1);
     969                 :            : 
     970         [ +  - ]:          1 :         if (caldata) {
     971         [ -  + ]:          1 :                 if (is_reusable)
     972                 :          0 :                         set_bit(TXIQCAL_DONE, &caldata->cal_flags);
     973                 :            :                 else
     974                 :          1 :                         clear_bit(TXIQCAL_DONE, &caldata->cal_flags);
     975                 :            :         }
     976                 :            : 
     977                 :          1 :         return;
     978                 :            : }
     979                 :            : 
     980                 :         10 : static bool ar9003_hw_tx_iq_cal_run(struct ath_hw *ah)
     981                 :            : {
     982                 :         10 :         struct ath_common *common = ath9k_hw_common(ah);
     983                 :         10 :         u8 tx_gain_forced;
     984                 :            : 
     985                 :         10 :         tx_gain_forced = REG_READ_FIELD(ah, AR_PHY_TX_FORCED_GAIN,
     986                 :            :                                         AR_PHY_TXGAIN_FORCE);
     987         [ +  + ]:         10 :         if (tx_gain_forced)
     988                 :          8 :                 REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN,
     989                 :            :                               AR_PHY_TXGAIN_FORCE, 0);
     990                 :            : 
     991         [ +  - ]:         20 :         REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_START,
     992                 :            :                       AR_PHY_TX_IQCAL_START_DO_CAL, 1);
     993                 :            : 
     994   [ +  -  -  + ]:         20 :         if (!ath9k_hw_wait(ah, AR_PHY_TX_IQCAL_START,
     995                 :            :                         AR_PHY_TX_IQCAL_START_DO_CAL, 0,
     996                 :            :                         AH_WAIT_TIMEOUT)) {
     997         [ #  # ]:          0 :                 ath_dbg(common, CALIBRATE, "Tx IQ Cal is not completed\n");
     998                 :          0 :                 return false;
     999                 :            :         }
    1000                 :            :         return true;
    1001                 :            : }
    1002                 :            : 
    1003                 :          0 : static void __ar955x_tx_iq_cal_sort(struct ath_hw *ah,
    1004                 :            :                                     struct coeff *coeff,
    1005                 :            :                                     int i, int nmeasurement)
    1006                 :            : {
    1007                 :          0 :         struct ath_common *common = ath9k_hw_common(ah);
    1008                 :          0 :         int im, ix, iy, temp;
    1009                 :            : 
    1010         [ #  # ]:          0 :         for (im = 0; im < nmeasurement; im++) {
    1011         [ #  # ]:          0 :                 for (ix = 0; ix < MAXIQCAL - 1; ix++) {
    1012         [ #  # ]:          0 :                         for (iy = ix + 1; iy <= MAXIQCAL - 1; iy++) {
    1013                 :          0 :                                 if (coeff->mag_coeff[i][im][iy] <
    1014         [ #  # ]:          0 :                                     coeff->mag_coeff[i][im][ix]) {
    1015                 :          0 :                                         temp = coeff->mag_coeff[i][im][ix];
    1016                 :          0 :                                         coeff->mag_coeff[i][im][ix] =
    1017                 :            :                                                 coeff->mag_coeff[i][im][iy];
    1018                 :          0 :                                         coeff->mag_coeff[i][im][iy] = temp;
    1019                 :            :                                 }
    1020                 :          0 :                                 if (coeff->phs_coeff[i][im][iy] <
    1021         [ #  # ]:          0 :                                     coeff->phs_coeff[i][im][ix]) {
    1022                 :          0 :                                         temp = coeff->phs_coeff[i][im][ix];
    1023                 :          0 :                                         coeff->phs_coeff[i][im][ix] =
    1024                 :            :                                                 coeff->phs_coeff[i][im][iy];
    1025                 :          0 :                                         coeff->phs_coeff[i][im][iy] = temp;
    1026                 :            :                                 }
    1027                 :            :                         }
    1028                 :            :                 }
    1029                 :          0 :                 coeff->mag_coeff[i][im][0] = coeff->mag_coeff[i][im][MAXIQCAL / 2];
    1030                 :          0 :                 coeff->phs_coeff[i][im][0] = coeff->phs_coeff[i][im][MAXIQCAL / 2];
    1031                 :            : 
    1032         [ #  # ]:          0 :                 ath_dbg(common, CALIBRATE,
    1033                 :            :                         "IQCAL: Median [ch%d][gain%d]: mag = %d phase = %d\n",
    1034                 :            :                         i, im,
    1035                 :            :                         coeff->mag_coeff[i][im][0],
    1036                 :            :                         coeff->phs_coeff[i][im][0]);
    1037                 :            :         }
    1038                 :          0 : }
    1039                 :            : 
    1040                 :          0 : static bool ar955x_tx_iq_cal_median(struct ath_hw *ah,
    1041                 :            :                                     struct coeff *coeff,
    1042                 :            :                                     int iqcal_idx,
    1043                 :            :                                     int nmeasurement)
    1044                 :            : {
    1045                 :          0 :         int i;
    1046                 :            : 
    1047                 :          0 :         if ((iqcal_idx + 1) != MAXIQCAL)
    1048                 :            :                 return false;
    1049                 :            : 
    1050         [ #  # ]:          0 :         for (i = 0; i < AR9300_MAX_CHAINS; i++) {
    1051                 :          0 :                 __ar955x_tx_iq_cal_sort(ah, coeff, i, nmeasurement);
    1052                 :            :         }
    1053                 :            : 
    1054                 :            :         return true;
    1055                 :            : }
    1056                 :            : 
    1057                 :         21 : static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah,
    1058                 :            :                                           int iqcal_idx,
    1059                 :            :                                           bool is_reusable)
    1060                 :            : {
    1061         [ +  - ]:         21 :         struct ath_common *common = ath9k_hw_common(ah);
    1062                 :         42 :         const u32 txiqcal_status[AR9300_MAX_CHAINS] = {
    1063         [ +  - ]:         21 :                 AR_PHY_TX_IQCAL_STATUS_B0,
    1064                 :            :                 AR_PHY_TX_IQCAL_STATUS_B1,
    1065                 :            :                 AR_PHY_TX_IQCAL_STATUS_B2,
    1066                 :            :         };
    1067                 :         21 :         const u_int32_t chan_info_tab[] = {
    1068                 :            :                 AR_PHY_CHAN_INFO_TAB_0,
    1069                 :            :                 AR_PHY_CHAN_INFO_TAB_1,
    1070                 :            :                 AR_PHY_CHAN_INFO_TAB_2,
    1071                 :            :         };
    1072                 :         21 :         static struct coeff coeff;
    1073                 :         21 :         s32 iq_res[6];
    1074                 :         21 :         int i, im, j;
    1075                 :         21 :         int nmeasurement = 0;
    1076                 :         21 :         bool outlier_detect = true;
    1077                 :            : 
    1078         [ +  + ]:         26 :         for (i = 0; i < AR9300_MAX_CHAINS; i++) {
    1079         [ +  + ]:         25 :                 if (!(ah->txchainmask & (1 << i)))
    1080                 :          1 :                         continue;
    1081                 :            : 
    1082         [ +  - ]:         48 :                 nmeasurement = REG_READ_FIELD(ah,
    1083                 :            :                                 AR_PHY_TX_IQCAL_STATUS_B0,
    1084                 :            :                                 AR_PHY_CALIBRATED_GAINS_0);
    1085                 :         24 :                 if (nmeasurement > MAX_MEASUREMENT)
    1086                 :            :                         nmeasurement = MAX_MEASUREMENT;
    1087                 :            : 
    1088         [ +  + ]:         24 :                 for (im = 0; im < nmeasurement; im++) {
    1089         [ -  + ]:         20 :                         ath_dbg(common, CALIBRATE,
    1090                 :            :                                 "Doing Tx IQ Cal for chain %d\n", i);
    1091                 :            : 
    1092         [ +  + ]:         20 :                         if (REG_READ(ah, txiqcal_status[i]) &
    1093                 :            :                                         AR_PHY_TX_IQCAL_STATUS_FAILED) {
    1094         [ -  + ]:         10 :                                 ath_dbg(common, CALIBRATE,
    1095                 :            :                                         "Tx IQ Cal failed for chain %d\n", i);
    1096                 :         10 :                                 goto tx_iqcal_fail;
    1097                 :            :                         }
    1098                 :            : 
    1099         [ +  + ]:         40 :                         for (j = 0; j < 3; j++) {
    1100                 :         30 :                                 u32 idx = 2 * j, offset = 4 * (3 * im + j);
    1101                 :            : 
    1102         [ +  + ]:         54 :                                 REG_RMW_FIELD(ah,
    1103                 :            :                                                 AR_PHY_CHAN_INFO_MEMORY,
    1104                 :            :                                                 AR_PHY_CHAN_INFO_TAB_S2_READ,
    1105                 :            :                                                 0);
    1106                 :            : 
    1107                 :            :                                 /* 32 bits */
    1108                 :         30 :                                 iq_res[idx] = REG_READ(ah,
    1109                 :            :                                                 chan_info_tab[i] +
    1110                 :            :                                                 offset);
    1111                 :            : 
    1112         [ +  + ]:         54 :                                 REG_RMW_FIELD(ah,
    1113                 :            :                                                 AR_PHY_CHAN_INFO_MEMORY,
    1114                 :            :                                                 AR_PHY_CHAN_INFO_TAB_S2_READ,
    1115                 :            :                                                 1);
    1116                 :            : 
    1117                 :            :                                 /* 16 bits */
    1118                 :         30 :                                 iq_res[idx + 1] = 0xffff & REG_READ(ah,
    1119                 :            :                                                 chan_info_tab[i] + offset);
    1120                 :            : 
    1121         [ -  + ]:         30 :                                 ath_dbg(common, CALIBRATE,
    1122                 :            :                                         "IQ_RES[%d]=0x%x IQ_RES[%d]=0x%x\n",
    1123                 :            :                                         idx, iq_res[idx], idx + 1,
    1124                 :            :                                         iq_res[idx + 1]);
    1125                 :            :                         }
    1126                 :            : 
    1127         [ +  - ]:         10 :                         if (!ar9003_hw_calc_iq_corr(ah, i, iq_res,
    1128                 :            :                                                 coeff.iqc_coeff)) {
    1129         [ -  + ]:         10 :                                 ath_dbg(common, CALIBRATE,
    1130                 :            :                                         "Failed in calculation of IQ correction\n");
    1131                 :         10 :                                 goto tx_iqcal_fail;
    1132                 :            :                         }
    1133                 :            : 
    1134                 :          0 :                         coeff.phs_coeff[i][im][iqcal_idx] =
    1135                 :          0 :                                 coeff.iqc_coeff[0] & 0x7f;
    1136                 :          0 :                         coeff.mag_coeff[i][im][iqcal_idx] =
    1137                 :          0 :                                 (coeff.iqc_coeff[0] >> 7) & 0x7f;
    1138                 :            : 
    1139         [ #  # ]:          0 :                         if (coeff.mag_coeff[i][im][iqcal_idx] > 63)
    1140                 :          0 :                                 coeff.mag_coeff[i][im][iqcal_idx] -= 128;
    1141         [ #  # ]:          0 :                         if (coeff.phs_coeff[i][im][iqcal_idx] > 63)
    1142                 :          0 :                                 coeff.phs_coeff[i][im][iqcal_idx] -= 128;
    1143                 :            :                 }
    1144                 :            :         }
    1145                 :            : 
    1146         [ -  + ]:          1 :         if (AR_SREV_9550(ah))
    1147         [ #  # ]:          0 :                 outlier_detect = ar955x_tx_iq_cal_median(ah, &coeff,
    1148                 :            :                                                          iqcal_idx, nmeasurement);
    1149                 :            :         if (outlier_detect)
    1150                 :          1 :                 ar9003_hw_tx_iq_cal_outlier_detection(ah, &coeff, is_reusable);
    1151                 :            : 
    1152                 :            :         return;
    1153                 :            : 
    1154                 :         20 : tx_iqcal_fail:
    1155         [ -  + ]:         20 :         ath_dbg(common, CALIBRATE, "Tx IQ Cal failed\n");
    1156                 :            :         return;
    1157                 :            : }
    1158                 :            : 
    1159                 :          0 : static void ar9003_hw_tx_iq_cal_reload(struct ath_hw *ah)
    1160                 :            : {
    1161                 :          0 :         struct ath9k_hw_cal_data *caldata = ah->caldata;
    1162                 :          0 :         u32 tx_corr_coeff[MAX_MEASUREMENT][AR9300_MAX_CHAINS];
    1163                 :          0 :         int i, im;
    1164                 :            : 
    1165                 :          0 :         memset(tx_corr_coeff, 0, sizeof(tx_corr_coeff));
    1166         [ #  # ]:          0 :         for (i = 0; i < MAX_MEASUREMENT / 2; i++) {
    1167                 :          0 :                 tx_corr_coeff[i * 2][0] = tx_corr_coeff[(i * 2) + 1][0] =
    1168         [ #  # ]:          0 :                                         AR_PHY_TX_IQCAL_CORR_COEFF_B0(i);
    1169         [ #  # ]:          0 :                 if (!AR_SREV_9485(ah)) {
    1170                 :          0 :                         tx_corr_coeff[i * 2][1] =
    1171                 :          0 :                         tx_corr_coeff[(i * 2) + 1][1] =
    1172                 :          0 :                                         AR_PHY_TX_IQCAL_CORR_COEFF_B1(i);
    1173                 :            : 
    1174                 :          0 :                         tx_corr_coeff[i * 2][2] =
    1175                 :          0 :                         tx_corr_coeff[(i * 2) + 1][2] =
    1176                 :          0 :                                         AR_PHY_TX_IQCAL_CORR_COEFF_B2(i);
    1177                 :            :                 }
    1178                 :            :         }
    1179                 :            : 
    1180         [ #  # ]:          0 :         for (i = 0; i < AR9300_MAX_CHAINS; i++) {
    1181         [ #  # ]:          0 :                 if (!(ah->txchainmask & (1 << i)))
    1182                 :          0 :                         continue;
    1183                 :            : 
    1184         [ #  # ]:          0 :                 for (im = 0; im < caldata->num_measures[i]; im++) {
    1185         [ #  # ]:          0 :                         if ((im % 2) == 0)
    1186                 :          0 :                                 REG_RMW_FIELD(ah, tx_corr_coeff[im][i],
    1187                 :            :                                      AR_PHY_TX_IQCAL_CORR_COEFF_00_COEFF_TABLE,
    1188                 :            :                                      caldata->tx_corr_coeff[im][i]);
    1189                 :            :                         else
    1190                 :          0 :                                 REG_RMW_FIELD(ah, tx_corr_coeff[im][i],
    1191                 :            :                                      AR_PHY_TX_IQCAL_CORR_COEFF_01_COEFF_TABLE,
    1192                 :            :                                      caldata->tx_corr_coeff[im][i]);
    1193                 :            :                 }
    1194                 :            :         }
    1195                 :            : 
    1196                 :          0 :         REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_3,
    1197                 :            :                       AR_PHY_TX_IQCAL_CONTROL_3_IQCORR_EN, 0x1);
    1198                 :          0 :         REG_RMW_FIELD(ah, AR_PHY_RX_IQCAL_CORR_B0,
    1199                 :            :                       AR_PHY_RX_IQCAL_CORR_B0_LOOPBACK_IQCORR_EN, 0x1);
    1200                 :          0 : }
    1201                 :            : 
    1202                 :         82 : static void ar9003_hw_manual_peak_cal(struct ath_hw *ah, u8 chain, bool is_2g)
    1203                 :            : {
    1204                 :         82 :         int offset[8] = {0}, total = 0, test;
    1205                 :         82 :         int agc_out, i, peak_detect_threshold = 0;
    1206                 :            : 
    1207   [ +  -  +  + ]:         82 :         if (AR_SREV_9550(ah) || AR_SREV_9531(ah))
    1208                 :            :                 peak_detect_threshold = 8;
    1209         [ +  + ]:         60 :         else if (AR_SREV_9561(ah))
    1210                 :         24 :                 peak_detect_threshold = 11;
    1211                 :            : 
    1212                 :            :         /*
    1213                 :            :          * Turn off LNA/SW.
    1214                 :            :          */
    1215                 :         82 :         REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_GAINSTAGES(chain),
    1216                 :            :                       AR_PHY_65NM_RXRF_GAINSTAGES_RX_OVERRIDE, 0x1);
    1217                 :         82 :         REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_GAINSTAGES(chain),
    1218                 :            :                       AR_PHY_65NM_RXRF_GAINSTAGES_LNAON_CALDC, 0x0);
    1219                 :            : 
    1220   [ +  +  +  -  :         82 :         if (AR_SREV_9003_PCOEM(ah) || AR_SREV_9330_11(ah)) {
             +  -  -  + ]
    1221         [ +  - ]:          6 :                 if (is_2g)
    1222                 :          6 :                         REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_GAINSTAGES(chain),
    1223                 :            :                                       AR_PHY_65NM_RXRF_GAINSTAGES_LNA2G_GAIN_OVR, 0x0);
    1224                 :            :                 else
    1225                 :          0 :                         REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_GAINSTAGES(chain),
    1226                 :            :                                       AR_PHY_65NM_RXRF_GAINSTAGES_LNA5G_GAIN_OVR, 0x0);
    1227                 :            :         }
    1228                 :            : 
    1229                 :            :         /*
    1230                 :            :          * Turn off RXON.
    1231                 :            :          */
    1232                 :         82 :         REG_RMW_FIELD(ah, AR_PHY_65NM_RXTX2(chain),
    1233                 :            :                       AR_PHY_65NM_RXTX2_RXON_OVR, 0x1);
    1234                 :         82 :         REG_RMW_FIELD(ah, AR_PHY_65NM_RXTX2(chain),
    1235                 :            :                       AR_PHY_65NM_RXTX2_RXON, 0x0);
    1236                 :            : 
    1237                 :            :         /*
    1238                 :            :          * Turn on AGC for cal.
    1239                 :            :          */
    1240                 :         82 :         REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
    1241                 :            :                       AR_PHY_65NM_RXRF_AGC_AGC_OVERRIDE, 0x1);
    1242                 :         82 :         REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
    1243                 :            :                       AR_PHY_65NM_RXRF_AGC_AGC_ON_OVR, 0x1);
    1244                 :         82 :         REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
    1245                 :            :                       AR_PHY_65NM_RXRF_AGC_AGC_CAL_OVR, 0x1);
    1246                 :            : 
    1247         [ -  + ]:         82 :         if (AR_SREV_9330_11(ah))
    1248                 :          0 :                 REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
    1249                 :            :                               AR_PHY_65NM_RXRF_AGC_AGC2G_CALDAC_OVR, 0x0);
    1250                 :            : 
    1251         [ +  - ]:         82 :         if (is_2g)
    1252                 :         82 :                 REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
    1253                 :            :                               AR_PHY_65NM_RXRF_AGC_AGC2G_DBDAC_OVR,
    1254                 :            :                               peak_detect_threshold);
    1255                 :            :         else
    1256                 :          0 :                 REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
    1257                 :            :                               AR_PHY_65NM_RXRF_AGC_AGC5G_DBDAC_OVR,
    1258                 :            :                               peak_detect_threshold);
    1259                 :            : 
    1260         [ +  + ]:        574 :         for (i = 6; i > 0; i--) {
    1261                 :        492 :                 offset[i] = BIT(i - 1);
    1262                 :        492 :                 test = total + offset[i];
    1263                 :            : 
    1264         [ +  - ]:        492 :                 if (is_2g)
    1265                 :        492 :                         REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
    1266                 :            :                                       AR_PHY_65NM_RXRF_AGC_AGC2G_CALDAC_OVR,
    1267                 :            :                                       test);
    1268                 :            :                 else
    1269                 :          0 :                         REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
    1270                 :            :                                       AR_PHY_65NM_RXRF_AGC_AGC5G_CALDAC_OVR,
    1271                 :            :                                       test);
    1272                 :        492 :                 udelay(100);
    1273                 :        492 :                 agc_out = REG_READ_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
    1274                 :            :                                          AR_PHY_65NM_RXRF_AGC_AGC_OUT);
    1275                 :        492 :                 offset[i] = (agc_out) ? 0 : 1;
    1276                 :        492 :                 total += (offset[i] << (i - 1));
    1277                 :            :         }
    1278                 :            : 
    1279         [ +  - ]:         82 :         if (is_2g)
    1280                 :         82 :                 REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
    1281                 :            :                               AR_PHY_65NM_RXRF_AGC_AGC2G_CALDAC_OVR, total);
    1282                 :            :         else
    1283                 :          0 :                 REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
    1284                 :            :                               AR_PHY_65NM_RXRF_AGC_AGC5G_CALDAC_OVR, total);
    1285                 :            : 
    1286                 :            :         /*
    1287                 :            :          * Turn on LNA.
    1288                 :            :          */
    1289                 :         82 :         REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_GAINSTAGES(chain),
    1290                 :            :                       AR_PHY_65NM_RXRF_GAINSTAGES_RX_OVERRIDE, 0);
    1291                 :            :         /*
    1292                 :            :          * Turn off RXON.
    1293                 :            :          */
    1294                 :         82 :         REG_RMW_FIELD(ah, AR_PHY_65NM_RXTX2(chain),
    1295                 :            :                       AR_PHY_65NM_RXTX2_RXON_OVR, 0);
    1296                 :            :         /*
    1297                 :            :          * Turn off peak detect calibration.
    1298                 :            :          */
    1299                 :         82 :         REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
    1300                 :            :                       AR_PHY_65NM_RXRF_AGC_AGC_CAL_OVR, 0);
    1301                 :         82 : }
    1302                 :            : 
    1303                 :         12 : static void ar9003_hw_do_pcoem_manual_peak_cal(struct ath_hw *ah,
    1304                 :            :                                                struct ath9k_channel *chan,
    1305                 :            :                                                bool run_rtt_cal)
    1306                 :            : {
    1307                 :         12 :         struct ath9k_hw_cal_data *caldata = ah->caldata;
    1308                 :         12 :         int i;
    1309                 :            : 
    1310   [ -  +  +  + ]:         12 :         if ((ah->caps.hw_caps & ATH9K_HW_CAP_RTT) && !run_rtt_cal)
    1311                 :            :                 return;
    1312                 :            : 
    1313         [ +  + ]:         12 :         for (i = 0; i < AR9300_MAX_CHAINS; i++) {
    1314         [ +  + ]:          9 :                 if (!(ah->rxchainmask & (1 << i)))
    1315                 :          3 :                         continue;
    1316                 :          6 :                 ar9003_hw_manual_peak_cal(ah, i, IS_CHAN_2GHZ(chan));
    1317                 :            :         }
    1318                 :            : 
    1319         [ +  + ]:          3 :         if (caldata)
    1320                 :          2 :                 set_bit(SW_PKDET_DONE, &caldata->cal_flags);
    1321                 :            : 
    1322   [ +  -  +  + ]:          3 :         if ((ah->caps.hw_caps & ATH9K_HW_CAP_RTT) && caldata) {
    1323         [ +  - ]:          2 :                 if (IS_CHAN_2GHZ(chan)){
    1324                 :          2 :                         caldata->caldac[0] = REG_READ_FIELD(ah,
    1325                 :            :                                                     AR_PHY_65NM_RXRF_AGC(0),
    1326                 :            :                                                     AR_PHY_65NM_RXRF_AGC_AGC2G_CALDAC_OVR);
    1327                 :          2 :                         caldata->caldac[1] = REG_READ_FIELD(ah,
    1328                 :            :                                                     AR_PHY_65NM_RXRF_AGC(1),
    1329                 :            :                                                     AR_PHY_65NM_RXRF_AGC_AGC2G_CALDAC_OVR);
    1330                 :            :                 } else {
    1331                 :          0 :                         caldata->caldac[0] = REG_READ_FIELD(ah,
    1332                 :            :                                                     AR_PHY_65NM_RXRF_AGC(0),
    1333                 :            :                                                     AR_PHY_65NM_RXRF_AGC_AGC5G_CALDAC_OVR);
    1334                 :          0 :                         caldata->caldac[1] = REG_READ_FIELD(ah,
    1335                 :            :                                                     AR_PHY_65NM_RXRF_AGC(1),
    1336                 :            :                                                     AR_PHY_65NM_RXRF_AGC_AGC5G_CALDAC_OVR);
    1337                 :            :                 }
    1338                 :            :         }
    1339                 :            : }
    1340                 :            : 
    1341                 :         12 : static void ar9003_hw_cl_cal_post_proc(struct ath_hw *ah, bool is_reusable)
    1342                 :            : {
    1343                 :         12 :         u32 cl_idx[AR9300_MAX_CHAINS] = { AR_PHY_CL_TAB_0,
    1344                 :            :                                           AR_PHY_CL_TAB_1,
    1345                 :            :                                           AR_PHY_CL_TAB_2 };
    1346                 :         12 :         struct ath9k_hw_cal_data *caldata = ah->caldata;
    1347                 :         12 :         bool txclcal_done = false;
    1348                 :         12 :         int i, j;
    1349                 :            : 
    1350   [ +  +  +  + ]:         12 :         if (!caldata || !(ah->enabled_cals & TX_CL_CAL))
    1351                 :         10 :                 return;
    1352                 :            : 
    1353         [ -  + ]:          2 :         txclcal_done = !!(REG_READ(ah, AR_PHY_AGC_CONTROL) &
    1354                 :            :                           AR_PHY_AGC_CONTROL_CLC_SUCCESS);
    1355                 :            : 
    1356         [ -  + ]:          2 :         if (test_bit(TXCLCAL_DONE, &caldata->cal_flags)) {
    1357         [ #  # ]:          0 :                 for (i = 0; i < AR9300_MAX_CHAINS; i++) {
    1358         [ #  # ]:          0 :                         if (!(ah->txchainmask & (1 << i)))
    1359                 :          0 :                                 continue;
    1360         [ #  # ]:          0 :                         for (j = 0; j < MAX_CL_TAB_ENTRY; j++)
    1361                 :          0 :                                 REG_WRITE(ah, CL_TAB_ENTRY(cl_idx[i]),
    1362                 :            :                                           caldata->tx_clcal[i][j]);
    1363                 :            :                 }
    1364   [ +  -  -  + ]:          2 :         } else if (is_reusable && txclcal_done) {
    1365         [ #  # ]:          0 :                 for (i = 0; i < AR9300_MAX_CHAINS; i++) {
    1366         [ #  # ]:          0 :                         if (!(ah->txchainmask & (1 << i)))
    1367                 :          0 :                                 continue;
    1368         [ #  # ]:          0 :                         for (j = 0; j < MAX_CL_TAB_ENTRY; j++)
    1369                 :          0 :                                 caldata->tx_clcal[i][j] =
    1370                 :          0 :                                         REG_READ(ah, CL_TAB_ENTRY(cl_idx[i]));
    1371                 :            :                 }
    1372                 :          0 :                 set_bit(TXCLCAL_DONE, &caldata->cal_flags);
    1373                 :            :         }
    1374                 :            : }
    1375                 :            : 
    1376                 :         41 : static void ar9003_hw_init_cal_common(struct ath_hw *ah)
    1377                 :            : {
    1378                 :         41 :         struct ath9k_hw_cal_data *caldata = ah->caldata;
    1379                 :            : 
    1380                 :            :         /* Initialize list pointers */
    1381                 :         41 :         ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL;
    1382                 :            : 
    1383                 :         41 :         INIT_CAL(&ah->iq_caldata);
    1384                 :         41 :         INSERT_CAL(ah, &ah->iq_caldata);
    1385                 :            : 
    1386                 :            :         /* Initialize current pointer to first element in list */
    1387                 :         41 :         ah->cal_list_curr = ah->cal_list;
    1388                 :            : 
    1389         [ +  - ]:         41 :         if (ah->cal_list_curr)
    1390                 :         41 :                 ath9k_hw_reset_calibration(ah, ah->cal_list_curr);
    1391                 :            : 
    1392         [ +  + ]:         41 :         if (caldata)
    1393                 :         37 :                 caldata->CalValid = 0;
    1394                 :         41 : }
    1395                 :            : 
    1396                 :         12 : static bool ar9003_hw_init_cal_pcoem(struct ath_hw *ah,
    1397                 :            :                                      struct ath9k_channel *chan)
    1398                 :            : {
    1399                 :         12 :         struct ath_common *common = ath9k_hw_common(ah);
    1400                 :         12 :         struct ath9k_hw_cal_data *caldata = ah->caldata;
    1401                 :         12 :         bool txiqcal_done = false;
    1402                 :         12 :         bool is_reusable = true, status = true;
    1403                 :         12 :         bool run_rtt_cal = false, run_agc_cal;
    1404                 :         12 :         bool rtt = !!(ah->caps.hw_caps & ATH9K_HW_CAP_RTT);
    1405                 :         12 :         u32 rx_delay = 0;
    1406                 :         12 :         u32 agc_ctrl = 0, agc_supp_cals = AR_PHY_AGC_CONTROL_OFFSET_CAL |
    1407                 :            :                                           AR_PHY_AGC_CONTROL_FLTR_CAL   |
    1408                 :            :                                           AR_PHY_AGC_CONTROL_PKDET_CAL;
    1409                 :            : 
    1410                 :            :         /* Use chip chainmask only for calibration */
    1411                 :         12 :         ar9003_hw_set_chain_masks(ah, ah->caps.rx_chainmask, ah->caps.tx_chainmask);
    1412                 :            : 
    1413         [ +  - ]:         12 :         if (rtt) {
    1414         [ +  + ]:         12 :                 if (!ar9003_hw_rtt_restore(ah, chan))
    1415                 :          3 :                         run_rtt_cal = true;
    1416                 :            : 
    1417                 :          3 :                 if (run_rtt_cal)
    1418         [ -  + ]:          3 :                         ath_dbg(common, CALIBRATE, "RTT calibration to be done\n");
    1419                 :            :         }
    1420                 :            : 
    1421                 :         12 :         run_agc_cal = run_rtt_cal;
    1422                 :            : 
    1423         [ +  + ]:         12 :         if (run_rtt_cal) {
    1424                 :          3 :                 ar9003_hw_rtt_enable(ah);
    1425                 :          3 :                 ar9003_hw_rtt_set_mask(ah, 0x00);
    1426                 :          3 :                 ar9003_hw_rtt_clear_hist(ah);
    1427                 :            :         }
    1428                 :            : 
    1429         [ +  - ]:         12 :         if (rtt) {
    1430         [ +  + ]:         12 :                 if (!run_rtt_cal) {
    1431         [ -  + ]:          9 :                         agc_ctrl = REG_READ(ah, AR_PHY_AGC_CONTROL);
    1432                 :          9 :                         agc_supp_cals &= agc_ctrl;
    1433                 :          9 :                         agc_ctrl &= ~(AR_PHY_AGC_CONTROL_OFFSET_CAL |
    1434                 :            :                                       AR_PHY_AGC_CONTROL_FLTR_CAL |
    1435                 :            :                                       AR_PHY_AGC_CONTROL_PKDET_CAL);
    1436         [ -  + ]:          9 :                         REG_WRITE(ah, AR_PHY_AGC_CONTROL, agc_ctrl);
    1437                 :            :                 } else {
    1438                 :            :                         if (ah->ah_flags & AH_FASTCC)
    1439                 :            :                                 run_agc_cal = true;
    1440                 :            :                 }
    1441                 :            :         }
    1442                 :            : 
    1443         [ +  + ]:         12 :         if (ah->enabled_cals & TX_CL_CAL) {
    1444   [ +  -  -  + ]:          2 :                 if (caldata && test_bit(TXCLCAL_DONE, &caldata->cal_flags))
    1445                 :          0 :                         REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL,
    1446                 :            :                                     AR_PHY_CL_CAL_ENABLE);
    1447                 :            :                 else {
    1448                 :          2 :                         REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL,
    1449                 :            :                                     AR_PHY_CL_CAL_ENABLE);
    1450                 :          2 :                         run_agc_cal = true;
    1451                 :            :                 }
    1452                 :            :         }
    1453                 :            : 
    1454         [ +  - ]:         12 :         if ((IS_CHAN_HALF_RATE(chan) || IS_CHAN_QUARTER_RATE(chan)) ||
    1455         [ +  + ]:         12 :             !(ah->enabled_cals & TX_IQ_CAL))
    1456                 :          8 :                 goto skip_tx_iqcal;
    1457                 :            : 
    1458                 :            :         /* Do Tx IQ Calibration */
    1459         [ +  - ]:          8 :         REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_1,
    1460                 :            :                       AR_PHY_TX_IQCAL_CONTROL_1_IQCORR_I_Q_COFF_DELPT,
    1461                 :            :                       DELPT);
    1462                 :            : 
    1463                 :            :         /*
    1464                 :            :          * For AR9485 or later chips, TxIQ cal runs as part of
    1465                 :            :          * AGC calibration
    1466                 :            :          */
    1467         [ -  + ]:          4 :         if (ah->enabled_cals & TX_IQ_ON_AGC_CAL) {
    1468   [ +  -  +  - ]:          4 :                 if (caldata && !test_bit(TXIQCAL_DONE, &caldata->cal_flags))
    1469         [ +  - ]:          8 :                         REG_SET_BIT(ah, AR_PHY_TX_IQCAL_CONTROL_0,
    1470                 :            :                                     AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL);
    1471                 :            :                 else
    1472         [ #  # ]:          0 :                         REG_CLR_BIT(ah, AR_PHY_TX_IQCAL_CONTROL_0,
    1473                 :            :                                     AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL);
    1474                 :            :                 txiqcal_done = run_agc_cal = true;
    1475                 :            :         }
    1476                 :            : 
    1477                 :          0 : skip_tx_iqcal:
    1478   [ -  +  -  +  :         24 :         if (ath9k_hw_mci_is_enabled(ah) && IS_CHAN_2GHZ(chan) && run_agc_cal)
             -  -  -  - ]
    1479                 :          0 :                 ar9003_mci_init_cal_req(ah, &is_reusable);
    1480                 :            : 
    1481         [ +  + ]:         12 :         if (REG_READ(ah, AR_PHY_CL_CAL_CTL) & AR_PHY_CL_CAL_ENABLE) {
    1482                 :          2 :                 rx_delay = REG_READ(ah, AR_PHY_RX_DELAY);
    1483                 :            :                 /* Disable BB_active */
    1484                 :          2 :                 REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS);
    1485                 :          2 :                 udelay(5);
    1486                 :          2 :                 REG_WRITE(ah, AR_PHY_RX_DELAY, AR_PHY_RX_DELAY_DELAY);
    1487                 :          2 :                 REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
    1488                 :            :         }
    1489                 :            : 
    1490   [ +  +  +  - ]:         12 :         if (run_agc_cal || !(ah->ah_flags & AH_FASTCC)) {
    1491                 :            :                 /* Calibrate the AGC */
    1492         [ -  + ]:         12 :                 REG_WRITE(ah, AR_PHY_AGC_CONTROL,
    1493                 :            :                           REG_READ(ah, AR_PHY_AGC_CONTROL) |
    1494                 :            :                           AR_PHY_AGC_CONTROL_CAL);
    1495                 :            : 
    1496                 :            :                 /* Poll for offset calibration complete */
    1497         [ -  + ]:         12 :                 status = ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL,
    1498                 :            :                                        AR_PHY_AGC_CONTROL_CAL,
    1499                 :            :                                        0, AH_WAIT_TIMEOUT);
    1500                 :            : 
    1501                 :         12 :                 ar9003_hw_do_pcoem_manual_peak_cal(ah, chan, run_rtt_cal);
    1502                 :            :         }
    1503                 :            : 
    1504         [ +  + ]:         12 :         if (REG_READ(ah, AR_PHY_CL_CAL_CTL) & AR_PHY_CL_CAL_ENABLE) {
    1505                 :          1 :                 REG_WRITE(ah, AR_PHY_RX_DELAY, rx_delay);
    1506                 :          1 :                 udelay(5);
    1507                 :            :         }
    1508                 :            : 
    1509   [ -  +  -  +  :         24 :         if (ath9k_hw_mci_is_enabled(ah) && IS_CHAN_2GHZ(chan) && run_agc_cal)
             -  -  -  - ]
    1510                 :          0 :                 ar9003_mci_init_cal_done(ah);
    1511                 :            : 
    1512   [ +  -  +  + ]:         12 :         if (rtt && !run_rtt_cal) {
    1513                 :          9 :                 agc_ctrl |= agc_supp_cals;
    1514         [ -  + ]:          9 :                 REG_WRITE(ah, AR_PHY_AGC_CONTROL, agc_ctrl);
    1515                 :            :         }
    1516                 :            : 
    1517         [ -  + ]:         12 :         if (!status) {
    1518         [ #  # ]:          0 :                 if (run_rtt_cal)
    1519                 :          0 :                         ar9003_hw_rtt_disable(ah);
    1520                 :            : 
    1521         [ #  # ]:          0 :                 ath_dbg(common, CALIBRATE,
    1522                 :            :                         "offset calibration failed to complete in %d ms; noisy environment?\n",
    1523                 :            :                         AH_WAIT_TIMEOUT / 1000);
    1524                 :          0 :                 return false;
    1525                 :            :         }
    1526                 :            : 
    1527         [ +  + ]:         12 :         if (txiqcal_done)
    1528                 :          4 :                 ar9003_hw_tx_iq_cal_post_proc(ah, 0, is_reusable);
    1529   [ +  +  -  + ]:          8 :         else if (caldata && test_bit(TXIQCAL_DONE, &caldata->cal_flags))
    1530                 :          0 :                 ar9003_hw_tx_iq_cal_reload(ah);
    1531                 :            : 
    1532                 :         12 :         ar9003_hw_cl_cal_post_proc(ah, is_reusable);
    1533                 :            : 
    1534   [ +  +  +  + ]:         12 :         if (run_rtt_cal && caldata) {
    1535         [ +  - ]:          2 :                 if (is_reusable) {
    1536         [ -  + ]:          2 :                         if (!ath9k_hw_rfbus_req(ah)) {
    1537                 :          0 :                                 ath_err(ath9k_hw_common(ah),
    1538                 :            :                                         "Could not stop baseband\n");
    1539                 :            :                         } else {
    1540                 :          2 :                                 ar9003_hw_rtt_fill_hist(ah);
    1541                 :            : 
    1542         [ +  - ]:          2 :                                 if (test_bit(SW_PKDET_DONE, &caldata->cal_flags))
    1543                 :          2 :                                         ar9003_hw_rtt_load_hist(ah);
    1544                 :            :                         }
    1545                 :            : 
    1546                 :          2 :                         ath9k_hw_rfbus_done(ah);
    1547                 :            :                 }
    1548                 :            : 
    1549                 :          2 :                 ar9003_hw_rtt_disable(ah);
    1550                 :            :         }
    1551                 :            : 
    1552                 :            :         /* Revert chainmask to runtime parameters */
    1553                 :         12 :         ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask);
    1554                 :            : 
    1555                 :         12 :         ar9003_hw_init_cal_common(ah);
    1556                 :            : 
    1557                 :         12 :         return true;
    1558                 :            : }
    1559                 :            : 
    1560                 :         29 : static bool do_ar9003_agc_cal(struct ath_hw *ah)
    1561                 :            : {
    1562         [ -  + ]:         29 :         struct ath_common *common = ath9k_hw_common(ah);
    1563                 :         29 :         bool status;
    1564                 :            : 
    1565         [ -  + ]:         29 :         REG_WRITE(ah, AR_PHY_AGC_CONTROL,
    1566                 :            :                   REG_READ(ah, AR_PHY_AGC_CONTROL) |
    1567                 :            :                   AR_PHY_AGC_CONTROL_CAL);
    1568                 :            : 
    1569         [ -  + ]:         29 :         status = ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL,
    1570                 :            :                                AR_PHY_AGC_CONTROL_CAL,
    1571                 :            :                                0, AH_WAIT_TIMEOUT);
    1572         [ -  + ]:         29 :         if (!status) {
    1573         [ #  # ]:          0 :                 ath_dbg(common, CALIBRATE,
    1574                 :            :                         "offset calibration failed to complete in %d ms,"
    1575                 :            :                         "noisy environment?\n",
    1576                 :            :                         AH_WAIT_TIMEOUT / 1000);
    1577                 :          0 :                 return false;
    1578                 :            :         }
    1579                 :            : 
    1580                 :            :         return true;
    1581                 :            : }
    1582                 :            : 
    1583                 :         29 : static bool ar9003_hw_init_cal_soc(struct ath_hw *ah,
    1584                 :            :                                    struct ath9k_channel *chan)
    1585                 :            : {
    1586                 :         29 :         bool txiqcal_done = false;
    1587                 :         29 :         bool status = true;
    1588                 :         29 :         bool run_agc_cal = false, sep_iq_cal = false;
    1589                 :         29 :         int i = 0;
    1590                 :            : 
    1591                 :            :         /* Use chip chainmask only for calibration */
    1592                 :         29 :         ar9003_hw_set_chain_masks(ah, ah->caps.rx_chainmask, ah->caps.tx_chainmask);
    1593                 :            : 
    1594         [ +  + ]:         29 :         if (ah->enabled_cals & TX_CL_CAL) {
    1595                 :          4 :                 REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
    1596                 :          4 :                 run_agc_cal = true;
    1597                 :            :         }
    1598                 :            : 
    1599         [ -  + ]:         29 :         if (IS_CHAN_HALF_RATE(chan) || IS_CHAN_QUARTER_RATE(chan))
    1600                 :          0 :                 goto skip_tx_iqcal;
    1601                 :            : 
    1602                 :            :         /* Do Tx IQ Calibration */
    1603         [ +  - ]:         58 :         REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_1,
    1604                 :            :                       AR_PHY_TX_IQCAL_CONTROL_1_IQCORR_I_Q_COFF_DELPT,
    1605                 :            :                       DELPT);
    1606                 :            : 
    1607                 :            :         /*
    1608                 :            :          * For AR9485 or later chips, TxIQ cal runs as part of
    1609                 :            :          * AGC calibration. Specifically, AR9550 in SoC chips.
    1610                 :            :          */
    1611         [ +  + ]:         29 :         if (ah->enabled_cals & TX_IQ_ON_AGC_CAL) {
    1612   [ +  -  +  + ]:         38 :                 if (REG_READ_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_0,
    1613                 :            :                                    AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL)) {
    1614                 :            :                                 txiqcal_done = true;
    1615                 :            :                 } else {
    1616                 :         12 :                         txiqcal_done = false;
    1617                 :            :                 }
    1618                 :            :                 run_agc_cal = true;
    1619                 :            :         } else {
    1620                 :            :                 sep_iq_cal = true;
    1621                 :            :                 run_agc_cal = true;
    1622                 :            :         }
    1623                 :            : 
    1624                 :            :         /*
    1625                 :            :          * In the SoC family, this will run for AR9300, AR9331 and AR9340.
    1626                 :            :          */
    1627                 :         10 :         if (sep_iq_cal) {
    1628                 :         10 :                 txiqcal_done = ar9003_hw_tx_iq_cal_run(ah);
    1629                 :         10 :                 REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS);
    1630                 :         10 :                 udelay(5);
    1631                 :         10 :                 REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
    1632                 :            :         }
    1633                 :            : 
    1634   [ -  +  -  - ]:         29 :         if (AR_SREV_9550(ah) && IS_CHAN_2GHZ(chan)) {
    1635         [ #  # ]:          0 :                 if (!ar9003_hw_dynamic_osdac_selection(ah, txiqcal_done))
    1636                 :            :                         return false;
    1637                 :            :         }
    1638                 :            : 
    1639                 :         29 : skip_tx_iqcal:
    1640   [ #  #  #  # ]:          0 :         if (run_agc_cal || !(ah->ah_flags & AH_FASTCC)) {
    1641         [ +  + ]:        116 :                 for (i = 0; i < AR9300_MAX_CHAINS; i++) {
    1642         [ +  + ]:         87 :                         if (!(ah->rxchainmask & (1 << i)))
    1643                 :         11 :                                 continue;
    1644                 :            : 
    1645                 :         76 :                         ar9003_hw_manual_peak_cal(ah, i,
    1646                 :         76 :                                                   IS_CHAN_2GHZ(chan));
    1647                 :            :                 }
    1648                 :            : 
    1649                 :            :                 /*
    1650                 :            :                  * For non-AR9550 chips, we just trigger AGC calibration
    1651                 :            :                  * in the HW, poll for completion and then process
    1652                 :            :                  * the results.
    1653                 :            :                  *
    1654                 :            :                  * For AR955x, we run it multiple times and use
    1655                 :            :                  * median IQ correction.
    1656                 :            :                  */
    1657         [ +  - ]:         29 :                 if (!AR_SREV_9550(ah)) {
    1658                 :         29 :                         status = do_ar9003_agc_cal(ah);
    1659         [ +  - ]:         29 :                         if (!status)
    1660                 :            :                                 return false;
    1661                 :            : 
    1662         [ +  + ]:         29 :                         if (txiqcal_done)
    1663                 :         17 :                                 ar9003_hw_tx_iq_cal_post_proc(ah, 0, false);
    1664                 :            :                 } else {
    1665         [ #  # ]:          0 :                         if (!txiqcal_done) {
    1666                 :          0 :                                 status = do_ar9003_agc_cal(ah);
    1667         [ #  # ]:          0 :                                 if (!status)
    1668                 :            :                                         return false;
    1669                 :            :                         } else {
    1670         [ #  # ]:          0 :                                 for (i = 0; i < MAXIQCAL; i++) {
    1671                 :          0 :                                         status = do_ar9003_agc_cal(ah);
    1672         [ #  # ]:          0 :                                         if (!status)
    1673                 :            :                                                 return false;
    1674                 :          0 :                                         ar9003_hw_tx_iq_cal_post_proc(ah, i, false);
    1675                 :            :                                 }
    1676                 :            :                         }
    1677                 :            :                 }
    1678                 :            :         }
    1679                 :            : 
    1680                 :            :         /* Revert chainmask to runtime parameters */
    1681                 :         29 :         ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask);
    1682                 :            : 
    1683                 :         29 :         ar9003_hw_init_cal_common(ah);
    1684                 :            : 
    1685                 :         29 :         return true;
    1686                 :            : }
    1687                 :            : 
    1688                 :          5 : void ar9003_hw_attach_calib_ops(struct ath_hw *ah)
    1689                 :            : {
    1690         [ +  + ]:          5 :         struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
    1691         [ +  + ]:          5 :         struct ath_hw_ops *ops = ath9k_hw_ops(ah);
    1692                 :            : 
    1693   [ +  +  +  -  :          5 :         if (AR_SREV_9003_PCOEM(ah))
                   -  + ]
    1694                 :          1 :                 priv_ops->init_cal = ar9003_hw_init_cal_pcoem;
    1695                 :            :         else
    1696                 :          4 :                 priv_ops->init_cal = ar9003_hw_init_cal_soc;
    1697                 :            : 
    1698                 :          5 :         priv_ops->init_cal_settings = ar9003_hw_init_cal_settings;
    1699                 :          5 :         priv_ops->setup_calibration = ar9003_hw_setup_calibration;
    1700                 :            : 
    1701                 :          5 :         ops->calibrate = ar9003_hw_calibrate;
    1702                 :          5 : }

Generated by: LCOV version 1.14