📄 ar5416_reset.c
字号:
/* * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting * Copyright (c) 2002-2008 Atheros Communications, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * $Id: ar5416_reset.c,v 1.27 2008/11/27 22:30:08 sam Exp $ */#include "opt_ah.h"#include "ah.h"#include "ah_internal.h"#include "ah_devid.h"#include "ah_eeprom_v14.h"#include "ar5416/ar5416.h"#include "ar5416/ar5416reg.h"#include "ar5416/ar5416phy.h"#ifdef AH_SUPPORT_AR9280#include "ar5416/ar9280.h"#endif/* Eeprom versioning macros. Returns true if the version is equal or newer than the ver specified */ #define EEP_MINOR(_ah) \ (AH_PRIVATE(_ah)->ah_eeversion & AR5416_EEP_VER_MINOR_MASK)#define IS_EEP_MINOR_V2(_ah) (EEP_MINOR(_ah) >= AR5416_EEP_MINOR_VER_2)#define IS_EEP_MINOR_V3(_ah) (EEP_MINOR(_ah) >= AR5416_EEP_MINOR_VER_3)/* Additional Time delay to wait after activiting the Base band */#define BASE_ACTIVATE_DELAY 100 /* 100 usec */#define PLL_SETTLE_DELAY 300 /* 300 usec */#define RTC_PLL_SETTLE_DELAY 1000 /* 1 ms */static void ar5416InitDMA(struct ath_hal *ah);static void ar5416InitBB(struct ath_hal *ah, HAL_CHANNEL *chan);static void ar5416InitIMR(struct ath_hal *ah, HAL_OPMODE opmode);static void ar5416InitQoS(struct ath_hal *ah);static void ar5416InitUserSettings(struct ath_hal *ah);static HAL_BOOL ar5416SetTransmitPower(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan, uint16_t *rfXpdGain);#if 0static HAL_BOOL ar5416ChannelChange(struct ath_hal *, HAL_CHANNEL *);#endifstatic void ar5416SetDeltaSlope(struct ath_hal *, HAL_CHANNEL_INTERNAL *);static void ar5416SpurMitigate(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan);#ifdef AH_SUPPORT_AR9280static void ar9280SpurMitigate(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan);#endifstatic HAL_BOOL ar5416SetResetPowerOn(struct ath_hal *ah);static HAL_BOOL ar5416SetReset(struct ath_hal *ah, int type);static void ar5416InitPLL(struct ath_hal *ah, HAL_CHANNEL *chan);static HAL_BOOL ar5416SetBoardValues(struct ath_hal *, HAL_CHANNEL_INTERNAL *);static HAL_BOOL ar5416SetPowerPerRateTable(struct ath_hal *ah, struct ar5416eeprom *pEepData, HAL_CHANNEL_INTERNAL *chan, int16_t *ratesArray, uint16_t cfgCtl, uint16_t AntennaReduction, uint16_t twiceMaxRegulatoryPower, uint16_t powerLimit);static HAL_BOOL ar5416SetPowerCalTable(struct ath_hal *ah, struct ar5416eeprom *pEepData, HAL_CHANNEL_INTERNAL *chan, int16_t *pTxPowerIndexOffset);static uint16_t ar5416GetMaxEdgePower(uint16_t freq, CAL_CTL_EDGES *pRdEdgesPower, HAL_BOOL is2GHz);static void ar5416GetTargetPowers(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan, CAL_TARGET_POWER_HT *powInfo, uint16_t numChannels, CAL_TARGET_POWER_HT *pNewPower, uint16_t numRates, HAL_BOOL isHt40Target);static void ar5416GetTargetPowersLeg(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan, CAL_TARGET_POWER_LEG *powInfo, uint16_t numChannels, CAL_TARGET_POWER_LEG *pNewPower, uint16_t numRates, HAL_BOOL isExtTarget);static int16_t interpolate(uint16_t target, uint16_t srcLeft, uint16_t srcRight, int16_t targetLeft, int16_t targetRight);static void ar5416Set11nRegs(struct ath_hal *ah, HAL_CHANNEL *chan);static void ar5416GetGainBoundariesAndPdadcs(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan, CAL_DATA_PER_FREQ *pRawDataSet, uint8_t * bChans, uint16_t availPiers, uint16_t tPdGainOverlap, int16_t *pMinCalPower, uint16_t * pPdGainBoundaries, uint8_t * pPDADCValues, uint16_t numXpdGains);static HAL_BOOL getLowerUpperIndex(uint8_t target, uint8_t *pList, uint16_t listSize, uint16_t *indexL, uint16_t *indexR);static HAL_BOOL ar5416FillVpdTable(uint8_t pwrMin, uint8_t pwrMax, uint8_t *pPwrList, uint8_t *pVpdList, uint16_t numIntercepts, uint8_t *pRetVpdList);/* * Places the device in and out of reset and then places sane * values in the registers based on EEPROM config, initialization * vectors (as determined by the mode), and station configuration * * bChannelChange is used to preserve DMA/PCU registers across * a HW Reset during channel change. */HAL_BOOLar5416Reset(struct ath_hal *ah, HAL_OPMODE opmode, HAL_CHANNEL *chan, HAL_BOOL bChannelChange, HAL_STATUS *status){#define N(a) (sizeof (a) / sizeof (a[0]))#define FAIL(_code) do { ecode = _code; goto bad; } while (0) struct ath_hal_5212 *ahp = AH5212(ah); HAL_CHANNEL_INTERNAL *ichan; uint32_t softLedCfg; uint32_t saveDefAntenna, saveLedState; uint32_t macStaId1; uint16_t rfXpdGain[2]; u_int modesIndex, freqIndex; HAL_STATUS ecode; int i, regWrites = 0; uint32_t powerVal, rssiThrReg; uint32_t ackTpcPow, ctsTpcPow, chirpTpcPow; OS_MARK(ah, AH_MARK_RESET, bChannelChange);#define IS(_c,_f) (((_c)->channelFlags & _f) || 0) if ((IS(chan, CHANNEL_2GHZ) ^ IS(chan, CHANNEL_5GHZ)) == 0) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel %u/0x%x; not marked as 2GHz or 5GHz\n", __func__, chan->channel, chan->channelFlags); FAIL(HAL_EINVAL); } if ((IS(chan, CHANNEL_OFDM) ^ IS(chan, CHANNEL_CCK)) == 0) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel %u/0x%x; not marked as OFDM or CCK\n", __func__, chan->channel, chan->channelFlags); FAIL(HAL_EINVAL); }#undef IS /* Bring out of sleep mode */ if (!ar5416SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip did not wakeup\n", __func__); FAIL(HAL_EIO); } /* * Map public channel to private. */ ichan = ath_hal_checkchannel(ah, chan); if (ichan == AH_NULL) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel %u/0x%x; no mapping\n", __func__, chan->channel, chan->channelFlags); FAIL(HAL_EINVAL); } else { HALDEBUG(ah, HAL_DEBUG_RESET, "%s: Ch=%u Max=%d Min=%d\n",__func__, ichan->channel, ichan->maxTxPower, ichan->minTxPower); } switch (opmode) { case HAL_M_STA: case HAL_M_IBSS: case HAL_M_HOSTAP: case HAL_M_MONITOR: break; default: HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid operating mode %u\n", __func__, opmode); FAIL(HAL_EINVAL); break; } HALASSERT(AH_PRIVATE(ah)->ah_eeversion >= AR_EEPROM_VER14_1); /* XXX Turn on fast channel change for 5416 */ /* * Preserve the bmiss rssi threshold and count threshold * across resets */ rssiThrReg = OS_REG_READ(ah, AR_RSSI_THR); /* If reg is zero, first time thru set to default val */ if (rssiThrReg == 0) rssiThrReg = INIT_RSSI_THR; /* * Preserve the antenna on a channel change */ saveDefAntenna = OS_REG_READ(ah, AR_DEF_ANTENNA); if (saveDefAntenna == 0) /* XXX magic constants */ saveDefAntenna = 1; /* Save hardware flag before chip reset clears the register */ macStaId1 = OS_REG_READ(ah, AR_STA_ID1) & (AR_STA_ID1_BASE_RATE_11B | AR_STA_ID1_USE_DEFANT); /* Save led state from pci config register */ saveLedState = OS_REG_READ(ah, AR_MAC_LED) & (AR_MAC_LED_ASSOC | AR_MAC_LED_MODE | AR_MAC_LED_BLINK_THRESH_SEL | AR_MAC_LED_BLINK_SLOW); softLedCfg = OS_REG_READ(ah, AR_GPIO_INTR_OUT); /* * Adjust gain parameters before reset if * there's an outstanding gain updated. */ (void) ar5416GetRfgain(ah); if (!ar5416ChipReset(ah, chan)) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__); FAIL(HAL_EIO); } /* Restore bmiss rssi & count thresholds */ OS_REG_WRITE(ah, AR_RSSI_THR, rssiThrReg); /* Setup the indices for the next set of register array writes */ /* XXX Ignore 11n dynamic mode on the AR5416 for the moment */ switch (chan->channelFlags & CHANNEL_ALL) { case CHANNEL_A: case CHANNEL_A_HT20: modesIndex = 1; freqIndex = 1; break; case CHANNEL_T: case CHANNEL_A_HT40PLUS: case CHANNEL_A_HT40MINUS: modesIndex = 2; freqIndex = 1; break; case CHANNEL_PUREG: case CHANNEL_G_HT20: case CHANNEL_B: /* treat as channel G , no B mode suport in owl */ modesIndex = 4; freqIndex = 2; break; case CHANNEL_G_HT40PLUS: case CHANNEL_G_HT40MINUS: modesIndex = 3; freqIndex = 2; break; case CHANNEL_108G: modesIndex = 5; freqIndex = 2; break; default: HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n", __func__, chan->channelFlags); FAIL(HAL_EINVAL); } OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__); /* Set correct Baseband to analog shift setting to access analog chips. */ OS_REG_WRITE(ah, AR_PHY(0), 0x00000007); /* * Write addac shifts */ OS_REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_EXTERNAL_RADIO);#if 0 /* NB: only required for Sowl */ ar5416EepromSetAddac(ah, ichan);#endif regWrites = ath_hal_ini_write(ah, &AH5416(ah)->ah_ini_addac, 1, regWrites); OS_REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_INTERNAL_ADDAC); /* XXX Merlin ini fixups */ /* XXX Merlin 100us delay for shift registers */ regWrites = ath_hal_ini_write(ah, &ahp->ah_ini_modes, modesIndex, regWrites);#ifdef AH_SUPPORT_AR9280 if (AR_SREV_MERLIN_20_OR_LATER(ah)) { regWrites = ath_hal_ini_write(ah, &AH9280(ah)->ah_ini_rxgain, modesIndex, regWrites); regWrites = ath_hal_ini_write(ah, &AH9280(ah)->ah_ini_txgain, modesIndex, regWrites); }#endif /* XXX Merlin 100us delay for shift registers */ regWrites = ath_hal_ini_write(ah, &ahp->ah_ini_common, 1, regWrites); /* Setup 11n MAC/Phy mode registers */ ar5416Set11nRegs(ah,chan); /* XXX updated regWrites? */ ahp->ah_rfHal->writeRegs(ah, modesIndex, freqIndex, regWrites);#ifdef AH_SUPPORT_AR9280 if (AR_SREV_MERLIN_20(ah) && IS_5GHZ_FAST_CLOCK_EN(ah, chan)) { /* 5GHz channels w/ Fast Clock use different modal values */ regWrites = ath_hal_ini_write(ah, &AH9280(ah)->ah_ini_xmodes, modesIndex, regWrites); }#endif OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__); HALDEBUG(ah, HAL_DEBUG_RESET, ">>>2 %s: AR_PHY_DAG_CTRLCCK=0x%x\n", __func__, OS_REG_READ(ah,AR_PHY_DAG_CTRLCCK)); HALDEBUG(ah, HAL_DEBUG_RESET, ">>>2 %s: AR_PHY_ADC_CTL=0x%x\n", __func__, OS_REG_READ(ah,AR_PHY_ADC_CTL)); /* Set the mute mask to the correct default */ if (AH_PRIVATE(ah)->ah_phyRev >= AR_PHY_CHIP_ID_REV_2) OS_REG_WRITE(ah, AR_SEQ_MASK, 0x0000000F); if (AH_PRIVATE(ah)->ah_phyRev >= AR_PHY_CHIP_ID_REV_3) { /* Clear reg to alllow RX_CLEAR line debug */ OS_REG_WRITE(ah, AR_PHY_BLUETOOTH, 0); } if (AH_PRIVATE(ah)->ah_phyRev >= AR_PHY_CHIP_ID_REV_4) {#ifdef notyet /* Enable burst prefetch for the data queues */ OS_REG_RMW_FIELD(ah, AR_D_FPCTL, ... ); /* Enable double-buffering */ OS_REG_CLR_BIT(ah, AR_TXCFG, AR_TXCFG_DBL_BUF_DIS);#endif } /* Set ADC/DAC select values */ OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0e); if (AH5416(ah)->ah_rx_chainmask == 0x5 || AH5416(ah)->ah_tx_chainmask == 0x5) OS_REG_WRITE(ah, AR_PHY_ANALOG_SWAP, AR_PHY_SWAP_ALT_CHAIN); /* Setup Chain Masks */ OS_REG_WRITE(ah, AR_PHY_RX_CHAINMASK, AH5416(ah)->ah_rx_chainmask); OS_REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, AH5416(ah)->ah_rx_chainmask); OS_REG_WRITE(ah, AR_SELFGEN_MASK, AH5416(ah)->ah_tx_chainmask); /* Setup the transmit power values. */ if (!ar5416SetTransmitPower(ah, ichan, rfXpdGain)) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: error init'ing transmit power\n", __func__); FAIL(HAL_EIO); } /* Write the analog registers */ if (!ahp->ah_rfHal->setRfRegs(ah, ichan, freqIndex, rfXpdGain)) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: ar5212SetRfRegs failed\n", __func__); FAIL(HAL_EIO); } /* Write delta slope for OFDM enabled modes (A, G, Turbo) */ if (IS_CHAN_OFDM(chan)|| IS_CHAN_HT(chan)) ar5416SetDeltaSlope(ah, ichan);#ifdef AH_SUPPORT_AR9280 if (AR_SREV_MERLIN_10_OR_LATER(ah)) ar9280SpurMitigate(ah, ichan); else#endif ar5416SpurMitigate(ah, ichan); /* Setup board specific options for EEPROM version 3 */ if (!ar5416SetBoardValues(ah, ichan)) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: error setting board options\n", __func__); FAIL(HAL_EIO); } OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__); OS_REG_WRITE(ah, AR_STA_ID0, LE_READ_4(ahp->ah_macaddr)); OS_REG_WRITE(ah, AR_STA_ID1, LE_READ_2(ahp->ah_macaddr + 4) | macStaId1 | AR_STA_ID1_RTS_USE_DEF | ahp->ah_staId1Defaults ); ar5212SetOperatingMode(ah, opmode); /* Set Venice BSSID mask according to current state */ OS_REG_WRITE(ah, AR_BSSMSKL, LE_READ_4(ahp->ah_bssidmask)); OS_REG_WRITE(ah, AR_BSSMSKU, LE_READ_2(ahp->ah_bssidmask + 4)); /* Restore previous led state */ OS_REG_WRITE(ah, AR_MAC_LED, OS_REG_READ(ah, AR_MAC_LED) | saveLedState); /* Restore soft Led state to GPIO */ OS_REG_WRITE(ah, AR_GPIO_INTR_OUT, softLedCfg); /* Restore previous antenna */ OS_REG_WRITE(ah, AR_DEF_ANTENNA, saveDefAntenna); /* then our BSSID */ OS_REG_WRITE(ah, AR_BSS_ID0, LE_READ_4(ahp->ah_bssid)); OS_REG_WRITE(ah, AR_BSS_ID1, LE_READ_2(ahp->ah_bssid + 4)); /* Restore bmiss rssi & count thresholds */ OS_REG_WRITE(ah, AR_RSSI_THR, ahp->ah_rssiThr); OS_REG_WRITE(ah, AR_ISR, ~0); /* cleared on write */ if (!ar5212SetChannel(ah, ichan))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -