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

📄 ar5211_reset.c

📁 Atheros wifi driver source code
💻 C
📖 第 1 页 / 共 4 页
字号:
	OS_REG_WRITE(ah, AR_IMR_S1, (AR_IMR_S1_QCU_TXERR & AR_QCU_0));	OS_REG_WRITE(ah, AR_IMR_S2, (AR_IMR_S2_QCU_TXURN & AR_QCU_0));	/*	 * DPD Added 4/19 from mainline:	 * AR5211 WAR - GBL_EIFS must always be written after writing	 *		to any QCUMASK register.	 */	OS_REG_WRITE(ah, AR_D_GBL_IFS_EIFS, OS_REG_READ(ah, AR_D_GBL_IFS_EIFS));	/* Now set up the Interrupt Mask Register and save it for future use */	OS_REG_WRITE(ah, AR_IMR, INIT_INTERRUPT_MASK);	ahp->ah_maskReg = INIT_INTERRUPT_MASK;	/* Enable bus error interrupts */	OS_REG_WRITE(ah, AR_IMR_S2, OS_REG_READ(ah, AR_IMR_S2) |		 AR_IMR_S2_MCABT | AR_IMR_S2_SSERR | AR_IMR_S2_DPERR);	/* Enable interrupts specific to AP */	if (opmode == HAL_M_HOSTAP) {		OS_REG_WRITE(ah, AR_IMR, OS_REG_READ(ah, AR_IMR) | AR_IMR_MIB);		ahp->ah_maskReg |= AR_IMR_MIB;	}	if (ar5211GetRfKill(ah))		ar5211EnableRfKill(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)		ar5211SetSlotTime(ah, ahp->ah_slottime);	if (ahp->ah_acktimeout != (u_int) -1)		ar5211SetAckTimeout(ah, ahp->ah_acktimeout);	if (ahp->ah_ctstimeout != (u_int) -1)		ar5211SetCTSTimeout(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}/* * 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_BOOLar5211PhyDisable(struct ath_hal *ah){	return ar5211SetResetReg(ah, AR_RC_BB);}/* * Places all of hardware into reset */HAL_BOOLar5211Disable(struct ath_hal *ah){	if (!ar5211SetPowerMode(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 (!ar5211SetResetReg(ah, AR_RC_MAC | AR_RC_BB | AR_RC_PCI))		return AH_FALSE;	OS_DELAY(2100);	   /* 8245 @ 96Mhz hangs with 2000us. */	return AH_TRUE;}/* * Places the hardware into reset and then pulls it out of reset * * Only write the PLL if we're changing to or from CCK mode * * Attach calls with channelFlags = 0, as the coldreset should have * us in the correct mode and we cannot check the hwchannel flags. */HAL_BOOLar5211ChipReset(struct ath_hal *ah, u_int16_t channelFlags){	if (!ar5211SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE))		return AH_FALSE;	/* Set CCK and Turbo modes correctly */	switch (channelFlags & CHANNEL_ALL) {	case CHANNEL_2GHZ|CHANNEL_CCK:	case CHANNEL_2GHZ|CHANNEL_CCK|CHANNEL_TURBO:		OS_REG_WRITE(ah, AR_PHY_TURBO, 0);		OS_REG_WRITE(ah, AR5211_PHY_MODE,			AR5211_PHY_MODE_CCK | AR5211_PHY_MODE_RF2GHZ);		OS_REG_WRITE(ah, AR_PHY_PLL_CTL, AR_PHY_PLL_CTL_44);		/* Wait for the PLL to settle */		OS_DELAY(DELAY_PLL_SETTLE);		break;	case CHANNEL_2GHZ|CHANNEL_OFDM:	case CHANNEL_2GHZ|CHANNEL_OFDM|CHANNEL_TURBO:		OS_REG_WRITE(ah, AR_PHY_TURBO, 0);		if (AH_PRIVATE(ah)->ah_devid == AR5211_DEVID) {			OS_REG_WRITE(ah, AR_PHY_PLL_CTL, AR_PHY_PLL_CTL_40);			OS_DELAY(DELAY_PLL_SETTLE);			OS_REG_WRITE(ah, AR5211_PHY_MODE,				AR5211_PHY_MODE_OFDM | AR5211_PHY_MODE_RF2GHZ);		}		break;	case CHANNEL_A:	case CHANNEL_T:		if (channelFlags & CHANNEL_TURBO) {			OS_REG_WRITE(ah, AR_PHY_TURBO,				AR_PHY_FC_TURBO_MODE | AR_PHY_FC_TURBO_SHORT);		} else {				/* 5 GHZ OFDM Mode */			OS_REG_WRITE(ah, AR_PHY_TURBO, 0);		}		if (AH_PRIVATE(ah)->ah_devid == AR5211_DEVID) {			OS_REG_WRITE(ah, AR_PHY_PLL_CTL, AR_PHY_PLL_CTL_40);			OS_DELAY(DELAY_PLL_SETTLE);			OS_REG_WRITE(ah, AR5211_PHY_MODE,				AR5211_PHY_MODE_OFDM | AR5211_PHY_MODE_RF5GHZ);		}		break;	}	/* NB: else no flags set - must be attach calling - do nothing */	/*	 * Reset the HW - PCI must be reset after the rest of the	 * device has been reset	 */	if (!ar5211SetResetReg(ah, AR_RC_MAC | AR_RC_BB | AR_RC_PCI))		return AH_FALSE;	OS_DELAY(2100);	   /* 8245 @ 96Mhz hangs with 2000us. */	/* Bring out of sleep mode (AGAIN) */	if (!ar5211SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE))		return AH_FALSE;	/* Clear warm reset register */	return ar5211SetResetReg(ah, 0);}/* * Recalibrate the lower PHY chips to account for temperature/environment * changes. */HAL_BOOLar5211PerCalibration(struct ath_hal *ah, HAL_CHANNEL *chan, HAL_BOOL *isIQdone){	struct ath_hal_5211 *ahp = AH5211(ah);	int32_t qCoff, qCoffDenom;	u_int32_t data;	int32_t iqCorrMeas;	int32_t iCoff, iCoffDenom;	u_int32_t powerMeasQ, powerMeasI;	/* IQ calibration in progress. Check to see if it has finished. */	if (ahp->ah_bIQCalibration &&	    !(OS_REG_READ(ah, AR_PHY_TIMING_CTRL4) & AR_PHY_TIMING_CTRL4_DO_IQCAL)) {		/* IQ Calibration has finished. */		ahp->ah_bIQCalibration = AH_FALSE;		/* Read calibration results. */		powerMeasI = OS_REG_READ(ah, AR_PHY_IQCAL_RES_PWR_MEAS_I);		powerMeasQ = OS_REG_READ(ah, AR_PHY_IQCAL_RES_PWR_MEAS_Q);		iqCorrMeas = OS_REG_READ(ah, AR_PHY_IQCAL_RES_IQ_CORR_MEAS);		/*		 * Prescale these values to remove 64-bit operation requirement at the loss		 * of a little precision.		 */		iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 128;		qCoffDenom = powerMeasQ / 64;		/* Protect against divide-by-0. */		if (iCoffDenom != 0 && qCoffDenom != 0) {			iCoff = (-iqCorrMeas) / iCoffDenom;			/* IQCORR_Q_I_COFF is a signed 6 bit number */			iCoff = iCoff & 0x3f;			qCoff = ((int32_t)powerMeasI / qCoffDenom) - 64;			/* IQCORR_Q_Q_COFF is a signed 5 bit number */			qCoff = qCoff & 0x1f;#ifdef CALIBRATION_DEBUG			HALDEBUG(ah, "powerMeasI = 0x%08x\n", powerMeasI);			HALDEBUG(ah, "powerMeasQ = 0x%08x\n", powerMeasQ);			HALDEBUG(ah, "iqCorrMeas = 0x%08x\n", iqCorrMeas);			HALDEBUG(ah, "iCoff	  = %d\n", iCoff);			HALDEBUG(ah, "qCoff	  = %d\n", qCoff);#endif			/* Write IQ */			data  = OS_REG_READ(ah, AR_PHY_TIMING_CTRL4) |				AR_PHY_TIMING_CTRL4_IQCORR_ENABLE |				(((u_int32_t)iCoff) << AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF_S) |				((u_int32_t)qCoff);			OS_REG_WRITE(ah, AR_PHY_TIMING_CTRL4, data);		}	}	/* Perform noise floor and set status */	if (!ar5211IsNfGood(ah, chan)) {		/* XXX??? */		if (!IS_CHAN_CCK(chan))			chan->channelFlags |= CHANNEL_CW_INT;		return AH_FALSE;	}	if (!ar5211CalNoiseFloor(ah, chan)) {		/*		 * Delay 5ms before retrying the noise floor		 * just to make sure, as we are in an error		 * condition here.		 */		OS_DELAY(5000);		if (!ar5211CalNoiseFloor(ah, chan)) {			if (!IS_CHAN_CCK(chan))				chan->channelFlags |= CHANNEL_CW_INT;			return AH_FALSE;		}	}	ar5211RequestRfgain(ah);	*isIQdone = !ahp->ah_bIQCalibration;	return AH_TRUE;}/* * Writes the given reset bit mask into the reset register */static HAL_BOOLar5211SetResetReg(struct ath_hal *ah, u_int32_t resetMask){	u_int32_t mask = resetMask ? resetMask : ~0;	HAL_BOOL rt;	(void) OS_REG_READ(ah, AR_RXDP);/* flush any pending MMR writes */	OS_REG_WRITE(ah, AR_RC, resetMask);	/* need to wait at least 128 clocks when reseting PCI before read */	OS_DELAY(15);	resetMask &= AR_RC_MAC | AR_RC_BB;	mask &= AR_RC_MAC | AR_RC_BB;	rt = ath_hal_wait(ah, AR_RC, mask, resetMask);        if ((resetMask & AR_RC_MAC) == 0) {		if (isBigEndian()) {			/*			 * Set CFG, little-endian for register			 * and descriptor accesses.			 */			mask = INIT_CONFIG_STATUS |				AR_CFG_SWTD | AR_CFG_SWRD | AR_CFG_SWRG;			OS_REG_WRITE(ah, AR_CFG, LE_READ_4(&mask));		} else			OS_REG_WRITE(ah, AR_CFG, INIT_CONFIG_STATUS);	}	return rt;}/* * Takes the MHz channel value and sets the Channel value * * ASSUMES: Writes enabled to analog bus before AGC is active *   or by disabling the AGC. */static HAL_BOOLar5211SetChannel(struct ath_hal *ah,  HAL_CHANNEL_INTERNAL *chan){	u_int32_t refClk, reg32, data2111;	int16_t chan5111, chanIEEE;	chanIEEE = ath_hal_mhz2ieee(ah, chan->channel, chan->channelFlags);	if (IS_CHAN_2GHZ(chan)) {		const CHAN_INFO_2GHZ* ci =			&chan2GHzData[chanIEEE + CI_2GHZ_INDEX_CORRECTION];		data2111 = ((ath_hal_reverseBits(ci->channelSelect, 8) & 0xff)				<< 5)			 | (ci->refClkSel << 4);		chan5111 = ci->channel5111;	} else {		data2111 = 0;		chan5111 = chanIEEE;	}	/* Rest of the code is common for 5 GHz and 2.4 GHz. */	if (chan5111 >= 145 || (chan5111 & 0x1)) {		reg32 = ath_hal_reverseBits(chan5111 - 24, 8) & 0xFF;		refClk = 1;	} else {		reg32 = ath_hal_reverseBits(((chan5111 - 24) / 2), 8) & 0xFF;		refClk = 0;	}	reg32 = (reg32 << 2) | (refClk << 1) | (1 << 10) | 0x1;	OS_REG_WRITE(ah, AR_PHY(0x27), ((data2111 & 0xff) << 8) | (reg32 & 0xff));	reg32 >>= 8;	OS_REG_WRITE(ah, AR_PHY(0x34), (data2111 & 0xff00) | (reg32 & 0xff));	AH_PRIVATE(ah)->ah_curchan = chan;	return AH_TRUE;}int16_tar5211GetNoiseFloor(struct ath_hal *ah){	int16_t nf;	nf = (OS_REG_READ(ah, AR_PHY(25)) >> 19) & 0x1ff;	if (nf & 0x100)		nf = 0 - ((nf ^ 0x1ff) + 1);	return nf;}/* * Peform the noisefloor calibration for the length of time set * in runTime (valid values 1 to 7) * * Returns: The NF value at the end of the given time (or 0 for failure) */int16_tar5211RunNoiseFloor(struct ath_hal *ah, u_int8_t runTime, int16_t startingNF){	int i, searchTime;	HALASSERT(runTime <= 7);	/* Setup  noise floor run time and starting value */	OS_REG_WRITE(ah, AR_PHY(25),		(OS_REG_READ(ah, AR_PHY(25)) & ~0xFFF) |			 ((runTime << 9) & 0xE00) | (startingNF & 0x1FF));	/* Calibrate the noise floor */	OS_REG_WRITE(ah, AR_PHY_AGC_CONTROL,		OS_REG_READ(ah, AR_PHY_AGC_CONTROL) | AR_PHY_AGC_CONTROL_NF);	/* Compute the required amount of searchTime needed to finish NF */	if (runTime == 0) {		/* 8 search windows * 6.4us each */		searchTime = 8  * 7;	} else {		/* 512 * runtime search windows * 6.4us each */		searchTime = (runTime * 512)  * 7;	}	/*	 * Do not read noise floor until it has been updated	 *	 * As a guesstimate - we may only get 1/60th the time on	 * the air to see search windows  in a heavily congested	 * network (40 us every 2400 us of time)	 */	for (i = 0; i < 60; i++) {		if ((OS_REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) == 0)			break;		OS_DELAY(searchTime);	}	if (i >= 60) {#ifdef AH_DEBUG		HALDEBUG(ah, "NF with runTime %d failed to end on channel %d\n",			runTime, AH_PRIVATE(ah)->ah_curchan->channel);		HALDEBUG(ah, "  PHY NF Reg state:	 0x%x\n",			OS_REG_READ(ah, AR_PHY_AGC_CONTROL));		HALDEBUG(ah, "  PHY Active Reg state: 0x%x\n",			OS_REG_READ(ah, AR_PHY_ACTIVE));#endif		return 0;	}	return ar5211GetNoiseFloor(ah);}static HAL_BOOLgetNoiseFloorThresh(struct ath_hal *ah, HAL_CHANNEL *chan, int16_t *nft){	struct ath_hal_5211 *ahp = AH5211(ah);	switch (chan->channelFlags & CHANNEL_ALL_NOTURBO) {	case CHANNEL_A:		*nft = ahp->ah_noiseFloorThresh[0];		break;	case CHANNEL_CCK|CHANNEL_2GHZ:		*nft = ahp->ah_noiseFloorThresh[1];		break;	case CHANNEL_OFDM|CHANNEL_2GHZ:		*nft = ahp->ah_noiseFloorThresh[2];		break;	default:		HALDEBUG(ah, "%s: invalid channel flags 0x%x\n",			__func__, chan->channelFlags);		return AH_FALSE;	}	return AH_TRUE;}/* * Read the NF and check it against the noise floor threshhold * * Returns: TRUE if the NF is good */static HAL_BOOLar5211IsNfGood(struct ath_hal *ah, HAL_CHANNEL *chan){	int16_t nf, nfThresh;	if (!getNoiseFloorThresh(ah, chan, &nfThresh))		return AH_FALSE;	if (OS_REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF)		HALDEBUG(ah, "%s: NF did not complete in calibration window\n",			__func__);	nf = (OS_REG_READ(ah, AR_PHY(25)) >> 19) & 0x1ff;	if (nf & 0x100)		nf = 0 - ((nf ^ 0x1ff) + 1);	if (nf > nfThresh)		HALDEBUG(ah, "%s: noise floor failed; detected %u, "			"threshold %u\n", __func__, nf, nfThresh);	return (nf <= nfThresh);}/* * Peform the noisefloor calibration and check for any constant channel * interference. * * NOTE: preAR5211 have a lengthy carrier wave detection process - hence * it is if'ed for MKK regulatory domain only. * * Returns: TRUE for a successful noise floor calibration; else FALSE */HAL_BOOLar5211CalNoiseFloor(struct ath_hal *ah, HAL_CHANNEL *chan){#define	N(a)	(sizeof (a) / sizeof (a[0]))	/* Check for Carrier Wave interference in MKK regulatory zone */	if (AH_PRIVATE(ah)->ah_macVersion < AR_SREV_VERSION_OAHU &&	    ath_hal_getnfcheckrequired(ah, chan)) {		static const u_int8_t runtime[3] = { 0, 2, 7 };		int16_t nf, nfThresh;		int i;		if (!getNoiseFloorThresh(ah, chan, &nfThresh))			return AH_FALSE;		/*		 * Run a quick noise floor that will hopefully		 * complete (decrease delay time).		 */		for (i = 0; i < N(runtime); i++) {			nf = ar5211RunNoiseFloor(ah, runtime[i], 0);			if (nf > nfThresh)				HALDEBUG(ah, "%s: run failed with %u > "					"threshold %u (runtime %u)\n",					__func__, nf, nfThresh, runtime[i]);		}		return (i <= N(runtime));	} else {		/* Calibrate the noise floor */		OS_REG_WRITE(ah, AR_PHY_AGC_CONTROL,			OS_REG_READ(ah, AR_PHY_AGC_CONTROL) |				 AR_PHY_AGC_CONTROL_NF);	}	return AH_TRUE;#undef N}/* * Reads EEPROM header info from device structure and programs * analog registers 6 and 7 * * REQUIRES: Access to the analog device */static HAL_BOOLar5211SetRf6and7(struct ath_hal *ah, HAL_CHANNEL *chan){#define	N(a)	(sizeof (a) / sizeof (a[0]))	struct ath_hal_5211 *ahp = AH5211(ah);	u_int16_t rfXpdGain, rfPloSel, rfPwdXpd;	u_int16_t tempOB, tempDB;	u_int16_t freqIndex;	int i;

⌨️ 快捷键说明

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