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

📄 ar5211_reset.c

📁 最新之atheros芯片driver source code, 基于linux操作系统,內含atheros芯片HAL全部代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	if (opmode != HAL_M_HOSTAP &&	    (AH_PRIVATE(ah)->ah_11nCompat & HAL_DIAG_11N_SERVICES) != 0) {		/* NB: override the .ini setting */		OS_REG_RMW_FIELD(ah, AR_PHY_FRAME_CTL,			AR_PHY_FRAME_CTL_ERR_SERV,			MS(AH_PRIVATE(ah)->ah_11nCompat, HAL_DIAG_11N_SERVICES)&1);	}	/* Setup board specific options for EEPROM version 3 */	ar5211SetBoardValues(ah, chan);	if (!ar5211SetChannel(ah, ichan)) {		HALDEBUG(ah, HAL_DEBUG_ANY, "%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, ichan)) {		if (!IS_CHAN_CCK(chan))			chan->channelFlags |= CHANNEL_CW_INT;		HALDEBUG(ah, HAL_DEBUG_ANY,		    "%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)));	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));	/*	 * 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 (AH_PRIVATE(ah)->ah_rfkillEnabled)		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_sifstime != (u_int) -1)		ar5211SetSifsTime(ah, ahp->ah_sifstime);	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, HAL_DEBUG_RESET, "%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, uint16_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_BOOLar5211PerCalibrationN(struct ath_hal *ah,  HAL_CHANNEL *chan, u_int chainMask,	HAL_BOOL longCal, HAL_BOOL *isCalDone){	struct ath_hal_5211 *ahp = AH5211(ah);	HAL_CHANNEL_INTERNAL *ichan;	int32_t qCoff, qCoffDenom;	uint32_t data;	int32_t iqCorrMeas;	int32_t iCoff, iCoffDenom;	uint32_t powerMeasQ, powerMeasI;	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;	}	/* 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;			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 IQ */			data  = OS_REG_READ(ah, AR_PHY_TIMING_CTRL4) |				AR_PHY_TIMING_CTRL4_IQCORR_ENABLE |				(((uint32_t)iCoff) << AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF_S) |				((uint32_t)qCoff);			OS_REG_WRITE(ah, AR_PHY_TIMING_CTRL4, data);		}	}	*isCalDone = !ahp->ah_bIQCalibration;	if (longCal) {		/* Perform noise floor and set status */		if (!ar5211IsNfGood(ah, ichan)) {			/* report up and clear internal state */			chan->channelFlags |= CHANNEL_CW_INT;			ichan->channelFlags &= ~CHANNEL_CW_INT;			return AH_FALSE;		}		if (!ar5211CalNoiseFloor(ah, ichan)) {			/*			 * 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, ichan)) {				if (!IS_CHAN_CCK(chan))					chan->channelFlags |= CHANNEL_CW_INT;				return AH_FALSE;			}		}		ar5211RequestRfgain(ah);	}	return AH_TRUE;}HAL_BOOLar5211PerCalibration(struct ath_hal *ah, HAL_CHANNEL *chan, HAL_BOOL *isIQdone){	return ar5211PerCalibrationN(ah,  chan, 0x1, AH_TRUE, isIQdone);}HAL_BOOLar5211ResetCalValid(struct ath_hal *ah, HAL_CHANNEL *chan){	/* XXX */	return AH_TRUE;}/* * Writes the given reset bit mask into the reset register */static HAL_BOOLar5211SetResetReg(struct ath_hal *ah, uint32_t resetMask){	uint32_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){	uint32_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;}static int16_tar5211GetNoiseFloor(struct ath_hal *ah){	int16_t nf;	nf = (OS_REG_READ(ah, AR_PHY(25)) >> 19) & 0x1ff;	if (nf & 0x100)

⌨️ 快捷键说明

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