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

📄 ar5211_reset.c

📁 Atheros wifi driver source code
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting * Copyright (c) 2002-2005 Atheros Communications, Inc. * All rights reserved. * * $Id: ar5211_reset.c,v 1.1.1.1 2006/09/12 03:45:24 steven Exp $ */#include "opt_ah.h"#ifdef AH_SUPPORT_AR5211/* * Chips specific device attachment and device info collection * Connects Init Reg Vectors, EEPROM Data, and device Functions. */#include "ah.h"#include "ah_internal.h"#include "ah_devid.h"#include "ar5211/ar5211.h"#include "ar5211/ar5211reg.h"#include "ar5211/ar5211phy.h"/* Add static register initialization vectors */#include "ar5211/boss.ini"/* * Structure to hold 11b tuning information for Beanie/Sombrero * 16 MHz mode, divider ratio = 198 = NP+S. N=16, S=4 or 6, P=12 */typedef struct {	u_int32_t	refClkSel;	/* reference clock, 1 for 16 MHz */	u_int32_t	channelSelect;	/* P[7:4]S[3:0] bits */	u_int16_t	channel5111;	/* 11a channel for 5111 */} CHAN_INFO_2GHZ;#define CI_2GHZ_INDEX_CORRECTION 19const static CHAN_INFO_2GHZ chan2GHzData[] = {	{ 1, 0x46, 96  },	/* 2312 -19 */	{ 1, 0x46, 97  },	/* 2317 -18 */	{ 1, 0x46, 98  },	/* 2322 -17 */	{ 1, 0x46, 99  },	/* 2327 -16 */	{ 1, 0x46, 100 },	/* 2332 -15 */	{ 1, 0x46, 101 },	/* 2337 -14 */	{ 1, 0x46, 102 },	/* 2342 -13 */	{ 1, 0x46, 103 },	/* 2347 -12 */	{ 1, 0x46, 104 },	/* 2352 -11 */	{ 1, 0x46, 105 },	/* 2357 -10 */	{ 1, 0x46, 106 },	/* 2362  -9 */	{ 1, 0x46, 107 },	/* 2367  -8 */	{ 1, 0x46, 108 },	/* 2372  -7 */	/* index -6 to 0 are pad to make this a nolookup table */	{ 1, 0x46, 116 },	/*       -6 */	{ 1, 0x46, 116 },	/*       -5 */	{ 1, 0x46, 116 },	/*       -4 */	{ 1, 0x46, 116 },	/*       -3 */	{ 1, 0x46, 116 },	/*       -2 */	{ 1, 0x46, 116 },	/*       -1 */	{ 1, 0x46, 116 },	/*        0 */	{ 1, 0x46, 116 },	/* 2412   1 */	{ 1, 0x46, 117 },	/* 2417   2 */	{ 1, 0x46, 118 },	/* 2422   3 */	{ 1, 0x46, 119 },	/* 2427   4 */	{ 1, 0x46, 120 },	/* 2432   5 */	{ 1, 0x46, 121 },	/* 2437   6 */	{ 1, 0x46, 122 },	/* 2442   7 */	{ 1, 0x46, 123 },	/* 2447   8 */	{ 1, 0x46, 124 },	/* 2452   9 */	{ 1, 0x46, 125 },	/* 2457  10 */	{ 1, 0x46, 126 },	/* 2462  11 */	{ 1, 0x46, 127 },	/* 2467  12 */	{ 1, 0x46, 128 },	/* 2472  13 */	{ 1, 0x44, 124 },	/* 2484  14 */	{ 1, 0x46, 136 },	/* 2512  15 */	{ 1, 0x46, 140 },	/* 2532  16 */	{ 1, 0x46, 144 },	/* 2552  17 */	{ 1, 0x46, 148 },	/* 2572  18 */	{ 1, 0x46, 152 },	/* 2592  19 */	{ 1, 0x46, 156 },	/* 2612  20 */	{ 1, 0x46, 160 },	/* 2632  21 */	{ 1, 0x46, 164 },	/* 2652  22 */	{ 1, 0x46, 168 },	/* 2672  23 */	{ 1, 0x46, 172 },	/* 2692  24 */	{ 1, 0x46, 176 },	/* 2712  25 */	{ 1, 0x46, 180 } 	/* 2732  26 */};/* Power timeouts in usec to wait for chip to wake-up. */#define POWER_UP_TIME	2000#define	DELAY_PLL_SETTLE	300		/* 300 us */#define	DELAY_BASE_ACTIVATE	100		/* 100 us */#define NUM_RATES	8static HAL_BOOL ar5211SetResetReg(struct ath_hal *ah, u_int32_t resetMask);static HAL_BOOL ar5211SetChannel(struct ath_hal *,  HAL_CHANNEL_INTERNAL *);static int16_t ar5211RunNoiseFloor(struct ath_hal *,		u_int8_t runTime, int16_t startingNF);static HAL_BOOL ar5211IsNfGood(struct ath_hal *, HAL_CHANNEL *chan);static HAL_BOOL ar5211SetRf6and7(struct ath_hal *, HAL_CHANNEL *chan);static HAL_BOOL ar5211SetBoardValues(struct ath_hal *, HAL_CHANNEL *chan);static void ar5211SetPowerTable(struct ath_hal *,		PCDACS_EEPROM *pSrcStruct, u_int16_t channel);static void ar5211SetRateTable(struct ath_hal *,		RD_EDGES_POWER *pRdEdgesPower, TRGT_POWER_INFO *pPowerInfo,		u_int16_t numChannels, HAL_CHANNEL *chan);static u_int16_t ar5211GetScaledPower(u_int16_t channel, u_int16_t pcdacValue,		PCDACS_EEPROM *pSrcStruct);static HAL_BOOL ar5211FindValueInList(u_int16_t channel, u_int16_t pcdacValue,		PCDACS_EEPROM *pSrcStruct, u_int16_t *powerValue);static u_int16_t ar5211GetInterpolatedValue(u_int16_t target,		u_int16_t srcLeft, u_int16_t srcRight,		u_int16_t targetLeft, u_int16_t targetRight, HAL_BOOL scaleUp);static void ar5211GetLowerUpperValues(u_int16_t value,		u_int16_t *pList, u_int16_t listSize,		u_int16_t *pLowerValue, u_int16_t *pUpperValue);static void ar5211GetLowerUpperPcdacs(u_int16_t pcdac,		u_int16_t channel, PCDACS_EEPROM *pSrcStruct,		u_int16_t *pLowerPcdac, u_int16_t *pUpperPcdac);static void ar5211SetRfgain(struct ath_hal *, const GAIN_VALUES *);;static void ar5211RequestRfgain(struct ath_hal *);static HAL_BOOL ar5211InvalidGainReadback(struct ath_hal *, GAIN_VALUES *);static HAL_BOOL ar5211IsGainAdjustNeeded(struct ath_hal *, const GAIN_VALUES *);static int32_t ar5211AdjustGain(struct ath_hal *, GAIN_VALUES *);/* * 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_BOOLar5211Reset(struct ath_hal *ah, HAL_OPMODE opmode,	HAL_CHANNEL *chan, HAL_BOOL bChannelChange, HAL_STATUS *status){u_int32_t softLedCfg, softLedState;#define	N(a)	(sizeof (a) /sizeof (a[0]))#define	FAIL(_code)	do { ecode = _code; goto bad; } while (0)	struct ath_hal_5211 *ahp = AH5211(ah);	HAL_CHANNEL_INTERNAL *ichan;	u_int32_t i, ledstate;	HAL_STATUS ecode;	int q;	u_int32_t		data, synthDelay;	u_int32_t		macStaId1;    	u_int16_t		modesIndex = 0, freqIndex = 0;	u_int32_t		saveFrameSeqCount[AR_NUM_DCU];	u_int32_t		saveTsfLow = 0, saveTsfHigh = 0;	u_int32_t		saveDefAntenna;	HALDEBUG(ah, "%s: opmode %u channel %u/0x%x %s channel\n",		__func__, opmode, chan->channel, chan->channelFlags,		bChannelChange ? "change" : "same");	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, "%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, "%s: invalid channel %u/0x%x; not marked as "			"OFDM or CCK\n", __func__,			chan->channel, chan->channelFlags);		FAIL(HAL_EINVAL);	}#undef IS	/*	 * Map public channel to private.	 */	ichan = ath_hal_checkchannel(ah, chan);	if (ichan == AH_NULL) {		HALDEBUG(ah, "%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, "%s: invalid operating mode %u\n",			__func__, opmode);		FAIL(HAL_EINVAL);		break;	}	HALASSERT(ahp->ah_eeversion >= AR_EEPROM_VER3);	/* Preserve certain DMA hardware registers on a channel change */	if (bChannelChange) {		/*		 * AR5211 WAR		 * Need to save/restore the TSF because of a hardware bug		 * that accelerates the TSF during a chip reset.		 *		 * We could use system timer routines to more		 * accurately restore the TSF, but		 * 1. Timer routines on certain platforms are		 *	not accurate enough (e.g. 1 ms resolution).		 * 2. It would still not be accurate.		 *		 * The most important aspect of this workaround,		 * is that, after reset, the TSF is behind		 * other STAs TSFs (see bug 4127).  This will		 * allow the STA to properly resynchronize its		 * TSF in adhoc mode.		 */		saveTsfLow  = OS_REG_READ(ah, AR_TSF_L32);		saveTsfHigh = OS_REG_READ(ah, AR_TSF_U32);		/* Read frame sequence count */		if (AH_PRIVATE(ah)->ah_macVersion >= AR_SREV_VERSION_OAHU) {			saveFrameSeqCount[0] = OS_REG_READ(ah, AR_D0_SEQNUM);		} else {			for (i = 0; i < AR_NUM_DCU; i++)				saveFrameSeqCount[i] = OS_REG_READ(ah, AR_DSEQNUM(i));		}		if (!(ichan->channelFlags & CHANNEL_DFS)) 			ichan->privFlags &= ~CHANNEL_INTERFERENCE;		chan->channelFlags = ichan->channelFlags;		chan->privFlags = ichan->privFlags;	}	/*	 * Preserve the antenna on a channel change	 */	saveDefAntenna = OS_REG_READ(ah, AR_DEF_ANTENNA);	if (saveDefAntenna == 0)		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;	/* Save led state from pci config register */	ledstate = 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);	if (!ar5211ChipReset(ah, chan->channelFlags)) {		HALDEBUG(ah, "%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;	default:		/* Ah, a new wireless mode */		HALASSERT(0);		break;	}	/* Set correct Baseband to analog shift setting to access analog chips. */	if (AH_PRIVATE(ah)->ah_macVersion >= AR_SREV_VERSION_OAHU) {		OS_REG_WRITE(ah, AR_PHY_BASE, 0x00000007);	} else {		OS_REG_WRITE(ah, AR_PHY_BASE, 0x00000047);	}	/* Write parameters specific to AR5211 */	if (AH_PRIVATE(ah)->ah_macVersion >= AR_SREV_VERSION_OAHU) {		if (IS_CHAN_2GHZ(chan) &&		    ahp->ah_eeversion >= AR_EEPROM_VER3_1) {			u_int32_t ob2GHz, db2GHz;			if (IS_CHAN_CCK(chan)) {				ob2GHz = ahp->ah_ob2GHz[0];				db2GHz = ahp->ah_db2GHz[0];			} else {				ob2GHz = ahp->ah_ob2GHz[1];				db2GHz = ahp->ah_db2GHz[1];			}			ob2GHz = ath_hal_reverseBits(ob2GHz, 3);			db2GHz = ath_hal_reverseBits(db2GHz, 3);			ar5211Mode2_4[25][freqIndex] =				(ar5211Mode2_4[25][freqIndex] & ~0xC0) |					((ob2GHz << 6) & 0xC0);			ar5211Mode2_4[26][freqIndex] =				(ar5211Mode2_4[26][freqIndex] & ~0x0F) |					(((ob2GHz >> 2) & 0x1) |					 ((db2GHz << 1) & 0x0E));		}		for (i = 0; i < N(ar5211Mode2_4); i++)			OS_REG_WRITE(ah, ar5211Mode2_4[i][0],				ar5211Mode2_4[i][freqIndex]);	}	/* Write the analog registers 6 and 7 before other config */	ar5211SetRf6and7(ah, chan);	/* Write registers that vary across all modes */	for (i = 0; i < N(ar5211Modes); i++)		OS_REG_WRITE(ah, ar5211Modes[i][0], ar5211Modes[i][modesIndex]);	/* Write RFGain Parameters that differ between 2.4 and 5 GHz */	for (i = 0; i < N(ar5211BB_RfGain); i++)		OS_REG_WRITE(ah, ar5211BB_RfGain[i][0], ar5211BB_RfGain[i][freqIndex]);	/* Write Common Array Parameters */	for (i = 0; i < N(ar5211Common); i++) {		u_int32_t reg = ar5211Common[i][0];		/* On channel change, don't reset the PCU registers */		if (!(bChannelChange && (0x8000 <= reg && reg < 0x9000)))			OS_REG_WRITE(ah, reg, ar5211Common[i][1]);	}	/* Fix pre-AR5211 register values, this includes AR5311s. */	if (AH_PRIVATE(ah)->ah_macVersion < AR_SREV_VERSION_OAHU) {		/*		 * The TX and RX latency values have changed locations		 * within the USEC register in AR5211.  Since they're		 * set via the .ini, for both AR5211 and AR5311, they		 * are written properly here for AR5311.		 */		data = OS_REG_READ(ah, AR_USEC);		/* Must be 0 for proper write in AR5311 */		HALASSERT((data & 0x00700000) == 0);		OS_REG_WRITE(ah, AR_USEC,			(data & (AR_USEC_M | AR_USEC_32_M | AR5311_USEC_TX_LAT_M)) |			((29 << AR5311_USEC_RX_LAT_S) & AR5311_USEC_RX_LAT_M));		/* The following registers exist only on AR5311. */		OS_REG_WRITE(ah, AR5311_QDCLKGATE, 0);		/* Set proper ADC & DAC delays for AR5311. */		OS_REG_WRITE(ah, 0x00009878, 0x00000008);		/* Enable the PCU FIFO corruption ECO on AR5311. */		OS_REG_WRITE(ah, AR_DIAG_SW,			OS_REG_READ(ah, AR_DIAG_SW) | AR5311_DIAG_SW_USE_ECO);	}	/* Restore certain DMA hardware registers on a channel change */	if (bChannelChange) {		/* AR5211 WAR - Restore TSF */		OS_REG_WRITE(ah, AR_TSF_L32, saveTsfLow);		OS_REG_WRITE(ah, AR_TSF_U32, saveTsfHigh);		if (AH_PRIVATE(ah)->ah_macVersion >= AR_SREV_VERSION_OAHU) {			OS_REG_WRITE(ah, AR_D0_SEQNUM, saveFrameSeqCount[0]);		} else {			for (i = 0; i < AR_NUM_DCU; i++)				OS_REG_WRITE(ah, AR_DSEQNUM(i), saveFrameSeqCount[i]);		}	}	OS_REG_WRITE(ah, AR_STA_ID0, LE_READ_4(ahp->ah_macaddr));	switch (opmode) {	case HAL_M_HOSTAP:		OS_REG_WRITE(ah, AR_STA_ID1, LE_READ_2(ahp->ah_macaddr + 4)			| macStaId1			| AR_STA_ID1_STA_AP			| AR_STA_ID1_RTS_USE_DEF);		break;	case HAL_M_IBSS:		/*		 * Set the IBSS mode only if we were configured to be so.		 * If bssType is ANY_BSS then the scan will determine what		 * mode we finally end up in.		 */		OS_REG_WRITE(ah, AR_STA_ID1, LE_READ_2(ahp->ah_macaddr + 4)			| AR_STA_ID1_ADHOC			| AR_STA_ID1_RTS_USE_DEF);		break;	case HAL_M_STA:		OS_REG_WRITE(ah, AR_STA_ID1, LE_READ_2(ahp->ah_macaddr + 4)			| AR_STA_ID1_DEFAULT_ANTENNA);		break;	case HAL_M_MONITOR:		OS_REG_WRITE(ah, AR_STA_ID1, LE_READ_2(ahp->ah_macaddr + 4)			| macStaId1			| AR_STA_ID1_DEFAULT_ANTENNA);		break;	}	/* Restore previous led state */	OS_REG_WRITE(ah, AR_PCICFG, OS_REG_READ(ah, AR_PCICFG) | ledstate);	OS_REG_WRITE(ah, AR_GPIOCR, softLedCfg);	OS_REG_WRITE(ah, AR_GPIODO, softLedState);	/* Restore previous antenna */	OS_REG_WRITE(ah, AR_DEF_ANTENNA, saveDefAntenna);	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));	OS_REG_WRITE(ah, AR_ISR, ~0);		/* cleared on write */	/*	 * AR5211 WAR - pre-Production Oahu only.	 * Disable clock gating in all DMA blocks. This is a workaround for	 * a hardware problem seen with 11B and AES.	 * This workaround will result in higher power consumption.	 */	if (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_VERSION_OAHU &&	    AH_PRIVATE(ah)->ah_macRev < AR_SREV_OAHU_PROD) {		OS_REG_WRITE(ah, AR_CFG,			OS_REG_READ(ah, AR_CFG) | AR_CFG_CLK_GATE_DIS);	}	OS_REG_WRITE(ah, AR_RSSI_THR, INIT_RSSI_THR);	/* Setup the transmit power values. */	if (!ar5211SetTransmitPower(ah, chan)) {		HALDEBUG(ah, "%s: error init'ing transmit power\n", __func__);		FAIL(HAL_EIO);	}	/* Setup board specific options for EEPROM version 3 */	ar5211SetBoardValues(ah, chan);	if (!ar5211SetChannel(ah, ichan)) {		HALDEBUG(ah, "%s: unable to set channel\n", __func__);		FAIL(HAL_EIO);	}	/* Activate the PHY */	if (AH_PRIVATE(ah)->ah_devid == AR5211_FPGA11B && IS_CHAN_2GHZ(chan))		OS_REG_WRITE(ah, 0xd808, 0x502); /* required for FPGA */	OS_REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);	/*	 * Wait for the frequency synth to settle (synth goes on	 * via AR_PHY_ACTIVE_EN).  Read the phy active delay register.	 * Value is in 100ns increments.	 */	data = OS_REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_M;	if (IS_CHAN_CCK(chan)) {		synthDelay = (4 * data) / 22;	} else {		synthDelay = data / 10;	}	/*	 * There is an issue if the AP starts the calibration before	 * the baseband timeout completes.  This could result in the	 * rxclear false triggering.  Add an extra delay to ensure this	 * this does not happen.	 */	OS_DELAY(synthDelay + DELAY_BASE_ACTIVATE);	/* Calibrate the AGC and wait for completion. */	OS_REG_WRITE(ah, AR_PHY_AGC_CONTROL,		 OS_REG_READ(ah, AR_PHY_AGC_CONTROL) | AR_PHY_AGC_CONTROL_CAL);	(void) ath_hal_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, 0);	/* Perform noise floor and set status */	if (!ar5211CalNoiseFloor(ah, chan)) {		if (!IS_CHAN_CCK(chan))			chan->channelFlags |= CHANNEL_CW_INT;		HALDEBUG(ah, "%s: noise floor calibration failed\n", __func__);		FAIL(HAL_EIO);	}	/* Start IQ calibration w/ 2^(INIT_IQCAL_LOG_COUNT_MAX+1) samples */	if (ahp->ah_calibrationTime != 0) {		OS_REG_WRITE(ah, AR_PHY_TIMING_CTRL4,			AR_PHY_TIMING_CTRL4_DO_IQCAL | (INIT_IQCAL_LOG_COUNT_MAX << AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX_S));		ahp->ah_bIQCalibration = AH_TRUE;	}	/* set 1:1 QCU to DCU mapping for all queues */	for (q = 0; q < AR_NUM_DCU; q++)		OS_REG_WRITE(ah, AR_DQCUMASK(q), 1<<q);	for (q = 0; q < HAL_NUM_TX_QUEUES; q++)		ar5211ResetTxQueue(ah, q);	/* Setup QCU0 transmit interrupt masks (TX_ERR, TX_OK, TX_DESC, TX_URN) */	OS_REG_WRITE(ah, AR_IMR_S0,		 (AR_IMR_S0_QCU_TXOK & AR_QCU_0) |		 (AR_IMR_S0_QCU_TXDESC & (AR_QCU_0<<AR_IMR_S0_QCU_TXDESC_S)));

⌨️ 快捷键说明

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