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

📄 ar5212_reset.c

📁 最新之atheros芯片driver source code, 基于linux操作系统,內含atheros芯片HAL全部代码
💻 C
📖 第 1 页 / 共 5 页
字号:
{	if (!ar5212SetPowerMode(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.	 */	return ar5212SetResetReg(ah, AR_RC_MAC | AR_RC_BB | AR_RC_PCI);}/* * Places the hardware into reset and then pulls it out of reset * * TODO: Only write the PLL if we're changing to or from CCK mode *  * WARNING: The order of the PLL and mode registers must be correct. */HAL_BOOLar5212ChipReset(struct ath_hal *ah, HAL_CHANNEL *chan){	OS_MARK(ah, AH_MARK_CHIPRESET, chan ? chan->channel : 0);	/*	 * Reset the HW - PCI must be reset after the rest of the	 * device has been reset	 */	if (!ar5212SetResetReg(ah, AR_RC_MAC | AR_RC_BB | AR_RC_PCI))		return AH_FALSE;	/* Bring out of sleep mode (AGAIN) */	if (!ar5212SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE))		return AH_FALSE;	/* Clear warm reset register */	if (!ar5212SetResetReg(ah, 0))		return AH_FALSE;	/*	 * Perform warm reset before the mode/PLL/turbo registers	 * are changed in order to deactivate the radio.  Mode changes	 * with an active radio can result in corrupted shifts to the	 * radio device.	 */	/*	 * Set CCK and Turbo modes correctly.	 */	if (chan != AH_NULL) {		/* NB: can be null during attach */		uint32_t rfMode, phyPLL = 0, curPhyPLL, turbo;		if (IS_5413(ah)) {	/* NB: =>'s 5424 also */			rfMode = AR_PHY_MODE_AR5112;			if (IS_CHAN_HALF_RATE(chan))				rfMode |= AR_PHY_MODE_HALF;			else if (IS_CHAN_QUARTER_RATE(chan))				rfMode |= AR_PHY_MODE_QUARTER;			if (IS_CHAN_CCK(chan) || IS_CHAN_G(chan))				phyPLL = AR_PHY_PLL_CTL_44_5112;			else				phyPLL = AR_PHY_PLL_CTL_40_5413;		} else if (IS_RAD5111(ah)) {			rfMode = AR_PHY_MODE_AR5111;			if (IS_CHAN_CCK(chan) || IS_CHAN_G(chan))				phyPLL = AR_PHY_PLL_CTL_44;			else				phyPLL = AR_PHY_PLL_CTL_40;			if (IS_CHAN_HALF_RATE(chan))				phyPLL = AR_PHY_PLL_CTL_HALF;			else if (IS_CHAN_QUARTER_RATE(chan))				phyPLL = AR_PHY_PLL_CTL_QUARTER;		} else {		/* 5112, 2413, 2316, 2317 */			rfMode = AR_PHY_MODE_AR5112;			if (IS_CHAN_CCK(chan) || IS_CHAN_G(chan))				phyPLL = AR_PHY_PLL_CTL_44_5112;			else				phyPLL = AR_PHY_PLL_CTL_40_5112;			if (IS_CHAN_HALF_RATE(chan))				phyPLL |= AR_PHY_PLL_CTL_HALF;			else if (IS_CHAN_QUARTER_RATE(chan))				phyPLL |= AR_PHY_PLL_CTL_QUARTER;		}		if (IS_CHAN_OFDM(chan) && (IS_CHAN_CCK(chan) || 					   IS_CHAN_G(chan)))			rfMode |= AR_PHY_MODE_DYNAMIC;		else if (IS_CHAN_OFDM(chan))			rfMode |= AR_PHY_MODE_OFDM;		else			rfMode |= AR_PHY_MODE_CCK;		if (IS_CHAN_5GHZ(chan))			rfMode |= AR_PHY_MODE_RF5GHZ;		else			rfMode |= AR_PHY_MODE_RF2GHZ;		turbo = IS_CHAN_TURBO(chan) ?			(AR_PHY_FC_TURBO_MODE | AR_PHY_FC_TURBO_SHORT) : 0;		curPhyPLL = OS_REG_READ(ah, AR_PHY_PLL_CTL);		/*		 * PLL, Mode, and Turbo values must be written in the correct		 * order to ensure:		 * - The PLL cannot be set to 44 unless the CCK or DYNAMIC		 *   mode bit is set		 * - Turbo cannot be set at the same time as CCK or DYNAMIC		 */		if (IS_CHAN_CCK(chan) || IS_CHAN_G(chan)) {			OS_REG_WRITE(ah, AR_PHY_TURBO, turbo);			OS_REG_WRITE(ah, AR_PHY_MODE, rfMode);			if (curPhyPLL != phyPLL) {				OS_REG_WRITE(ah,  AR_PHY_PLL_CTL,  phyPLL);				/* Wait for the PLL to settle */				OS_DELAY(PLL_SETTLE_DELAY);			}		} else {			if (curPhyPLL != phyPLL) {				OS_REG_WRITE(ah,  AR_PHY_PLL_CTL,  phyPLL);				/* Wait for the PLL to settle */				OS_DELAY(PLL_SETTLE_DELAY);			}			OS_REG_WRITE(ah, AR_PHY_TURBO, turbo);			OS_REG_WRITE(ah, AR_PHY_MODE, rfMode);		}	}	return AH_TRUE;}/* * Recalibrate the lower PHY chips to account for temperature/environment * changes. */HAL_BOOLar5212PerCalibrationN(struct ath_hal *ah,  HAL_CHANNEL *chan, u_int chainMask,	HAL_BOOL longCal, HAL_BOOL *isCalDone){#define IQ_CAL_TRIES    10	struct ath_hal_5212 *ahp = AH5212(ah);	HAL_CHANNEL_INTERNAL *ichan;	int32_t qCoff, qCoffDenom;	int32_t iqCorrMeas, iCoff, iCoffDenom;	uint32_t powerMeasQ, powerMeasI;	HAL_BOOL ichan_isBmode = AH_FALSE;	HAL_BOOL isBmode = AH_FALSE;	OS_MARK(ah, AH_MARK_PERCAL, chan->channel);	*isCalDone = AH_FALSE;	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);		return AH_FALSE;	}	SAVE_CCK(ah, ichan, ichan_isBmode);	SAVE_CCK(ah, chan, isBmode);	if (ahp->ah_bIQCalibration == IQ_CAL_DONE ||	    ahp->ah_bIQCalibration == IQ_CAL_INACTIVE)		*isCalDone = AH_TRUE;	/* IQ calibration in progress. Check to see if it has finished. */	if (ahp->ah_bIQCalibration == IQ_CAL_RUNNING &&	    !(OS_REG_READ(ah, AR_PHY_TIMING_CTRL4) & AR_PHY_TIMING_CTRL4_DO_IQCAL)) {		int i;		/* IQ Calibration has finished. */		ahp->ah_bIQCalibration = IQ_CAL_INACTIVE;		*isCalDone = AH_TRUE;		/* workaround for misgated IQ Cal results */		i = 0;		do {			/* 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);			if (powerMeasI && powerMeasQ)				break;			/* Do we really need this??? */			OS_REG_WRITE (ah,  AR_PHY_TIMING_CTRL4,				      OS_REG_READ(ah,  AR_PHY_TIMING_CTRL4) |				      AR_PHY_TIMING_CTRL4_DO_IQCAL);		} while (++i < IQ_CAL_TRIES);		/*		 * Prescale these values to remove 64-bit operation		 * requirement at the loss of a little precision.		 */		iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 128;		qCoffDenom = powerMeasQ / 128;		/* Protect against divide-by-0 and loss of sign bits. */		if (iCoffDenom != 0 && qCoffDenom >= 2) {			iCoff = (int8_t)(-iqCorrMeas) / iCoffDenom;			/* IQCORR_Q_I_COFF is a signed 6 bit number */			if (iCoff < -32) {				iCoff = -32;			} else if (iCoff > 31) {				iCoff = 31;			}			/* IQCORR_Q_Q_COFF is a signed 5 bit number */			qCoff = (powerMeasI / qCoffDenom) - 128;			if (qCoff < -16) {				qCoff = -16;			} else if (qCoff > 15) {				qCoff = 15;			}			HALDEBUG(ah, HAL_DEBUG_PERCAL,			    "****************** MISGATED IQ CAL! *******************\n");			HALDEBUG(ah, HAL_DEBUG_PERCAL,			    "time       = %d, i = %d, \n", OS_GETUPTIME(ah), i);			HALDEBUG(ah, HAL_DEBUG_PERCAL,			    "powerMeasI = 0x%08x\n", powerMeasI);			HALDEBUG(ah, HAL_DEBUG_PERCAL,			    "powerMeasQ = 0x%08x\n", powerMeasQ);			HALDEBUG(ah, HAL_DEBUG_PERCAL,			    "iqCorrMeas = 0x%08x\n", iqCorrMeas);			HALDEBUG(ah, HAL_DEBUG_PERCAL,			    "iCoff      = %d\n", iCoff);			HALDEBUG(ah, HAL_DEBUG_PERCAL,			    "qCoff      = %d\n", qCoff);			/* Write values and enable correction */			OS_REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4,				AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF, iCoff);			OS_REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4,				AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF, qCoff);			OS_REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4, 				AR_PHY_TIMING_CTRL4_IQCORR_ENABLE);			ahp->ah_bIQCalibration = IQ_CAL_DONE;			ichan->iqCalValid = AH_TRUE;			ichan->iCoff = iCoff;			ichan->qCoff = qCoff;		}	} else if (!IS_CHAN_B(chan) && ahp->ah_bIQCalibration == IQ_CAL_DONE &&	    !ichan->iqCalValid) {		/*		 * Start IQ calibration if configured channel has changed.		 * Use a magic number of 15 based on default value.		 */		OS_REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4,			AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX,			INIT_IQCAL_LOG_COUNT_MAX);		OS_REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4,			AR_PHY_TIMING_CTRL4_DO_IQCAL);		ahp->ah_bIQCalibration = IQ_CAL_RUNNING;	}	/* XXX EAR */	if (longCal) {		/* Check noise floor results */		ar5212GetNf(ah, ichan);		if ((ichan->channelFlags & CHANNEL_CW_INT) == 0) {			/* Perform cal for 5Ghz channels and any OFDM on 5112 */			if (IS_CHAN_5GHZ(chan) ||			    (IS_RAD5112(ah) && IS_CHAN_OFDM(chan)))				ar5212RequestRfgain(ah);		} else {			/* report up and clear internal state */			chan->channelFlags |= CHANNEL_CW_INT;			ichan->channelFlags &= ~CHANNEL_CW_INT;		}	}	RESTORE_CCK(ah, ichan, ichan_isBmode);	RESTORE_CCK(ah, chan, isBmode);	return AH_TRUE;#undef IQ_CAL_TRIES}HAL_BOOLar5212PerCalibration(struct ath_hal *ah,  HAL_CHANNEL *chan, HAL_BOOL *isIQdone){	return ar5212PerCalibrationN(ah, chan, 0x1, AH_TRUE, isIQdone);}HAL_BOOLar5212ResetCalValid(struct ath_hal *ah, HAL_CHANNEL *chan){	/* XXX */	return AH_TRUE;}/* * Write the given reset bit mask into the reset register */static HAL_BOOLar5212SetResetReg(struct ath_hal *ah, uint32_t resetMask){	uint32_t mask = resetMask ? resetMask : ~0;	HAL_BOOL rt;	/* XXX ar5212MacStop & co. */	if (IS_PCIE(ah)) {		resetMask &= ~AR_RC_PCI;	}	(void) OS_REG_READ(ah, AR_RXDP);/* flush any pending MMR writes */	OS_REG_WRITE(ah, AR_RC, resetMask);	OS_DELAY(15);			/* need to wait at least 128 clocks					   when reseting PCI before read */	mask &= (AR_RC_MAC | AR_RC_BB);	resetMask &= (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_SWRD | AR_CFG_SWRG;#ifndef AH_NEED_DESC_SWAP			mask |= AR_CFG_SWTD;#endif			OS_REG_WRITE(ah, AR_CFG, LE_READ_4(&mask));		} else			OS_REG_WRITE(ah, AR_CFG, INIT_CONFIG_STATUS);		if (ar5212SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE))			(void) OS_REG_READ(ah, AR_ISR_RAC);	}	/* track PHY power state so we don't try to r/w BB registers */	AH5212(ah)->ah_phyPowerOn = ((resetMask & AR_RC_BB) == 0);	return rt;}int16_tar5212GetNoiseFloor(struct ath_hal *ah){	int16_t nf = (OS_REG_READ(ah, AR_PHY(25)) >> 19) & 0x1ff;	if (nf & 0x100)		nf = 0 - ((nf ^ 0x1ff) + 1);	return nf;}static HAL_BOOLgetNoiseFloorThresh(struct ath_hal *ah, const HAL_CHANNEL_INTERNAL *chan,	int16_t *nft){	const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;	HALASSERT(ah->ah_magic == AR5212_MAGIC);	switch (chan->channelFlags & CHANNEL_ALL_NOTURBO) {	case CHANNEL_A:		*nft = ee->ee_noiseFloorThresh[headerInfo11A];		break;	case CHANNEL_B:		*nft = ee->ee_noiseFloorThresh[headerInfo11B];		break;	case CHANNEL_PUREG:		*nft = ee->ee_noiseFloorThresh[headerInfo11G];		break;	default:		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n",		    __func__, chan->channelFlags);		return AH_FALSE;	}	return AH_TRUE;}/* * Setup the noise floor cal history buffer. */void ar5212InitNfCalHistBuffer(struct ath_hal *ah){	struct ath_hal_5212 *ahp = AH5212(ah);	int i;	ahp->ah_nfCalHist.first_run = 1;		ahp->ah_nfCalHist.currIndex = 0;	ahp->ah_nfCalHist.privNF = AR5212_CCA_MAX_GOOD_VALUE;	ahp->ah_nfCalHist.invalidNFcount = AR512_NF_CAL_HIST_MAX;	for (i = 0; i < AR512_NF_CAL_HIST_MAX; i ++)		ahp->ah_nfCalHist.nfCalBuffer[i] = AR5212_CCA_MAX_GOOD_VALUE;}/* * Add a noise floor value to the ring buffer. */static __inline voidupdateNFHistBuff(struct ar5212NfCalHist *h, int16_t nf){ 	h->nfCalBuffer[h->currIndex] = nf;     	if (++h->currIndex >= AR512_NF_CAL_HIST_MAX)		h->currIndex = 0;}	/* * Return the median noise floor value in the ring buffer. */int16_t ar5212GetNfHistMid(const int16_t calData[AR512_NF_CAL_HIST_MAX]){	int16_t sort[AR512_NF_CAL_HIST_MAX];	int i, j;	OS_MEMCPY(sort, calData, AR512_NF_CAL_HIST_MAX*sizeof(int16_t));	for (i = 0; i < AR512_NF_CAL_HIST_MAX-1; i ++) {		for (j = 1; j < AR512_NF_CAL_HIST_MAX-i; j ++) {			if (sort[j] > sort[j-1]) {				int16_t nf = sort[j];				sort[j] = sort[j-1];				sort[j-1] = nf;			}		}	}	return sort[(AR512_NF_CAL_HIST_MAX-1)>>1];}/* * Read the NF and check it against the noise floor threshhold */int16_tar5212GetNf(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan){	struct ath_hal_5212 *ahp = AH5212(ah);	struct ar5212NfCalHist *h = &ahp->ah_nfCalHist;

⌨️ 快捷键说明

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