⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ar5212_reset.c.svn-base

📁 最新之atheros芯片driver source code, 基于linux操作系统,內含atheros芯片HAL全部代码
💻 SVN-BASE
📖 第 1 页 / 共 5 页
字号:
/* * 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: ar5212_reset.c,v 1.20 2008/11/27 22:30:00 sam Exp $ */#include "opt_ah.h"#include "ah.h"#include "ah_internal.h"#include "ah_devid.h"#include "ar5212/ar5212.h"#include "ar5212/ar5212reg.h"#include "ar5212/ar5212phy.h"#include "ah_eeprom_v3.h"/* Additional Time delay to wait after activiting the Base band */#define BASE_ACTIVATE_DELAY	100	/* 100 usec */#define PLL_SETTLE_DELAY	300	/* 300 usec */static HAL_BOOL ar5212SetResetReg(struct ath_hal *, uint32_t resetMask);/* NB: public for 5312 use */HAL_BOOL	ar5212IsSpurChannel(struct ath_hal *, HAL_CHANNEL *);HAL_BOOL	ar5212ChannelChange(struct ath_hal *, HAL_CHANNEL *);int16_t		ar5212GetNf(struct ath_hal *, HAL_CHANNEL_INTERNAL *);HAL_BOOL	ar5212SetBoardValues(struct ath_hal *, HAL_CHANNEL_INTERNAL *);void		ar5212SetDeltaSlope(struct ath_hal *, HAL_CHANNEL *);HAL_BOOL	ar5212SetTransmitPower(struct ath_hal *ah,		HAL_CHANNEL_INTERNAL *chan, uint16_t *rfXpdGain);static HAL_BOOL ar5212SetRateTable(struct ath_hal *, 		   HAL_CHANNEL *, int16_t tpcScaleReduction, int16_t powerLimit,		   HAL_BOOL commit, int16_t *minPower, int16_t *maxPower);static void ar5212CorrectGainDelta(struct ath_hal *, int twiceOfdmCckDelta);static void ar5212GetTargetPowers(struct ath_hal *, HAL_CHANNEL *,		   const TRGT_POWER_INFO *pPowerInfo, uint16_t numChannels,		   TRGT_POWER_INFO *pNewPower);static uint16_t ar5212GetMaxEdgePower(uint16_t channel,		   const RD_EDGES_POWER  *pRdEdgesPower);void		ar5212SetRateDurationTable(struct ath_hal *, HAL_CHANNEL *);void		ar5212SetIFSTiming(struct ath_hal *, HAL_CHANNEL *);/* NB: public for RF backend use */void		ar5212GetLowerUpperValues(uint16_t value,		   uint16_t *pList, uint16_t listSize,		   uint16_t *pLowerValue, uint16_t *pUpperValue);void		ar5212ModifyRfBuffer(uint32_t *rfBuf, uint32_t reg32,		   uint32_t numBits, uint32_t firstBit, uint32_t column);static intwrite_common(struct ath_hal *ah, const HAL_INI_ARRAY *ia,	HAL_BOOL bChannelChange, int writes){#define IS_NO_RESET_TIMER_ADDR(x)                      \    ( (((x) >= AR_BEACON) && ((x) <= AR_CFP_DUR)) || \      (((x) >= AR_SLEEP1) && ((x) <= AR_SLEEP3)))#define	V(r, c)	(ia)->data[((r)*(ia)->cols) + (c)]	int r;	/* Write Common Array Parameters */	for (r = 0; r < ia->rows; r++) {		uint32_t reg = V(r, 0);		/* XXX timer/beacon setup registers? */		/* On channel change, don't reset the PCU registers */		if (!(bChannelChange && IS_NO_RESET_TIMER_ADDR(reg))) {			OS_REG_WRITE(ah, reg, V(r, 1));			DMA_YIELD(writes);		}	}	return writes;#undef IS_NO_RESET_TIMER_ADDR#undef V}#define IS_DISABLE_FAST_ADC_CHAN(x) (((x) == 2462) || ((x) == 2467))/* * 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_BOOLar5212Reset(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 = AH_NULL;	const HAL_EEPROM *ee;	uint32_t softLedCfg, softLedState;	uint32_t saveFrameSeqCount, saveDefAntenna, saveLedState;	uint32_t macStaId1, synthDelay, txFrm2TxDStart;	uint16_t rfXpdGain[MAX_NUM_PDGAINS_PER_CHANNEL];	int16_t cckOfdmPwrDelta = 0;	u_int modesIndex, freqIndex;	HAL_STATUS ecode;	int i, regWrites;	uint32_t testReg, powerVal;	int8_t twiceAntennaGain, twiceAntennaReduction;	uint32_t ackTpcPow, ctsTpcPow, chirpTpcPow;	HAL_BOOL isBmode = AH_FALSE;	HAL_BOOL ichan_isBmode = AH_FALSE;	HALASSERT(ah->ah_magic == AR5212_MAGIC);	ee = AH_PRIVATE(ah)->ah_eeprom;	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 (!ar5212SetPowerMode(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);	}	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_VER3);	SAVE_CCK(ah, ichan, ichan_isBmode);	SAVE_CCK(ah, chan, isBmode);	/* Preserve certain DMA hardware registers on a channel change */	if (bChannelChange) {		/*		 * On Venice, the TSF is almost preserved across a reset;		 * it requires doubling writes to the RESET_TSF		 * bit in the AR_BEACON register; it also has the quirk		 * of the TSF going back in time on the station (station		 * latches onto the last beacon's tsf during a reset 50%		 * of the times); the latter is not a problem for adhoc		 * stations since as long as the TSF is behind, it will		 * get resynchronized on receiving the next beacon; the		 * TSF going backwards in time could be a problem for the		 * sleep operation (supported on infrastructure stations		 * only) - the best and most general fix for this situation		 * is to resynchronize the various sleep/beacon timers on		 * the receipt of the next beacon i.e. when the TSF itself		 * gets resynchronized to the AP's TSF - power save is		 * needed to be temporarily disabled until that time		 *		 * Need to save the sequence number to restore it after		 * the reset!		 */		saveFrameSeqCount = OS_REG_READ(ah, AR_D_SEQNUM);	} else		saveFrameSeqCount = 0;		/* NB: silence compiler */#if 0	/*	 * XXX disable for now; this appears to sometimes cause OFDM	 * XXX timing error floods when ani is enabled and bg scanning	 * XXX kicks in	 */	/* If the channel change is across the same mode - perform a fast channel change */	if (IS_2413(ah) || IS_5413(ah)) {		/*		 * Fast channel change can only be used when:		 *  -channel change requested - so it's not the initial reset.		 *  -it's not a change to the current channel -		 *	often called when switching modes on a channel		 *  -the modes of the previous and requested channel are the		 *	same		 * XXX opmode shouldn't change either?		 */		if (bChannelChange &&		    (AH_PRIVATE(ah)->ah_curchan != AH_NULL) &&		    (chan->channel != AH_PRIVATE(ah)->ah_curchan->channel) &&		    ((chan->channelFlags & CHANNEL_ALL) ==		     (AH_PRIVATE(ah)->ah_curchan->channelFlags & CHANNEL_ALL))) {			if (ar5212ChannelChange(ah, chan)) {				/* If ChannelChange completed - skip the rest of reset */				/* XXX ani? */				return AH_TRUE;			}		}	}#endif	/*	 * 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_PCICFG) &		(AR_PCICFG_LEDCTL | AR_PCICFG_LEDMODE | AR_PCICFG_LEDBLINK |		 AR_PCICFG_LEDSLOW);	softLedCfg = OS_REG_READ(ah, AR_GPIOCR);	softLedState = OS_REG_READ(ah, AR_GPIODO);	ar5212RestoreClock(ah, opmode);		/* move to refclk operation */	/*	 * Adjust gain parameters before reset if	 * there's an outstanding gain updated.	 */	(void) ar5212GetRfgain(ah);	if (!ar5212ChipReset(ah, chan)) {		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__);		FAIL(HAL_EIO);	}	/* Setup the indices for the next set of register array writes */	switch (chan->channelFlags & CHANNEL_ALL) {	case CHANNEL_A:		modesIndex = 1;		freqIndex  = 1;		break;	case CHANNEL_T:		modesIndex = 2;		freqIndex  = 1;		break;	case CHANNEL_B:		modesIndex = 3;		freqIndex  = 2;		break;	case CHANNEL_PUREG:		modesIndex = 4;		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);	regWrites = ath_hal_ini_write(ah, &ahp->ah_ini_modes, modesIndex, 0);	regWrites = write_common(ah, &ahp->ah_ini_common, bChannelChange,		regWrites);	ahp->ah_rfHal->writeRegs(ah, modesIndex, freqIndex, regWrites);	OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__);	if (IS_CHAN_HALF_RATE(chan) || IS_CHAN_QUARTER_RATE(chan)) {		ar5212SetIFSTiming(ah, chan);		if (IS_5413(ah)) {			/*			 * Force window_length for 1/2 and 1/4 rate channels,			 * the ini file sets this to zero otherwise.			 */			OS_REG_RMW_FIELD(ah, AR_PHY_FRAME_CTL,				AR_PHY_FRAME_CTL_WINLEN, 3);		}	}	/* Overwrite INI values for revised chipsets */	if (AH_PRIVATE(ah)->ah_phyRev >= AR_PHY_CHIP_ID_REV_2) {		/* ADC_CTL */		OS_REG_WRITE(ah, AR_PHY_ADC_CTL,			SM(2, AR_PHY_ADC_CTL_OFF_INBUFGAIN) |			SM(2, AR_PHY_ADC_CTL_ON_INBUFGAIN) |			AR_PHY_ADC_CTL_OFF_PWDDAC |			AR_PHY_ADC_CTL_OFF_PWDADC);		/* TX_PWR_ADJ */		if (chan->channel == 2484) {			cckOfdmPwrDelta = SCALE_OC_DELTA(			    ee->ee_cckOfdmPwrDelta -			    ee->ee_scaledCh14FilterCckDelta);		} else {			cckOfdmPwrDelta = SCALE_OC_DELTA(			    ee->ee_cckOfdmPwrDelta);		}		if (IS_CHAN_G(chan)) {		    OS_REG_WRITE(ah, AR_PHY_TXPWRADJ,			SM((ee->ee_cckOfdmPwrDelta*-1),			    AR_PHY_TXPWRADJ_CCK_GAIN_DELTA) |			SM((cckOfdmPwrDelta*-1),			    AR_PHY_TXPWRADJ_CCK_PCDAC_INDEX));		} else {			OS_REG_WRITE(ah, AR_PHY_TXPWRADJ, 0);		}		/* Add barker RSSI thresh enable as disabled */		OS_REG_CLR_BIT(ah, AR_PHY_DAG_CTRLCCK,			AR_PHY_DAG_CTRLCCK_EN_RSSI_THR);		OS_REG_RMW_FIELD(ah, AR_PHY_DAG_CTRLCCK,			AR_PHY_DAG_CTRLCCK_RSSI_THR, 2);		/* Set the mute mask to the correct default */		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 (IS_5413(ah) || IS_2417(ah)) {		uint32_t newReg=1;		if (IS_DISABLE_FAST_ADC_CHAN(chan->channel))			newReg = 0;		/* As it's a clock changing register, only write when the value needs to be changed */		if (OS_REG_READ(ah, AR_PHY_FAST_ADC) != newReg)			OS_REG_WRITE(ah, AR_PHY_FAST_ADC, newReg);	}	/* Setup the transmit power values. */	if (!ar5212SetTransmitPower(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, modesIndex, 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)) {		if ((IS_5413(ah) || (AH_PRIVATE(ah)->ah_eeversion >= AR_EEPROM_VER5_3)) &&		    (!IS_CHAN_B(chan)))			ar5212SetSpurMitigation(ah, ichan);		ar5212SetDeltaSlope(ah, chan);	}	/* Setup board specific options for EEPROM version 3 */	if (!ar5212SetBoardValues(ah, ichan)) {		HALDEBUG(ah, HAL_DEBUG_ANY,		    "%s: error setting board options\n", __func__);		FAIL(HAL_EIO);	}	/* Restore certain DMA hardware registers on a channel change */	if (bChannelChange)		OS_REG_WRITE(ah, AR_D_SEQNUM, saveFrameSeqCount);	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));

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -