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/ar5312/ar5312_reset.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-2009 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 #ifdef AH_SUPPORT_AR5312
   24 
   25 #include "ah.h"
   26 #include "ah_internal.h"
   27 #include "ah_devid.h"
   28 
   29 #include "ar5312/ar5312.h"
   30 #include "ar5312/ar5312reg.h"
   31 #include "ar5312/ar5312phy.h"
   32 
   33 #include "ah_eeprom_v3.h"
   34 
   35 /* Additional Time delay to wait after activiting the Base band */
   36 #define BASE_ACTIVATE_DELAY     100     /* 100 usec */
   37 #define PLL_SETTLE_DELAY        300     /* 300 usec */
   38 
   39 extern int16_t ar5212GetNf(struct ath_hal *, const struct ieee80211_channel *);
   40 extern void ar5212SetRateDurationTable(struct ath_hal *,
   41                 const struct ieee80211_channel *);
   42 extern HAL_BOOL ar5212SetTransmitPower(struct ath_hal *ah,
   43                  const struct ieee80211_channel *chan, uint16_t *rfXpdGain);
   44 extern void ar5212SetDeltaSlope(struct ath_hal *,
   45                  const struct ieee80211_channel *);
   46 extern HAL_BOOL ar5212SetBoardValues(struct ath_hal *,
   47                  const struct ieee80211_channel *);
   48 extern void ar5212SetIFSTiming(struct ath_hal *,
   49                  const struct ieee80211_channel *);
   50 extern HAL_BOOL ar5212IsSpurChannel(struct ath_hal *,
   51                  const struct ieee80211_channel *);
   52 extern HAL_BOOL ar5212ChannelChange(struct ath_hal *,
   53                  const struct ieee80211_channel *);
   54 
   55 static HAL_BOOL ar5312SetResetReg(struct ath_hal *, uint32_t resetMask);
   56 
   57 static int
   58 write_common(struct ath_hal *ah, const HAL_INI_ARRAY *ia,
   59         HAL_BOOL bChannelChange, int writes)
   60 {
   61 #define IS_NO_RESET_TIMER_ADDR(x)                      \
   62     ( (((x) >= AR_BEACON) && ((x) <= AR_CFP_DUR)) || \
   63       (((x) >= AR_SLEEP1) && ((x) <= AR_SLEEP3)))
   64 #define V(r, c) (ia)->data[((r)*(ia)->cols) + (c)]
   65         int i;
   66 
   67         /* Write Common Array Parameters */
   68         for (i = 0; i < ia->rows; i++) {
   69                 uint32_t reg = V(i, 0);
   70                 /* XXX timer/beacon setup registers? */
   71                 /* On channel change, don't reset the PCU registers */
   72                 if (!(bChannelChange && IS_NO_RESET_TIMER_ADDR(reg))) {
   73                         OS_REG_WRITE(ah, reg, V(i, 1));
   74                         DMA_YIELD(writes);
   75                 }
   76         }
   77         return writes;
   78 #undef IS_NO_RESET_TIMER_ADDR
   79 #undef V
   80 }
   81 
   82 /*
   83  * Places the device in and out of reset and then places sane
   84  * values in the registers based on EEPROM config, initialization
   85  * vectors (as determined by the mode), and station configuration
   86  *
   87  * bChannelChange is used to preserve DMA/PCU registers across
   88  * a HW Reset during channel change.
   89  */
   90 HAL_BOOL
   91 ar5312Reset(struct ath_hal *ah, HAL_OPMODE opmode,
   92         struct ieee80211_channel *chan,
   93         HAL_BOOL bChannelChange,
   94         HAL_RESET_TYPE resetType,
   95         HAL_STATUS *status)
   96 {
   97 #define N(a)    (sizeof (a) / sizeof (a[0]))
   98 #define FAIL(_code)     do { ecode = _code; goto bad; } while (0)
   99         struct ath_hal_5212 *ahp = AH5212(ah);
  100         HAL_CHANNEL_INTERNAL *ichan;
  101         const HAL_EEPROM *ee;
  102         uint32_t saveFrameSeqCount, saveDefAntenna;
  103         uint32_t macStaId1, synthDelay, txFrm2TxDStart;
  104         uint16_t rfXpdGain[MAX_NUM_PDGAINS_PER_CHANNEL];
  105         int16_t cckOfdmPwrDelta = 0;
  106         u_int modesIndex, freqIndex;
  107         HAL_STATUS ecode;
  108         int i, regWrites = 0;
  109         uint32_t testReg;
  110         uint32_t saveLedState = 0;
  111 
  112         HALASSERT(ah->ah_magic == AR5212_MAGIC);
  113         ee = AH_PRIVATE(ah)->ah_eeprom;
  114 
  115         OS_MARK(ah, AH_MARK_RESET, bChannelChange);
  116         /*
  117          * Map public channel to private.
  118          */
  119         ichan = ath_hal_checkchannel(ah, chan);
  120         if (ichan == AH_NULL) {
  121                 HALDEBUG(ah, HAL_DEBUG_ANY,
  122                     "%s: invalid channel %u/0x%x; no mapping\n",
  123                     __func__, chan->ic_freq, chan->ic_flags);
  124                 FAIL(HAL_EINVAL);
  125         }
  126         switch (opmode) {
  127         case HAL_M_STA:
  128         case HAL_M_IBSS:
  129         case HAL_M_HOSTAP:
  130         case HAL_M_MONITOR:
  131                 break;
  132         default:
  133                 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid operating mode %u\n",
  134                     __func__, opmode);
  135                 FAIL(HAL_EINVAL);
  136                 break;
  137         }
  138         HALASSERT(ahp->ah_eeversion >= AR_EEPROM_VER3);
  139 
  140         /* Preserve certain DMA hardware registers on a channel change */
  141         if (bChannelChange) {
  142                 /*
  143                  * On Venice, the TSF is almost preserved across a reset;
  144                  * it requires the doubling writes to the RESET_TSF
  145                  * bit in the AR_BEACON register; it also has the quirk
  146                  * of the TSF going back in time on the station (station
  147                  * latches onto the last beacon's tsf during a reset 50%
  148                  * of the times); the latter is not a problem for adhoc
  149                  * stations since as long as the TSF is behind, it will
  150                  * get resynchronized on receiving the next beacon; the
  151                  * TSF going backwards in time could be a problem for the
  152                  * sleep operation (supported on infrastructure stations
  153                  * only) - the best and most general fix for this situation
  154                  * is to resynchronize the various sleep/beacon timers on
  155                  * the receipt of the next beacon i.e. when the TSF itself
  156                  * gets resynchronized to the AP's TSF - power save is
  157                  * needed to be temporarily disabled until that time
  158                  *
  159                  * Need to save the sequence number to restore it after
  160                  * the reset!
  161                  */
  162                 saveFrameSeqCount = OS_REG_READ(ah, AR_D_SEQNUM);
  163         } else
  164                 saveFrameSeqCount = 0;          /* NB: silence compiler */
  165 
  166         /* If the channel change is across the same mode - perform a fast channel change */
  167         if ((IS_2413(ah) || IS_5413(ah))) {
  168                 /*
  169                  * Channel change can only be used when:
  170                  *  -channel change requested - so it's not the initial reset.
  171                  *  -it's not a change to the current channel - often called when switching modes
  172                  *   on a channel
  173                  *  -the modes of the previous and requested channel are the same - some ugly code for XR
  174                  */
  175                 if (bChannelChange &&
  176                     AH_PRIVATE(ah)->ah_curchan != AH_NULL &&
  177                     (chan->ic_freq != AH_PRIVATE(ah)->ah_curchan->ic_freq) &&
  178                     ((chan->ic_flags & IEEE80211_CHAN_ALLTURBO) ==
  179                      (AH_PRIVATE(ah)->ah_curchan->ic_flags & IEEE80211_CHAN_ALLTURBO))) {
  180                         if (ar5212ChannelChange(ah, chan))
  181                                 /* If ChannelChange completed - skip the rest of reset */
  182                                 return AH_TRUE;
  183                 }
  184         }
  185 
  186         /*
  187          * Preserve the antenna on a channel change
  188          */
  189         saveDefAntenna = OS_REG_READ(ah, AR_DEF_ANTENNA);
  190         if (saveDefAntenna == 0)                /* XXX magic constants */
  191                 saveDefAntenna = 1;
  192 
  193         /* Save hardware flag before chip reset clears the register */
  194         macStaId1 = OS_REG_READ(ah, AR_STA_ID1) & 
  195                 (AR_STA_ID1_BASE_RATE_11B | AR_STA_ID1_USE_DEFANT);
  196 
  197         /* Save led state from pci config register */
  198         if (!IS_5315(ah))
  199                 saveLedState = OS_REG_READ(ah, AR5312_PCICFG) &
  200                         (AR_PCICFG_LEDCTL | AR_PCICFG_LEDMODE | AR_PCICFG_LEDBLINK |
  201                          AR_PCICFG_LEDSLOW);
  202 
  203         ar5312RestoreClock(ah, opmode);         /* move to refclk operation */
  204 
  205         /*
  206          * Adjust gain parameters before reset if
  207          * there's an outstanding gain updated.
  208          */
  209         (void) ar5212GetRfgain(ah);
  210 
  211         if (!ar5312ChipReset(ah, chan)) {
  212                 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__);
  213                 FAIL(HAL_EIO);
  214         }
  215 
  216         /* Setup the indices for the next set of register array writes */
  217         if (IEEE80211_IS_CHAN_2GHZ(chan)) {
  218                 freqIndex  = 2;
  219                 modesIndex = IEEE80211_IS_CHAN_108G(chan) ? 5 :
  220                              IEEE80211_IS_CHAN_G(chan) ? 4 : 3;
  221         } else {
  222                 freqIndex  = 1;
  223                 modesIndex = IEEE80211_IS_CHAN_ST(chan) ? 2 : 1;
  224         }
  225 
  226         OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__);
  227 
  228         /* Set correct Baseband to analog shift setting to access analog chips. */
  229         OS_REG_WRITE(ah, AR_PHY(0), 0x00000007);
  230 
  231         regWrites = ath_hal_ini_write(ah, &ahp->ah_ini_modes, modesIndex, 0);
  232         regWrites = write_common(ah, &ahp->ah_ini_common, bChannelChange,
  233                 regWrites);
  234         ahp->ah_rfHal->writeRegs(ah, modesIndex, freqIndex, regWrites);
  235 
  236         OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__);
  237 
  238         if (IEEE80211_IS_CHAN_HALF(chan) || IEEE80211_IS_CHAN_QUARTER(chan))
  239                 ar5212SetIFSTiming(ah, chan);
  240 
  241         /* Overwrite INI values for revised chipsets */
  242         if (AH_PRIVATE(ah)->ah_phyRev >= AR_PHY_CHIP_ID_REV_2) {
  243                 /* ADC_CTL */
  244                 OS_REG_WRITE(ah, AR_PHY_ADC_CTL,
  245                              SM(2, AR_PHY_ADC_CTL_OFF_INBUFGAIN) |
  246                              SM(2, AR_PHY_ADC_CTL_ON_INBUFGAIN) |
  247                              AR_PHY_ADC_CTL_OFF_PWDDAC |
  248                              AR_PHY_ADC_CTL_OFF_PWDADC);
  249                 
  250                 /* TX_PWR_ADJ */
  251                 if (chan->channel == 2484) {
  252                         cckOfdmPwrDelta = SCALE_OC_DELTA(ee->ee_cckOfdmPwrDelta - ee->ee_scaledCh14FilterCckDelta);
  253                 } else {
  254                         cckOfdmPwrDelta = SCALE_OC_DELTA(ee->ee_cckOfdmPwrDelta);
  255                 }
  256                 
  257                 if (IEEE80211_IS_CHAN_G(chan)) {
  258                         OS_REG_WRITE(ah, AR_PHY_TXPWRADJ,
  259                                      SM((ee->ee_cckOfdmPwrDelta*-1), AR_PHY_TXPWRADJ_CCK_GAIN_DELTA) |
  260                                      SM((cckOfdmPwrDelta*-1), AR_PHY_TXPWRADJ_CCK_PCDAC_INDEX));
  261                 } else {
  262                         OS_REG_WRITE(ah, AR_PHY_TXPWRADJ, 0);
  263                 }
  264                 
  265                 /* Add barker RSSI thresh enable as disabled */
  266                 OS_REG_CLR_BIT(ah, AR_PHY_DAG_CTRLCCK,
  267                                AR_PHY_DAG_CTRLCCK_EN_RSSI_THR);
  268                 OS_REG_RMW_FIELD(ah, AR_PHY_DAG_CTRLCCK,
  269                                  AR_PHY_DAG_CTRLCCK_RSSI_THR, 2);
  270                 
  271                 /* Set the mute mask to the correct default */
  272                 OS_REG_WRITE(ah, AR_SEQ_MASK, 0x0000000F);
  273         }
  274 
  275         if (AH_PRIVATE(ah)->ah_phyRev >= AR_PHY_CHIP_ID_REV_3) {
  276                 /* Clear reg to alllow RX_CLEAR line debug */
  277                 OS_REG_WRITE(ah, AR_PHY_BLUETOOTH,  0);
  278         }
  279         if (AH_PRIVATE(ah)->ah_phyRev >= AR_PHY_CHIP_ID_REV_4) {
  280 #ifdef notyet
  281                 /* Enable burst prefetch for the data queues */
  282                 OS_REG_RMW_FIELD(ah, AR_D_FPCTL, ... );
  283                 /* Enable double-buffering */
  284                 OS_REG_CLR_BIT(ah, AR_TXCFG, AR_TXCFG_DBL_BUF_DIS);
  285 #endif
  286         }
  287 
  288         if (IS_5312_2_X(ah)) {
  289                 /* ADC_CTRL */
  290                 OS_REG_WRITE(ah, AR_PHY_SIGMA_DELTA,
  291                              SM(2, AR_PHY_SIGMA_DELTA_ADC_SEL) |
  292                              SM(4, AR_PHY_SIGMA_DELTA_FILT2) |
  293                              SM(0x16, AR_PHY_SIGMA_DELTA_FILT1) |
  294                              SM(0, AR_PHY_SIGMA_DELTA_ADC_CLIP));
  295 
  296                 if (IEEE80211_IS_CHAN_2GHZ(chan))
  297                         OS_REG_RMW_FIELD(ah, AR_PHY_RXGAIN, AR_PHY_RXGAIN_TXRX_RF_MAX, 0x0F);
  298 
  299                 /* CCK Short parameter adjustment in 11B mode */
  300                 if (IEEE80211_IS_CHAN_B(chan))
  301                         OS_REG_RMW_FIELD(ah, AR_PHY_CCK_RXCTRL4, AR_PHY_CCK_RXCTRL4_FREQ_EST_SHORT, 12);
  302 
  303                 /* Set ADC/DAC select values */
  304                 OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x04);
  305 
  306                 /* Increase 11A AGC Settling */
  307                 if (IEEE80211_IS_CHAN_A(chan))
  308                         OS_REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_AGC, 32);
  309         } else {
  310                 /* Set ADC/DAC select values */
  311                 OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0e);
  312         }
  313 
  314         /* Setup the transmit power values. */
  315         if (!ar5212SetTransmitPower(ah, chan, rfXpdGain)) {
  316                 HALDEBUG(ah, HAL_DEBUG_ANY,
  317                     "%s: error init'ing transmit power\n", __func__);
  318                 FAIL(HAL_EIO);
  319         }
  320 
  321         /* Write the analog registers */
  322         if (!ahp->ah_rfHal->setRfRegs(ah, chan, modesIndex, rfXpdGain)) {
  323                 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: ar5212SetRfRegs failed\n",
  324                     __func__);
  325                 FAIL(HAL_EIO);
  326         }
  327 
  328         /* Write delta slope for OFDM enabled modes (A, G, Turbo) */
  329         if (IEEE80211_IS_CHAN_OFDM(chan)) {
  330                 if (IS_5413(ah) ||
  331                    AH_PRIVATE(ah)->ah_eeversion >= AR_EEPROM_VER5_3)
  332                         ar5212SetSpurMitigation(ah, chan);
  333                 ar5212SetDeltaSlope(ah, chan);
  334         }
  335 
  336         /* Setup board specific options for EEPROM version 3 */
  337         if (!ar5212SetBoardValues(ah, chan)) {
  338                 HALDEBUG(ah, HAL_DEBUG_ANY,
  339                     "%s: error setting board options\n", __func__);
  340                 FAIL(HAL_EIO);
  341         }
  342 
  343         /* Restore certain DMA hardware registers on a channel change */
  344         if (bChannelChange)
  345                 OS_REG_WRITE(ah, AR_D_SEQNUM, saveFrameSeqCount);
  346 
  347         OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__);
  348 
  349         OS_REG_WRITE(ah, AR_STA_ID0, LE_READ_4(ahp->ah_macaddr));
  350         OS_REG_WRITE(ah, AR_STA_ID1, LE_READ_2(ahp->ah_macaddr + 4)
  351                 | macStaId1
  352                 | AR_STA_ID1_RTS_USE_DEF
  353                 | ahp->ah_staId1Defaults
  354         );
  355         ar5212SetOperatingMode(ah, opmode);
  356 
  357         /* Set Venice BSSID mask according to current state */
  358         OS_REG_WRITE(ah, AR_BSSMSKL, LE_READ_4(ahp->ah_bssidmask));
  359         OS_REG_WRITE(ah, AR_BSSMSKU, LE_READ_2(ahp->ah_bssidmask + 4));
  360 
  361         /* Restore previous led state */
  362         if (!IS_5315(ah))
  363                 OS_REG_WRITE(ah, AR5312_PCICFG, OS_REG_READ(ah, AR_PCICFG) | saveLedState);
  364 
  365         /* Restore previous antenna */
  366         OS_REG_WRITE(ah, AR_DEF_ANTENNA, saveDefAntenna);
  367 
  368         /* then our BSSID */
  369         OS_REG_WRITE(ah, AR_BSS_ID0, LE_READ_4(ahp->ah_bssid));
  370         OS_REG_WRITE(ah, AR_BSS_ID1, LE_READ_2(ahp->ah_bssid + 4));
  371 
  372         /* Restore bmiss rssi & count thresholds */
  373         OS_REG_WRITE(ah, AR_RSSI_THR, ahp->ah_rssiThr);
  374 
  375         OS_REG_WRITE(ah, AR_ISR, ~0);           /* cleared on write */
  376 
  377         if (!ar5212SetChannel(ah, chan))
  378                 FAIL(HAL_EIO);
  379 
  380         OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__);
  381 
  382         ar5212SetCoverageClass(ah, AH_PRIVATE(ah)->ah_coverageClass, 1);
  383 
  384         ar5212SetRateDurationTable(ah, chan);
  385 
  386         /* Set Tx frame start to tx data start delay */
  387         if (IS_RAD5112_ANY(ah) &&
  388             (IEEE80211_IS_CHAN_HALF(chan) || IEEE80211_IS_CHAN_QUARTER(chan))) {
  389                 txFrm2TxDStart = 
  390                         IEEE80211_IS_CHAN_HALF(chan) ?
  391                                         TX_FRAME_D_START_HALF_RATE:
  392                                         TX_FRAME_D_START_QUARTER_RATE;
  393                 OS_REG_RMW_FIELD(ah, AR_PHY_TX_CTL, 
  394                         AR_PHY_TX_FRAME_TO_TX_DATA_START, txFrm2TxDStart);
  395         }
  396 
  397         /*
  398          * Setup fast diversity.
  399          * Fast diversity can be enabled or disabled via regadd.txt.
  400          * Default is enabled.
  401          * For reference,
  402          *    Disable: reg        val
  403          *             0x00009860 0x00009d18 (if 11a / 11g, else no change)
  404          *             0x00009970 0x192bb514
  405          *             0x0000a208 0xd03e4648
  406          *
  407          *    Enable:  0x00009860 0x00009d10 (if 11a / 11g, else no change)
  408          *             0x00009970 0x192fb514
  409          *             0x0000a208 0xd03e6788
  410          */
  411 
  412         /* XXX Setup pre PHY ENABLE EAR additions */
  413 
  414         /* flush SCAL reg */
  415         if (IS_5312_2_X(ah)) {
  416                 (void) OS_REG_READ(ah, AR_PHY_SLEEP_SCAL);
  417         }
  418 
  419         /*
  420          * Wait for the frequency synth to settle (synth goes on
  421          * via AR_PHY_ACTIVE_EN).  Read the phy active delay register.
  422          * Value is in 100ns increments.
  423          */
  424         synthDelay = OS_REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY;
  425         if (IEEE80211_IS_CHAN_B(chan)) {
  426                 synthDelay = (4 * synthDelay) / 22;
  427         } else {
  428                 synthDelay /= 10;
  429         }
  430 
  431         /* Activate the PHY (includes baseband activate and synthesizer on) */
  432         OS_REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
  433 
  434         /* 
  435          * There is an issue if the AP starts the calibration before
  436          * the base band timeout completes.  This could result in the
  437          * rx_clear false triggering.  As a workaround we add delay an
  438          * extra BASE_ACTIVATE_DELAY usecs to ensure this condition
  439          * does not happen.
  440          */
  441         if (IEEE80211_IS_CHAN_HALF(chan)) {
  442                 OS_DELAY((synthDelay << 1) + BASE_ACTIVATE_DELAY);
  443         } else if (IEEE80211_IS_CHAN_QUARTER(chan)) {
  444                 OS_DELAY((synthDelay << 2) + BASE_ACTIVATE_DELAY);
  445         } else {
  446                 OS_DELAY(synthDelay + BASE_ACTIVATE_DELAY);
  447         }
  448 
  449         /*
  450          * The udelay method is not reliable with notebooks.
  451          * Need to check to see if the baseband is ready
  452          */
  453         testReg = OS_REG_READ(ah, AR_PHY_TESTCTRL);
  454         /* Selects the Tx hold */
  455         OS_REG_WRITE(ah, AR_PHY_TESTCTRL, AR_PHY_TESTCTRL_TXHOLD);
  456         i = 0;
  457         while ((i++ < 20) &&
  458                (OS_REG_READ(ah, 0x9c24) & 0x10)) /* test if baseband not ready */               OS_DELAY(200);
  459         OS_REG_WRITE(ah, AR_PHY_TESTCTRL, testReg);
  460 
  461         /* Calibrate the AGC and start a NF calculation */
  462         OS_REG_WRITE(ah, AR_PHY_AGC_CONTROL,
  463                   OS_REG_READ(ah, AR_PHY_AGC_CONTROL)
  464                 | AR_PHY_AGC_CONTROL_CAL
  465                 | AR_PHY_AGC_CONTROL_NF);
  466 
  467         if (!IEEE80211_IS_CHAN_B(chan) && ahp->ah_bIQCalibration != IQ_CAL_DONE) {
  468                 /* Start IQ calibration w/ 2^(INIT_IQCAL_LOG_COUNT_MAX+1) samples */
  469                 OS_REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4, 
  470                         AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX,
  471                         INIT_IQCAL_LOG_COUNT_MAX);
  472                 OS_REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4,
  473                         AR_PHY_TIMING_CTRL4_DO_IQCAL);
  474                 ahp->ah_bIQCalibration = IQ_CAL_RUNNING;
  475         } else
  476                 ahp->ah_bIQCalibration = IQ_CAL_INACTIVE;
  477 
  478         /* Setup compression registers */
  479         ar5212SetCompRegs(ah);
  480 
  481         /* Set 1:1 QCU to DCU mapping for all queues */
  482         for (i = 0; i < AR_NUM_DCU; i++)
  483                 OS_REG_WRITE(ah, AR_DQCUMASK(i), 1 << i);
  484 
  485         ahp->ah_intrTxqs = 0;
  486         for (i = 0; i < AH_PRIVATE(ah)->ah_caps.halTotalQueues; i++)
  487                 ar5212ResetTxQueue(ah, i);
  488 
  489         /*
  490          * Setup interrupt handling.  Note that ar5212ResetTxQueue
  491          * manipulates the secondary IMR's as queues are enabled
  492          * and disabled.  This is done with RMW ops to insure the
  493          * settings we make here are preserved.
  494          */
  495         ahp->ah_maskReg = AR_IMR_TXOK | AR_IMR_TXERR | AR_IMR_TXURN
  496                         | AR_IMR_RXOK | AR_IMR_RXERR | AR_IMR_RXORN
  497                         | AR_IMR_HIUERR
  498                         ;
  499         if (opmode == HAL_M_HOSTAP)
  500                 ahp->ah_maskReg |= AR_IMR_MIB;
  501         OS_REG_WRITE(ah, AR_IMR, ahp->ah_maskReg);
  502         /* Enable bus errors that are OR'd to set the HIUERR bit */
  503         OS_REG_WRITE(ah, AR_IMR_S2,
  504                 OS_REG_READ(ah, AR_IMR_S2)
  505                 | AR_IMR_S2_MCABT | AR_IMR_S2_SSERR | AR_IMR_S2_DPERR);
  506 
  507         if (AH_PRIVATE(ah)->ah_rfkillEnabled)
  508                 ar5212EnableRfKill(ah);
  509 
  510         if (!ath_hal_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, 0)) {
  511                 HALDEBUG(ah, HAL_DEBUG_ANY,
  512                     "%s: offset calibration failed to complete in 1ms;"
  513                     " noisy environment?\n", __func__);
  514         }
  515 
  516         /*
  517          * Set clocks back to 32kHz if they had been using refClk, then
  518          * use an external 32kHz crystal when sleeping, if one exists.
  519          */
  520         ar5312SetupClock(ah, opmode);
  521 
  522         /*
  523          * Writing to AR_BEACON will start timers. Hence it should
  524          * be the last register to be written. Do not reset tsf, do
  525          * not enable beacons at this point, but preserve other values
  526          * like beaconInterval.
  527          */
  528         OS_REG_WRITE(ah, AR_BEACON,
  529                 (OS_REG_READ(ah, AR_BEACON) &~ (AR_BEACON_EN | AR_BEACON_RESET_TSF)));
  530 
  531         /* XXX Setup post reset EAR additions */
  532 
  533         /*  QoS support */
  534         if (AH_PRIVATE(ah)->ah_macVersion > AR_SREV_VERSION_VENICE ||
  535             (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_VERSION_VENICE &&
  536              AH_PRIVATE(ah)->ah_macRev >= AR_SREV_GRIFFIN_LITE)) {
  537                 OS_REG_WRITE(ah, AR_QOS_CONTROL, 0x100aa);      /* XXX magic */
  538                 OS_REG_WRITE(ah, AR_QOS_SELECT, 0x3210);        /* XXX magic */
  539         }
  540 
  541         /* Turn on NOACK Support for QoS packets */
  542         OS_REG_WRITE(ah, AR_NOACK,
  543                      SM(2, AR_NOACK_2BIT_VALUE) |
  544                      SM(5, AR_NOACK_BIT_OFFSET) |
  545                      SM(0, AR_NOACK_BYTE_OFFSET));
  546 
  547         /* Restore user-specified settings */
  548         if (ahp->ah_miscMode != 0)
  549                 OS_REG_WRITE(ah, AR_MISC_MODE, ahp->ah_miscMode);
  550         if (ahp->ah_slottime != (u_int) -1)
  551                 ar5212SetSlotTime(ah, ahp->ah_slottime);
  552         if (ahp->ah_acktimeout != (u_int) -1)
  553                 ar5212SetAckTimeout(ah, ahp->ah_acktimeout);
  554         if (ahp->ah_ctstimeout != (u_int) -1)
  555                 ar5212SetCTSTimeout(ah, ahp->ah_ctstimeout);
  556         if (ahp->ah_sifstime != (u_int) -1)
  557                 ar5212SetSifsTime(ah, ahp->ah_sifstime);
  558         if (AH_PRIVATE(ah)->ah_diagreg != 0)
  559                 OS_REG_WRITE(ah, AR_DIAG_SW, AH_PRIVATE(ah)->ah_diagreg);
  560 
  561         AH_PRIVATE(ah)->ah_opmode = opmode;     /* record operating mode */
  562 
  563         if (bChannelChange && !IEEE80211_IS_CHAN_DFS(chan)) 
  564                 chan->ic_state &= ~IEEE80211_CHANSTATE_CWINT;
  565 
  566         HALDEBUG(ah, HAL_DEBUG_RESET, "%s: done\n", __func__);
  567 
  568         OS_MARK(ah, AH_MARK_RESET_DONE, 0);
  569 
  570         return AH_TRUE;
  571 bad:
  572         OS_MARK(ah, AH_MARK_RESET_DONE, ecode);
  573         if (status != AH_NULL)
  574                 *status = ecode;
  575         return AH_FALSE;
  576 #undef FAIL
  577 #undef N
  578 }
  579 
  580 /*
  581  * Places the PHY and Radio chips into reset.  A full reset
  582  * must be called to leave this state.  The PCI/MAC/PCU are
  583  * not placed into reset as we must receive interrupt to
  584  * re-enable the hardware.
  585  */
  586 HAL_BOOL
  587 ar5312PhyDisable(struct ath_hal *ah)
  588 {
  589     return ar5312SetResetReg(ah, AR_RC_BB);
  590 }
  591 
  592 /*
  593  * Places all of hardware into reset
  594  */
  595 HAL_BOOL
  596 ar5312Disable(struct ath_hal *ah)
  597 {
  598         if (!ar5312SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE))
  599                 return AH_FALSE;
  600         /*
  601          * Reset the HW - PCI must be reset after the rest of the
  602          * device has been reset.
  603          */
  604         return ar5312SetResetReg(ah, AR_RC_MAC | AR_RC_BB);
  605 }
  606 
  607 /*
  608  * Places the hardware into reset and then pulls it out of reset
  609  *
  610  * TODO: Only write the PLL if we're changing to or from CCK mode
  611  * 
  612  * WARNING: The order of the PLL and mode registers must be correct.
  613  */
  614 HAL_BOOL
  615 ar5312ChipReset(struct ath_hal *ah, const struct ieee80211_channel *chan)
  616 {
  617 
  618         OS_MARK(ah, AH_MARK_CHIPRESET, chan ? chan->ic_freq : 0);
  619 
  620         /*
  621          * Reset the HW 
  622          */
  623         if (!ar5312SetResetReg(ah, AR_RC_MAC | AR_RC_BB)) {
  624                 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: ar5312SetResetReg failed\n",
  625                     __func__);
  626                 return AH_FALSE;
  627         }
  628 
  629         /* Bring out of sleep mode (AGAIN) */
  630         if (!ar5312SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) {
  631                 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: ar5312SetPowerMode failed\n",
  632                     __func__);
  633                 return AH_FALSE;
  634         }
  635 
  636         /* Clear warm reset register */
  637         if (!ar5312SetResetReg(ah, 0)) {
  638                 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: ar5312SetResetReg failed\n",
  639                     __func__);
  640                 return AH_FALSE;
  641         }
  642 
  643         /*
  644          * Perform warm reset before the mode/PLL/turbo registers
  645          * are changed in order to deactivate the radio.  Mode changes
  646          * with an active radio can result in corrupted shifts to the
  647          * radio device.
  648          */
  649 
  650         /*
  651          * Set CCK and Turbo modes correctly.
  652          */
  653         if (chan != AH_NULL) {          /* NB: can be null during attach */
  654                 uint32_t rfMode, phyPLL = 0, curPhyPLL, turbo;
  655 
  656                 if (IS_RAD5112_ANY(ah)) {
  657                         rfMode = AR_PHY_MODE_AR5112;
  658                         if (!IS_5315(ah)) {
  659                                 if (IEEE80211_IS_CHAN_CCK(chan)) {
  660                                         phyPLL = AR_PHY_PLL_CTL_44_5312;
  661                                 } else {
  662                                         if (IEEE80211_IS_CHAN_HALF(chan)) {
  663                                                 phyPLL = AR_PHY_PLL_CTL_40_5312_HALF;
  664                                         } else if (IEEE80211_IS_CHAN_QUARTER(chan)) {
  665                                                 phyPLL = AR_PHY_PLL_CTL_40_5312_QUARTER;
  666                                         } else {
  667                                                 phyPLL = AR_PHY_PLL_CTL_40_5312;
  668                                         }
  669                                 }
  670                         } else {
  671                                 if (IEEE80211_IS_CHAN_CCK(chan))
  672                                         phyPLL = AR_PHY_PLL_CTL_44_5112;
  673                                 else
  674                                         phyPLL = AR_PHY_PLL_CTL_40_5112;
  675                                 if (IEEE80211_IS_CHAN_HALF(chan))
  676                                         phyPLL |= AR_PHY_PLL_CTL_HALF;
  677                                 else if (IEEE80211_IS_CHAN_QUARTER(chan))
  678                                         phyPLL |= AR_PHY_PLL_CTL_QUARTER;
  679                         }
  680                 } else {
  681                         rfMode = AR_PHY_MODE_AR5111;
  682                         if (IEEE80211_IS_CHAN_CCK(chan))
  683                                 phyPLL = AR_PHY_PLL_CTL_44;
  684                         else
  685                                 phyPLL = AR_PHY_PLL_CTL_40;
  686                         if (IEEE80211_IS_CHAN_HALF(chan))
  687                                 phyPLL = AR_PHY_PLL_CTL_HALF;
  688                         else if (IEEE80211_IS_CHAN_QUARTER(chan))
  689                                 phyPLL = AR_PHY_PLL_CTL_QUARTER;
  690                 }
  691                 if (IEEE80211_IS_CHAN_G(chan))
  692                         rfMode |= AR_PHY_MODE_DYNAMIC;
  693                 else if (IEEE80211_IS_CHAN_OFDM(chan))
  694                         rfMode |= AR_PHY_MODE_OFDM;
  695                 else
  696                         rfMode |= AR_PHY_MODE_CCK;
  697                 if (IEEE80211_IS_CHAN_5GHZ(chan))
  698                         rfMode |= AR_PHY_MODE_RF5GHZ;
  699                 else
  700                         rfMode |= AR_PHY_MODE_RF2GHZ;
  701                 turbo = IEEE80211_IS_CHAN_TURBO(chan) ?
  702                         (AR_PHY_FC_TURBO_MODE | AR_PHY_FC_TURBO_SHORT) : 0;
  703                 curPhyPLL = OS_REG_READ(ah, AR_PHY_PLL_CTL);
  704                 /*
  705                  * PLL, Mode, and Turbo values must be written in the correct
  706                  * order to ensure:
  707                  * - The PLL cannot be set to 44 unless the CCK or DYNAMIC
  708                  *   mode bit is set
  709                  * - Turbo cannot be set at the same time as CCK or DYNAMIC
  710                  */
  711                 if (IEEE80211_IS_CHAN_CCK(chan)) {
  712                         OS_REG_WRITE(ah, AR_PHY_TURBO, turbo);
  713                         OS_REG_WRITE(ah, AR_PHY_MODE, rfMode);
  714                         if (curPhyPLL != phyPLL) {
  715                                 OS_REG_WRITE(ah,  AR_PHY_PLL_CTL,  phyPLL);
  716                                 /* Wait for the PLL to settle */
  717                                 OS_DELAY(PLL_SETTLE_DELAY);
  718                         }
  719                 } else {
  720                         if (curPhyPLL != phyPLL) {
  721                                 OS_REG_WRITE(ah,  AR_PHY_PLL_CTL,  phyPLL);
  722                                 /* Wait for the PLL to settle */
  723                                 OS_DELAY(PLL_SETTLE_DELAY);
  724                         }
  725                         OS_REG_WRITE(ah, AR_PHY_TURBO, turbo);
  726                         OS_REG_WRITE(ah, AR_PHY_MODE, rfMode);
  727                 }
  728         }
  729         return AH_TRUE;
  730 }
  731 
  732 /*
  733  * Write the given reset bit mask into the reset register
  734  */
  735 static HAL_BOOL
  736 ar5312SetResetReg(struct ath_hal *ah, uint32_t resetMask)
  737 {
  738         uint32_t mask = resetMask ? resetMask : ~0;
  739         HAL_BOOL rt;
  740 
  741         if ((rt = ar5312MacReset(ah, mask)) == AH_FALSE) {
  742                 return rt;
  743         }
  744         if ((resetMask & AR_RC_MAC) == 0) {
  745                 if (isBigEndian()) {
  746                         /*
  747                          * Set CFG, little-endian for descriptor accesses.
  748                          */
  749 #ifdef AH_NEED_DESC_SWAP
  750                         mask = INIT_CONFIG_STATUS | AR_CFG_SWRD;
  751 #else
  752                         mask = INIT_CONFIG_STATUS |
  753                                 AR_CFG_SWTD | AR_CFG_SWRD;
  754 #endif
  755                         OS_REG_WRITE(ah, AR_CFG, mask);
  756                 } else
  757                         OS_REG_WRITE(ah, AR_CFG, INIT_CONFIG_STATUS);
  758         }
  759         return rt;
  760 }
  761 
  762 /*
  763  * ar5312MacReset resets (and then un-resets) the specified
  764  * wireless components.
  765  * Note: The RCMask cannot be zero on entering from ar5312SetResetReg.
  766  */
  767 
  768 HAL_BOOL
  769 ar5312MacReset(struct ath_hal *ah, unsigned int RCMask)
  770 {
  771         int wlanNum = AR5312_UNIT(ah);
  772         uint32_t resetBB, resetBits, regMask;
  773         uint32_t reg;
  774 
  775         if (RCMask == 0)
  776                 return(AH_FALSE);
  777 #if ( AH_SUPPORT_2316 || AH_SUPPORT_2317 )
  778             if (IS_5315(ah)) {
  779                         switch(wlanNum) {
  780                         case 0:
  781                                 resetBB = AR5315_RC_BB0_CRES | AR5315_RC_WBB0_RES; 
  782                                 /* Warm and cold reset bits for wbb */
  783                                 resetBits = AR5315_RC_WMAC0_RES;
  784                                 break;
  785                         case 1:
  786                                 resetBB = AR5315_RC_BB1_CRES | AR5315_RC_WBB1_RES; 
  787                                 /* Warm and cold reset bits for wbb */
  788                                 resetBits = AR5315_RC_WMAC1_RES;
  789                                 break;
  790                         default:
  791                                 return(AH_FALSE);
  792                         }               
  793                         regMask = ~(resetBB | resetBits);
  794 
  795                         /* read before */
  796                         reg = OS_REG_READ(ah, 
  797                                                           (AR5315_RSTIMER_BASE - ((uint32_t) ah->ah_sh) + AR5315_RESET));
  798 
  799                         if (RCMask == AR_RC_BB) {
  800                                 /* Put baseband in reset */
  801                                 reg |= resetBB;    /* Cold and warm reset the baseband bits */
  802                         } else {
  803                                 /*
  804                                  * Reset the MAC and baseband.  This is a bit different than
  805                                  * the PCI version, but holding in reset causes problems.
  806                                  */
  807                                 reg &= regMask;
  808                                 reg |= (resetBits | resetBB) ;
  809                         }
  810                         OS_REG_WRITE(ah, 
  811                                                  (AR5315_RSTIMER_BASE - ((uint32_t) ah->ah_sh)+AR5315_RESET),
  812                                                  reg);
  813                         /* read after */
  814                         OS_REG_READ(ah, 
  815                                                 (AR5315_RSTIMER_BASE - ((uint32_t) ah->ah_sh) +AR5315_RESET));
  816                         OS_DELAY(100);
  817 
  818                         /* Bring MAC and baseband out of reset */
  819                         reg &= regMask;
  820                         /* read before */
  821                         OS_REG_READ(ah, 
  822                                                 (AR5315_RSTIMER_BASE- ((uint32_t) ah->ah_sh) +AR5315_RESET));
  823                         OS_REG_WRITE(ah, 
  824                                                  (AR5315_RSTIMER_BASE - ((uint32_t) ah->ah_sh)+AR5315_RESET),
  825                                                  reg);
  826                         /* read after */
  827                         OS_REG_READ(ah,
  828                                                 (AR5315_RSTIMER_BASE- ((uint32_t) ah->ah_sh) +AR5315_RESET));
  829 
  830                 } 
  831         else 
  832 #endif
  833                 {
  834                         switch(wlanNum) {
  835                         case 0:
  836                                 resetBB = AR5312_RC_BB0_CRES | AR5312_RC_WBB0_RES;
  837                                 /* Warm and cold reset bits for wbb */
  838                                 resetBits = AR5312_RC_WMAC0_RES;
  839                                 break;
  840                         case 1:
  841                                 resetBB = AR5312_RC_BB1_CRES | AR5312_RC_WBB1_RES;
  842                                 /* Warm and cold reset bits for wbb */
  843                                 resetBits = AR5312_RC_WMAC1_RES;
  844                                 break;
  845                         default:
  846                                 return(AH_FALSE);
  847                         }
  848                         regMask = ~(resetBB | resetBits);
  849 
  850                         /* read before */
  851                         reg = OS_REG_READ(ah,
  852                                                           (AR5312_RSTIMER_BASE - ((uint32_t) ah->ah_sh) + AR5312_RESET));
  853 
  854                         if (RCMask == AR_RC_BB) {
  855                                 /* Put baseband in reset */
  856                                 reg |= resetBB;    /* Cold and warm reset the baseband bits */
  857                         } else {
  858                                 /*
  859                                  * Reset the MAC and baseband.  This is a bit different than
  860                                  * the PCI version, but holding in reset causes problems.
  861                                  */
  862                                 reg &= regMask;
  863                                 reg |= (resetBits | resetBB) ;
  864                         }
  865                         OS_REG_WRITE(ah,
  866                                                  (AR5312_RSTIMER_BASE - ((uint32_t) ah->ah_sh)+AR5312_RESET),
  867                                                  reg);
  868                         /* read after */
  869                         OS_REG_READ(ah,
  870                                                 (AR5312_RSTIMER_BASE - ((uint32_t) ah->ah_sh) +AR5312_RESET));
  871                         OS_DELAY(100);
  872 
  873                         /* Bring MAC and baseband out of reset */
  874                         reg &= regMask;
  875                         /* read before */
  876                         OS_REG_READ(ah,
  877                                                 (AR5312_RSTIMER_BASE- ((uint32_t) ah->ah_sh) +AR5312_RESET));
  878                         OS_REG_WRITE(ah,
  879                                                  (AR5312_RSTIMER_BASE - ((uint32_t) ah->ah_sh)+AR5312_RESET),
  880                                                  reg);
  881                         /* read after */
  882                         OS_REG_READ(ah,
  883                                                 (AR5312_RSTIMER_BASE- ((uint32_t) ah->ah_sh) +AR5312_RESET));
  884                 }
  885         return(AH_TRUE);
  886 }
  887 
  888 #endif /* AH_SUPPORT_AR5312 */

Cache object: aa6519fc46b034006ba13d5f7a762dcf


[ 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.