The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/ath/ath_hal/ar5212/ar5212_rfgain.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * SPDX-License-Identifier: ISC
    3  *
    4  * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
    5  * Copyright (c) 2002-2008 Atheros Communications, Inc.
    6  *
    7  * Permission to use, copy, modify, and/or distribute this software for any
    8  * purpose with or without fee is hereby granted, provided that the above
    9  * copyright notice and this permission notice appear in all copies.
   10  *
   11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
   13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
   14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
   15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
   16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
   17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   18  *
   19  * $FreeBSD$
   20  */
   21 #include "opt_ah.h"
   22 
   23 #include "ah.h"
   24 #include "ah_internal.h"
   25 #include "ah_devid.h"
   26 
   27 #include "ar5212/ar5212.h"
   28 #include "ar5212/ar5212reg.h"
   29 #include "ar5212/ar5212phy.h"
   30 
   31 #include "ah_eeprom_v3.h"
   32 
   33 static const GAIN_OPTIMIZATION_LADDER gainLadder = {
   34         9,                                      /* numStepsInLadder */
   35         4,                                      /* defaultStepNum */
   36         { { {4, 1, 1, 1},  6, "FG8"},
   37           { {4, 0, 1, 1},  4, "FG7"},
   38           { {3, 1, 1, 1},  3, "FG6"},
   39           { {4, 0, 0, 1},  1, "FG5"},
   40           { {4, 1, 1, 0},  0, "FG4"},   /* noJack */
   41           { {4, 0, 1, 0}, -2, "FG3"},   /* halfJack */
   42           { {3, 1, 1, 0}, -3, "FG2"},   /* clip3 */
   43           { {4, 0, 0, 0}, -4, "FG1"},   /* noJack */
   44           { {2, 1, 1, 0}, -6, "FG0"}    /* clip2 */
   45         }
   46 };
   47 
   48 static const GAIN_OPTIMIZATION_LADDER gainLadder5112 = {
   49         8,                                      /* numStepsInLadder */
   50         1,                                      /* defaultStepNum */
   51         { { {3, 0,0,0, 0,0,0},   6, "FG7"},     /* most fixed gain */
   52           { {2, 0,0,0, 0,0,0},   0, "FG6"},
   53           { {1, 0,0,0, 0,0,0},  -3, "FG5"},
   54           { {0, 0,0,0, 0,0,0},  -6, "FG4"},
   55           { {0, 1,1,0, 0,0,0},  -8, "FG3"},
   56           { {0, 1,1,0, 1,1,0}, -10, "FG2"},
   57           { {0, 1,0,1, 1,1,0}, -13, "FG1"},
   58           { {0, 1,0,1, 1,0,1}, -16, "FG0"},     /* least fixed gain */
   59         }
   60 };
   61 
   62 /*
   63  * Initialize the gain structure to good values
   64  */
   65 void
   66 ar5212InitializeGainValues(struct ath_hal *ah)
   67 {
   68         struct ath_hal_5212 *ahp = AH5212(ah);
   69         GAIN_VALUES *gv = &ahp->ah_gainValues;
   70 
   71         /* initialize gain optimization values */
   72         if (IS_RAD5112_ANY(ah)) {
   73                 gv->currStepNum = gainLadder5112.defaultStepNum;
   74                 gv->currStep =
   75                         &gainLadder5112.optStep[gainLadder5112.defaultStepNum];
   76                 gv->active = AH_TRUE;
   77                 gv->loTrig = 20;
   78                 gv->hiTrig = 85;
   79         } else {
   80                 gv->currStepNum = gainLadder.defaultStepNum;
   81                 gv->currStep = &gainLadder.optStep[gainLadder.defaultStepNum];
   82                 gv->active = AH_TRUE;
   83                 gv->loTrig = 20;
   84                 gv->hiTrig = 35;
   85         }
   86 }
   87 
   88 #define MAX_ANALOG_START        319             /* XXX */
   89 
   90 /*
   91  * Find analog bits of given parameter data and return a reversed value
   92  */
   93 static uint32_t
   94 ar5212GetRfField(uint32_t *rfBuf, uint32_t numBits, uint32_t firstBit, uint32_t column)
   95 {
   96         uint32_t reg32 = 0, mask, arrayEntry, lastBit;
   97         uint32_t bitPosition, bitsShifted;
   98         int32_t bitsLeft;
   99 
  100         HALASSERT(column <= 3);
  101         HALASSERT(numBits <= 32);
  102         HALASSERT(firstBit + numBits <= MAX_ANALOG_START);
  103 
  104         arrayEntry = (firstBit - 1) / 8;
  105         bitPosition = (firstBit - 1) % 8;
  106         bitsLeft = numBits;
  107         bitsShifted = 0;
  108         while (bitsLeft > 0) {
  109                 lastBit = (bitPosition + bitsLeft > 8) ?
  110                         (8) : (bitPosition + bitsLeft);
  111                 mask = (((1 << lastBit) - 1) ^ ((1 << bitPosition) - 1)) <<
  112                         (column * 8);
  113                 reg32 |= (((rfBuf[arrayEntry] & mask) >> (column * 8)) >>
  114                         bitPosition) << bitsShifted;
  115                 bitsShifted += lastBit - bitPosition;
  116                 bitsLeft -= (8 - bitPosition);
  117                 bitPosition = 0;
  118                 arrayEntry++;
  119         }
  120         reg32 = ath_hal_reverseBits(reg32, numBits);
  121         return reg32;
  122 }
  123 
  124 static HAL_BOOL
  125 ar5212InvalidGainReadback(struct ath_hal *ah, GAIN_VALUES *gv)
  126 {
  127         uint32_t gStep, g, mixOvr;
  128         uint32_t L1, L2, L3, L4;
  129 
  130         if (IS_RAD5112_ANY(ah)) {
  131                 mixOvr = ar5212GetRfField(ar5212GetRfBank(ah, 7), 1, 36, 0);
  132                 L1 = 0;
  133                 L2 = 107;
  134                 L3 = 0;
  135                 L4 = 107;
  136                 if (mixOvr == 1) {
  137                         L2 = 83;
  138                         L4 = 83;
  139                         gv->hiTrig = 55;
  140                 }
  141         } else {
  142                 gStep = ar5212GetRfField(ar5212GetRfBank(ah, 7), 6, 37, 0);
  143 
  144                 L1 = 0;
  145                 L2 = (gStep == 0x3f) ? 50 : gStep + 4;
  146                 L3 = (gStep != 0x3f) ? 0x40 : L1;
  147                 L4 = L3 + 50;
  148 
  149                 gv->loTrig = L1 + (gStep == 0x3f ? DYN_ADJ_LO_MARGIN : 0);
  150                 /* never adjust if != 0x3f */
  151                 gv->hiTrig = L4 - (gStep == 0x3f ? DYN_ADJ_UP_MARGIN : -5);
  152         }
  153         g = gv->currGain;
  154 
  155         return !((g >= L1 && g<= L2) || (g >= L3 && g <= L4));
  156 }
  157 
  158 /*
  159  * Enable the probe gain check on the next packet
  160  */
  161 void
  162 ar5212RequestRfgain(struct ath_hal *ah)
  163 {
  164         struct ath_hal_5212 *ahp = AH5212(ah);
  165         uint32_t probePowerIndex;
  166 
  167         /* Enable the gain readback probe */
  168         probePowerIndex = ahp->ah_ofdmTxPower + ahp->ah_txPowerIndexOffset;
  169         OS_REG_WRITE(ah, AR_PHY_PAPD_PROBE,
  170                   SM(probePowerIndex, AR_PHY_PAPD_PROBE_POWERTX)
  171                 | AR_PHY_PAPD_PROBE_NEXT_TX);
  172 
  173         ahp->ah_rfgainState = HAL_RFGAIN_READ_REQUESTED;
  174 }
  175 
  176 /*
  177  * Check to see if our readback gain level sits within the linear
  178  * region of our current variable attenuation window
  179  */
  180 static HAL_BOOL
  181 ar5212IsGainAdjustNeeded(struct ath_hal *ah, const GAIN_VALUES *gv)
  182 {
  183         return (gv->currGain <= gv->loTrig || gv->currGain >= gv->hiTrig);
  184 }
  185 
  186 /*
  187  * Move the rabbit ears in the correct direction.
  188  */
  189 static int32_t 
  190 ar5212AdjustGain(struct ath_hal *ah, GAIN_VALUES *gv)
  191 {
  192         const GAIN_OPTIMIZATION_LADDER *gl;
  193 
  194         if (IS_RAD5112_ANY(ah))
  195                 gl = &gainLadder5112;
  196         else
  197                 gl = &gainLadder;
  198         gv->currStep = &gl->optStep[gv->currStepNum];
  199         if (gv->currGain >= gv->hiTrig) {
  200                 if (gv->currStepNum == 0) {
  201                         HALDEBUG(ah, HAL_DEBUG_ANY, "%s: Max gain limit.\n",
  202                             __func__);
  203                         return -1;
  204                 }
  205                 HALDEBUG(ah, HAL_DEBUG_RFPARAM,
  206                     "%s: Adding gain: currG=%d [%s] --> ",
  207                     __func__, gv->currGain, gv->currStep->stepName);
  208                 gv->targetGain = gv->currGain;
  209                 while (gv->targetGain >= gv->hiTrig && gv->currStepNum > 0) {
  210                         gv->targetGain -= 2 * (gl->optStep[--(gv->currStepNum)].stepGain -
  211                                 gv->currStep->stepGain);
  212                         gv->currStep = &gl->optStep[gv->currStepNum];
  213                 }
  214                 HALDEBUG(ah, HAL_DEBUG_RFPARAM, "targG=%d [%s]\n",
  215                     gv->targetGain, gv->currStep->stepName);
  216                 return 1;
  217         }
  218         if (gv->currGain <= gv->loTrig) {
  219                 if (gv->currStepNum == gl->numStepsInLadder-1) {
  220                         HALDEBUG(ah, HAL_DEBUG_RFPARAM,
  221                             "%s: Min gain limit.\n", __func__);
  222                         return -2;
  223                 }
  224                 HALDEBUG(ah, HAL_DEBUG_RFPARAM,
  225                     "%s: Deducting gain: currG=%d [%s] --> ",
  226                     __func__, gv->currGain, gv->currStep->stepName);
  227                 gv->targetGain = gv->currGain;
  228                 while (gv->targetGain <= gv->loTrig &&
  229                       gv->currStepNum < (gl->numStepsInLadder - 1)) {
  230                         gv->targetGain -= 2 *
  231                                 (gl->optStep[++(gv->currStepNum)].stepGain - gv->currStep->stepGain);
  232                         gv->currStep = &gl->optStep[gv->currStepNum];
  233                 }
  234                 HALDEBUG(ah, HAL_DEBUG_RFPARAM, "targG=%d [%s]\n",
  235                     gv->targetGain, gv->currStep->stepName);
  236                 return 2;
  237         }
  238         return 0;               /* caller didn't call needAdjGain first */
  239 }
  240 
  241 /*
  242  * Read rf register to determine if gainF needs correction
  243  */
  244 static uint32_t
  245 ar5212GetGainFCorrection(struct ath_hal *ah)
  246 {
  247         struct ath_hal_5212 *ahp = AH5212(ah);
  248         uint32_t correction;
  249 
  250         HALASSERT(IS_RADX112_REV2(ah));
  251 
  252         correction = 0;
  253         if (ar5212GetRfField(ar5212GetRfBank(ah, 7), 1, 36, 0) == 1) {
  254                 const GAIN_VALUES *gv = &ahp->ah_gainValues;
  255                 uint32_t mixGain = gv->currStep->paramVal[0];
  256                 uint32_t gainStep =
  257                         ar5212GetRfField(ar5212GetRfBank(ah, 7), 4, 32, 0);
  258                 switch (mixGain) {
  259                 case 0 :
  260                         correction = 0;
  261                         break;
  262                 case 1 :
  263                         correction = gainStep;
  264                         break;
  265                 case 2 :
  266                         correction = 2 * gainStep - 5;
  267                         break;
  268                 case 3 :
  269                         correction = 2 * gainStep;
  270                         break;
  271                 }
  272         }
  273         return correction;
  274 }
  275 
  276 /*
  277  * Exported call to check for a recent gain reading and return
  278  * the current state of the thermal calibration gain engine.
  279  */
  280 HAL_RFGAIN
  281 ar5212GetRfgain(struct ath_hal *ah)
  282 {
  283         struct ath_hal_5212 *ahp = AH5212(ah);
  284         GAIN_VALUES *gv = &ahp->ah_gainValues;
  285         uint32_t rddata, probeType;
  286 
  287         /* NB: beware of touching the BB when PHY is powered down */
  288         if (!gv->active || !ahp->ah_phyPowerOn)
  289                 return HAL_RFGAIN_INACTIVE;
  290 
  291         if (ahp->ah_rfgainState == HAL_RFGAIN_READ_REQUESTED) {
  292                 /* Caller had asked to setup a new reading. Check it. */
  293                 rddata = OS_REG_READ(ah, AR_PHY_PAPD_PROBE);
  294 
  295                 if ((rddata & AR_PHY_PAPD_PROBE_NEXT_TX) == 0) {
  296                         /* bit got cleared, we have a new reading. */
  297                         gv->currGain = rddata >> AR_PHY_PAPD_PROBE_GAINF_S;
  298                         probeType = MS(rddata, AR_PHY_PAPD_PROBE_TYPE);
  299                         if (probeType == AR_PHY_PAPD_PROBE_TYPE_CCK) {
  300                                 const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
  301 
  302                                 HALASSERT(IS_RAD5112_ANY(ah));
  303                                 HALASSERT(ah->ah_magic == AR5212_MAGIC);
  304                                 if (AH_PRIVATE(ah)->ah_phyRev >= AR_PHY_CHIP_ID_REV_2)
  305                                         gv->currGain += ee->ee_cckOfdmGainDelta;
  306                                 else
  307                                         gv->currGain += PHY_PROBE_CCK_CORRECTION;
  308                         }
  309                         if (IS_RADX112_REV2(ah)) {
  310                                 uint32_t correct = ar5212GetGainFCorrection(ah);
  311                                 if (gv->currGain >= correct)
  312                                         gv->currGain -= correct;
  313                                 else
  314                                         gv->currGain = 0;
  315                         }
  316                         /* inactive by default */
  317                         ahp->ah_rfgainState = HAL_RFGAIN_INACTIVE;
  318 
  319                         if (!ar5212InvalidGainReadback(ah, gv) &&
  320                             ar5212IsGainAdjustNeeded(ah, gv) &&
  321                             ar5212AdjustGain(ah, gv) > 0) {
  322                                 /*
  323                                  * Change needed. Copy ladder info
  324                                  * into eeprom info.
  325                                  */
  326                                 ahp->ah_rfgainState = HAL_RFGAIN_NEED_CHANGE;
  327                                 /* for ap51 */
  328                                 ahp->ah_cwCalRequire = AH_TRUE;
  329                                 /* Request IQ recalibration for temperature chang */
  330                                 ahp->ah_bIQCalibration = IQ_CAL_INACTIVE;
  331                         }
  332                 }
  333         }
  334         return ahp->ah_rfgainState;
  335 }

Cache object: 3d301031669d60cb3c315a806c885717


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.