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

📄 ar5210_reset.c

📁 Atheros wifi driver source code
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting * Copyright (c) 2002-2005 Atheros Communications, Inc. * All rights reserved. * * $Id: ar5210_reset.c,v 1.1.1.1 2006/09/12 03:45:22 steven Exp $ */#include "opt_ah.h"#ifdef AH_SUPPORT_AR5210#include "ah.h"#include "ah_internal.h"#include "ar5210/ar5210.h"#include "ar5210/ar5210reg.h"#include "ar5210/ar5210phy.h"typedef struct {	u_int32_t	Offset;	u_int32_t	Value;} REGISTER_VAL;static const REGISTER_VAL ar5k0007_init[] = {#include "ar5210/ar5k_0007.ini"};/* Default Power Settings for channels outside of EEPROM range */static const u_int8_t ar5k0007_pwrSettings[17] = {/*	gain delta			pc dac *//* 54  48  36  24  18  12   9   54  48  36  24  18  12   9   6  ob  db	  */    9,  9,  0,  0,  0,  0,  0,   2,  2,  6,  6,  6,  6,  6,  6,  2,  2};/* * The delay, in usecs, between writing AR_RC with a reset * request and waiting for the chip to settle.  If this is * too short then the chip does not come out of sleep state. * Note this value was empirically derived and may be dependent * on the host machine (don't know--the problem was identified * on an IBM 570e laptop; 10us delays worked on other systems). */#define	AR_RC_SETTLE_TIME	20000static HAL_BOOL ar5210SetResetReg(struct ath_hal *,		u_int32_t resetMask, u_int delay);static HAL_BOOL ar5210SetChannel(struct ath_hal *ah, HAL_CHANNEL *chan);/* * 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_BOOLar5210Reset(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_5210 *ahp = AH5210(ah);	HAL_STATUS ecode;	u_int32_t ledstate;	int i, q;	HALDEBUG(ah, "%s: opmode %u channel %u/0x%x %s channel\n", __func__,		opmode, chan->channel, chan->channelFlags,		bChannelChange ? "change" : "same");	if ((chan->channelFlags & CHANNEL_5GHZ) == 0) {		/* Only 11a mode */		HALDEBUG(ah, "%s: channel not 5Ghz\n", __func__);		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;	}	ledstate = OS_REG_READ(ah, AR_PCICFG) &		(AR_PCICFG_LED_PEND | AR_PCICFG_LED_ACT);	if (!ar5210ChipReset(ah, chan)) {		HALDEBUG(ah, "%s: chip reset failed\n", __func__);		FAIL(HAL_EIO);	}	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)			| AR_STA_ID1_AP			| AR_STA_ID1_NO_PSPOLL			| AR_STA_ID1_DESC_ANTENNA);		OS_REG_WRITE(ah, AR_BCR, INIT_BCON_CNTRL_REG);		OS_REG_WRITE(ah, AR_PCICFG,			AR_PCICFG_LED_ACT | AR_PCICFG_LED_BCTL);		break;	case HAL_M_IBSS:		OS_REG_WRITE(ah, AR_STA_ID1, LE_READ_2(ahp->ah_macaddr + 4)			| AR_STA_ID1_ADHOC			| AR_STA_ID1_NO_PSPOLL			| AR_STA_ID1_DESC_ANTENNA);		OS_REG_WRITE(ah, AR_BCR, INIT_BCON_CNTRL_REG | AR_BCR_BCMD);		OS_REG_WRITE(ah, AR_PCICFG,			AR_PCICFG_CLKRUNEN | AR_PCICFG_LED_PEND | AR_PCICFG_LED_BCTL);		break;	case HAL_M_STA:		OS_REG_WRITE(ah, AR_STA_ID1, LE_READ_2(ahp->ah_macaddr + 4)			| AR_STA_ID1_NO_PSPOLL			| AR_STA_ID1_PWR_SV);		OS_REG_WRITE(ah, AR_BCR, INIT_BCON_CNTRL_REG);		OS_REG_WRITE(ah, AR_PCICFG,			AR_PCICFG_CLKRUNEN | AR_PCICFG_LED_PEND | AR_PCICFG_LED_BCTL);		break;	case HAL_M_MONITOR:		OS_REG_WRITE(ah, AR_STA_ID1, LE_READ_2(ahp->ah_macaddr + 4)			| AR_STA_ID1_NO_PSPOLL);		OS_REG_WRITE(ah, AR_BCR, INIT_BCON_CNTRL_REG);		OS_REG_WRITE(ah, AR_PCICFG,			AR_PCICFG_LED_ACT | AR_PCICFG_LED_BCTL);		break;	}	/* Restore previous led state */	OS_REG_WRITE(ah, AR_PCICFG, OS_REG_READ(ah, AR_PCICFG) | ledstate);	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_TXDP0, 0);	OS_REG_WRITE(ah, AR_TXDP1, 0);	OS_REG_WRITE(ah, AR_RXDP, 0);	/*	 * Initialize interrupt state.	 */	(void) OS_REG_READ(ah, AR_ISR);		/* cleared on read */	OS_REG_WRITE(ah, AR_IMR, 0);	OS_REG_WRITE(ah, AR_IER, AR_IER_DISABLE);	ahp->ah_maskReg = 0;	(void) OS_REG_READ(ah, AR_BSR);		/* cleared on read */	OS_REG_WRITE(ah, AR_TXCFG, AR_DMASIZE_128B);	OS_REG_WRITE(ah, AR_RXCFG, AR_DMASIZE_128B);	OS_REG_WRITE(ah, AR_TOPS, 8);		/* timeout prescale */	OS_REG_WRITE(ah, AR_RXNOFRM, 8);	/* RX no frame timeout */	OS_REG_WRITE(ah, AR_RPGTO, 0);		/* RX frame gap timeout */	OS_REG_WRITE(ah, AR_TXNOFRM, 0);	/* TX no frame timeout */	OS_REG_WRITE(ah, AR_SFR, 0);	OS_REG_WRITE(ah, AR_MIBC, 0);		/* unfreeze ctrs + clr state */	OS_REG_WRITE(ah, AR_RSSI_THR, INIT_RSSI_THR);	OS_REG_WRITE(ah, AR_CFP_DUR, 0);	ar5210SetRxFilter(ah, 0);		/* nothing for now */	OS_REG_WRITE(ah, AR_MCAST_FIL0, 0);	/* multicast filter */	OS_REG_WRITE(ah, AR_MCAST_FIL1, 0);	/* XXX was 2 */	OS_REG_WRITE(ah, AR_TX_MASK0, 0);	OS_REG_WRITE(ah, AR_TX_MASK1, 0);	OS_REG_WRITE(ah, AR_CLR_TMASK, 1);	OS_REG_WRITE(ah, AR_TRIG_LEV, 1);	/* minimum */	OS_REG_WRITE(ah, AR_DIAG_SW, 0);	OS_REG_WRITE(ah, AR_CFP_PERIOD, 0);	OS_REG_WRITE(ah, AR_TIMER0, 0);		/* next beacon time */	OS_REG_WRITE(ah, AR_TSF_L32, 0);	/* local clock */	OS_REG_WRITE(ah, AR_TIMER1, ~0);	/* next DMA beacon alert */	OS_REG_WRITE(ah, AR_TIMER2, ~0);	/* next SW beacon alert */	OS_REG_WRITE(ah, AR_TIMER3, 1);		/* next ATIM window */	/* Write the INI values for PHYreg initialization */	for (i = 0; i < N(ar5k0007_init); i++) {		u_int32_t reg = ar5k0007_init[i].Offset;		/* On channel change, don't reset the PCU registers */		if (!(bChannelChange && (0x8000 <= reg && reg < 0x9000)))			OS_REG_WRITE(ah, reg, ar5k0007_init[i].Value);	}	/* Setup the transmit power values for cards since 0x0[0-2]05 */	if (!ar5210SetTransmitPower(ah, chan)) {		HALDEBUG(ah, "%s: error init'ing transmit power\n", __func__);		FAIL(HAL_EIO);	}	OS_REG_WRITE(ah, AR_PHY(10),		(OS_REG_READ(ah, AR_PHY(10)) & 0xFFFF00FF) |		(ahp->ah_xlnaOn << 8));	OS_REG_WRITE(ah, AR_PHY(13),		(ahp->ah_xpaOff << 24) | (ahp->ah_xpaOff << 16) |		(ahp->ah_xpaOn << 8) | ahp->ah_xpaOn);	OS_REG_WRITE(ah, AR_PHY(17),		(OS_REG_READ(ah, AR_PHY(17)) & 0xFFFFC07F) |		((ahp->ah_antenna >> 1) & 0x3F80));	OS_REG_WRITE(ah, AR_PHY(18),		(OS_REG_READ(ah, AR_PHY(18)) & 0xFFFC0FFF) |		((ahp->ah_antenna << 10) & 0x3F000));	OS_REG_WRITE(ah, AR_PHY(25),		(OS_REG_READ(ah, AR_PHY(25)) & 0xFFF80FFF) |		((ahp->ah_thresh62 << 12) & 0x7F000));	OS_REG_WRITE(ah, AR_PHY(68),		(OS_REG_READ(ah, AR_PHY(68)) & 0xFFFFFFFC) |		(ahp->ah_antenna & 0x3));	if (!ar5210SetChannel(ah, chan)) {		HALDEBUG(ah, "%s: unable to set channel\n", __func__);		FAIL(HAL_EIO);	}	if (bChannelChange) {		HAL_CHANNEL_INTERNAL *ichan = AH_PRIVATE(ah)->ah_curchan;;		if (!(ichan->channelFlags & CHANNEL_DFS)) 			ichan->privFlags &= ~CHANNEL_INTERFERENCE;		chan->channelFlags = ichan->channelFlags;		chan->privFlags = ichan->privFlags;	}	/* Activate the PHY */	OS_REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ENABLE);	OS_DELAY(1000);		/* Wait a bit (1 msec) */	/* calibrate the HW and poll the bit going to 0 for completion */	OS_REG_WRITE(ah, AR_PHY_AGCCTL,		OS_REG_READ(ah, AR_PHY_AGCCTL) | AR_PHY_AGC_CAL);	(void) ath_hal_wait(ah, AR_PHY_AGCCTL, AR_PHY_AGC_CAL, 0);	/* Perform noise floor calibration and set status */	if (!ar5210CalNoiseFloor(ah, chan)) {		chan->channelFlags |= CHANNEL_CW_INT;		HALDEBUG(ah, "%s: noise floor calibration failed\n", __func__);		FAIL(HAL_EIO);	}	for (q = 0; q < HAL_NUM_TX_QUEUES; q++)		ar5210ResetTxQueue(ah, q);	if (ahp->ah_rfKill)		ar5210EnableRfKill(ah);	/*	 * Writing to AR_BEACON will start timers. Hence it should be	 * the last register to be written. Do not reset tsf, do not	 * enable beacons at this point, but preserve other values	 * like beaconInterval.	 */	OS_REG_WRITE(ah, AR_BEACON,		(OS_REG_READ(ah, AR_BEACON) &			~(AR_BEACON_EN | AR_BEACON_RESET_TSF)));	/* Restore user-specified slot time and timeouts */	if (ahp->ah_slottime != (u_int) -1)		ar5210SetSlotTime(ah, ahp->ah_slottime);	if (ahp->ah_acktimeout != (u_int) -1)		ar5210SetAckTimeout(ah, ahp->ah_acktimeout);	if (ahp->ah_ctstimeout != (u_int) -1)		ar5210SetCTSTimeout(ah, ahp->ah_ctstimeout);	if (AH_PRIVATE(ah)->ah_diagreg != 0)		OS_REG_WRITE(ah, AR_DIAG_SW, AH_PRIVATE(ah)->ah_diagreg);	AH_PRIVATE(ah)->ah_opmode = opmode;	/* record operating mode */	HALDEBUG(ah, "%s: done\n", __func__);	return AH_TRUE;bad:	if (*status)		*status = ecode;	return AH_FALSE;#undef FAIL#undef N}voidar5210SetPCUConfig(struct ath_hal *ah){	u_int32_t val;	val = OS_REG_READ(ah, AR_STA_ID1) & 0xffff;	switch (AH_PRIVATE(ah)->ah_opmode) {	case HAL_M_HOSTAP:		OS_REG_WRITE(ah, AR_STA_ID1, val			| AR_STA_ID1_AP			| AR_STA_ID1_NO_PSPOLL			| AR_STA_ID1_DESC_ANTENNA);		break;	case HAL_M_IBSS:		OS_REG_WRITE(ah, AR_STA_ID1, val			| AR_STA_ID1_ADHOC			| AR_STA_ID1_NO_PSPOLL			| AR_STA_ID1_DESC_ANTENNA);		break;	case HAL_M_STA:		OS_REG_WRITE(ah, AR_STA_ID1, val			| AR_STA_ID1_NO_PSPOLL			| AR_STA_ID1_PWR_SV);		break;	case HAL_M_MONITOR:		OS_REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_NO_PSPOLL);		break;	}}/* * Places the PHY and Radio chips into reset.  A full reset * must be called to leave this state.  The PCI/MAC/PCU are * not placed into reset as we must receive interrupt to * re-enable the hardware. */HAL_BOOLar5210PhyDisable(struct ath_hal *ah){	return ar5210SetResetReg(ah, AR_RC_RPHY, 10);}/* * Places all of hardware into reset */HAL_BOOLar5210Disable(struct ath_hal *ah){#define	AR_RC_HW (AR_RC_RPCU | AR_RC_RDMA | AR_RC_RPHY | AR_RC_RMAC)	if (!ar5210SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE))		return AH_FALSE;	/*	 * Reset the HW - PCI must be reset after the rest of the	 * device has been reset	 */	if (!ar5210SetResetReg(ah, AR_RC_HW, AR_RC_SETTLE_TIME))		return AH_FALSE;	OS_DELAY(1000);	(void) ar5210SetResetReg(ah, AR_RC_HW | AR_RC_RPCI, AR_RC_SETTLE_TIME);	OS_DELAY(2100);   /* 8245 @ 96Mhz hangs with 2000us. */	return AH_TRUE;#undef AR_RC_HW}/* * Places the hardware into reset and then pulls it out of reset */HAL_BOOLar5210ChipReset(struct ath_hal *ah, HAL_CHANNEL *chan){#define	AR_RC_HW (AR_RC_RPCU | AR_RC_RDMA | AR_RC_RPHY | AR_RC_RMAC)	HALDEBUG(ah, "%s %p turbo %s\n", __func__, ah,		chan && IS_CHAN_TURBO(chan) ? "enabled" : "disabled");	if (!ar5210SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE))		return AH_FALSE;	/* Place chip in turbo before reset to cleanly reset clocks */	OS_REG_WRITE(ah, AR_PHY_FRCTL,		chan && IS_CHAN_TURBO(chan) ? AR_PHY_TURBO_MODE : 0);	/*	 * Reset the HW.	 * PCI must be reset after the rest of the device has been reset.	 */	if (!ar5210SetResetReg(ah, AR_RC_HW, AR_RC_SETTLE_TIME))		return AH_FALSE;	OS_DELAY(1000);	if (!ar5210SetResetReg(ah, AR_RC_HW | AR_RC_RPCI, AR_RC_SETTLE_TIME))		return AH_FALSE;	OS_DELAY(2100);   /* 8245 @ 96Mhz hangs with 2000us. */	/*	 * Bring out of sleep mode (AGAIN)	 *	 * WARNING WARNING WARNING	 *	 * There is a problem with the chip where it doesn't always indicate	 * that it's awake, so initializePowerUp() will fail.	 */	if (!ar5210SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE))		return AH_FALSE;	/* Clear warm reset reg */	return ar5210SetResetReg(ah, 0, 10);#undef AR_RC_HW}enum {	FIRPWR_M	= 0x03fc0000,	FIRPWR_S	= 18,	KCOARSEHIGH_M   = 0x003f8000,	KCOARSEHIGH_S   = 15,	KCOARSELOW_M	= 0x00007f80,	KCOARSELOW_S	= 7,	ADCSAT_ICOUNT_M	= 0x0001f800,	ADCSAT_ICOUNT_S	= 11,	ADCSAT_THRESH_M	= 0x000007e0,	ADCSAT_THRESH_S	= 5};/* * Recalibrate the lower PHY chips to account for temperature/environment * changes. */HAL_BOOLar5210PerCalibration(struct ath_hal *ah, HAL_CHANNEL *chan, HAL_BOOL *isIQdone){	u_int32_t regBeacon;	u_int32_t reg9858, reg985c, reg9868;	/* Disable tx and rx */	OS_REG_WRITE(ah, AR_DIAG_SW,		OS_REG_READ(ah, AR_DIAG_SW) | (AR_DIAG_SW_DIS_TX | AR_DIAG_SW_DIS_RX));	/* Disable Beacon Enable */	regBeacon = OS_REG_READ(ah, AR_BEACON);	OS_REG_WRITE(ah, AR_BEACON, regBeacon & ~AR_BEACON_EN);	/* Delay 4ms to ensure that all tx and rx activity has ceased */	OS_DELAY(4000);	/* Disable AGC to radio traffic */	OS_REG_WRITE(ah, 0x9808, OS_REG_READ(ah, 0x9808) | 0x08000000);	/* Wait for the AGC traffic to cease. */	OS_DELAY(10);	/* Change Channel to relock synth */	if (!ar5210SetChannel(ah, chan))		return AH_FALSE;	/* wait for the synthesizer lock to stabilize */	OS_DELAY(1000);	/* Re-enable AGC to radio traffic */	OS_REG_WRITE(ah, 0x9808, OS_REG_READ(ah, 0x9808) & (~0x08000000));	/*	 * Configure the AGC so that it is highly unlikely (if not	 * impossible) for it to send any gain changes to the analog	 * chip.  We store off the current values so that they can	 * be rewritten below. Setting the following values:	 * firpwr	 = -1	 * Kcoursehigh   = -1	 * Kcourselow	 = -127	 * ADCsat_icount = 2	 * ADCsat_thresh = 12	 */	reg9858 = OS_REG_READ(ah, 0x9858);	reg985c = OS_REG_READ(ah, 0x985c);	reg9868 = OS_REG_READ(ah, 0x9868);	OS_REG_WRITE(ah, 0x9858, (reg9858 & ~FIRPWR_M) |					 ((-1 << FIRPWR_S) & FIRPWR_M));	OS_REG_WRITE(ah, 0x985c,		 (reg985c & ~(KCOARSEHIGH_M | KCOARSELOW_M)) |		 ((-1 << KCOARSEHIGH_S) & KCOARSEHIGH_M) |		 ((-127 << KCOARSELOW_S) & KCOARSELOW_M));	OS_REG_WRITE(ah, 0x9868,		 (reg9868 & ~(ADCSAT_ICOUNT_M | ADCSAT_THRESH_M)) |		 ((2 << ADCSAT_ICOUNT_S) & ADCSAT_ICOUNT_M) |		 ((12 << ADCSAT_THRESH_S) & ADCSAT_THRESH_M));

⌨️ 快捷键说明

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