📄 ar5312_reset.c.svn-base
字号:
* extra BASE_ACTIVATE_DELAY usecs to ensure this condition * does not happen. */ if (IS_CHAN_HALF_RATE(AH_PRIVATE(ah)->ah_curchan)) { OS_DELAY((synthDelay << 1) + BASE_ACTIVATE_DELAY); } else if (IS_CHAN_QUARTER_RATE(AH_PRIVATE(ah)->ah_curchan)) { OS_DELAY((synthDelay << 2) + BASE_ACTIVATE_DELAY); } else { OS_DELAY(synthDelay + BASE_ACTIVATE_DELAY); } /* * The udelay method is not reliable with notebooks. * Need to check to see if the baseband is ready */ testReg = OS_REG_READ(ah, AR_PHY_TESTCTRL); /* Selects the Tx hold */ OS_REG_WRITE(ah, AR_PHY_TESTCTRL, AR_PHY_TESTCTRL_TXHOLD); i = 0; while ((i++ < 20) && (OS_REG_READ(ah, 0x9c24) & 0x10)) /* test if baseband not ready */ OS_DELAY(200); OS_REG_WRITE(ah, AR_PHY_TESTCTRL, testReg); /* Calibrate the AGC and start a NF calculation */ OS_REG_WRITE(ah, AR_PHY_AGC_CONTROL, OS_REG_READ(ah, AR_PHY_AGC_CONTROL) | AR_PHY_AGC_CONTROL_CAL | AR_PHY_AGC_CONTROL_NF); if (!IS_CHAN_B(chan) && ahp->ah_bIQCalibration != IQ_CAL_DONE) { /* Start IQ calibration w/ 2^(INIT_IQCAL_LOG_COUNT_MAX+1) samples */ 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; } else ahp->ah_bIQCalibration = IQ_CAL_INACTIVE; /* Setup compression registers */ ar5212SetCompRegs(ah); /* Set 1:1 QCU to DCU mapping for all queues */ for (i = 0; i < AR_NUM_DCU; i++) OS_REG_WRITE(ah, AR_DQCUMASK(i), 1 << i); ahp->ah_intrTxqs = 0; for (i = 0; i < AH_PRIVATE(ah)->ah_caps.halTotalQueues; i++) ar5212ResetTxQueue(ah, i); /* * Setup interrupt handling. Note that ar5212ResetTxQueue * manipulates the secondary IMR's as queues are enabled * and disabled. This is done with RMW ops to insure the * settings we make here are preserved. */ ahp->ah_maskReg = AR_IMR_TXOK | AR_IMR_TXERR | AR_IMR_TXURN | AR_IMR_RXOK | AR_IMR_RXERR | AR_IMR_RXORN | AR_IMR_HIUERR ; if (opmode == HAL_M_HOSTAP) ahp->ah_maskReg |= AR_IMR_MIB; OS_REG_WRITE(ah, AR_IMR, ahp->ah_maskReg); /* Enable bus errors that are OR'd to set the HIUERR bit */ 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); if (AH_PRIVATE(ah)->ah_rfkillEnabled) ar5212EnableRfKill(ah); if (!ath_hal_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, 0)) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: offset calibration failed to complete in 1ms;" " noisy environment?\n", __func__); } /* * Set clocks back to 32kHz if they had been using refClk, then * use an external 32kHz crystal when sleeping, if one exists. */ ar5312SetupClock(ah, opmode); /* * 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))); /* XXX Setup post reset EAR additions */ /* QoS support */ if (AH_PRIVATE(ah)->ah_macVersion > AR_SREV_VERSION_VENICE || (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_VERSION_VENICE && AH_PRIVATE(ah)->ah_macRev >= AR_SREV_GRIFFIN_LITE)) { OS_REG_WRITE(ah, AR_QOS_CONTROL, 0x100aa); /* XXX magic */ OS_REG_WRITE(ah, AR_QOS_SELECT, 0x3210); /* XXX magic */ } /* Turn on NOACK Support for QoS packets */ OS_REG_WRITE(ah, AR_NOACK, SM(2, AR_NOACK_2BIT_VALUE) | SM(5, AR_NOACK_BIT_OFFSET) | SM(0, AR_NOACK_BYTE_OFFSET)); /* Restore user-specified settings */ if (ahp->ah_miscMode != 0) OS_REG_WRITE(ah, AR_MISC_MODE, ahp->ah_miscMode); if (ahp->ah_slottime != (u_int) -1) ar5212SetSlotTime(ah, ahp->ah_slottime); if (ahp->ah_acktimeout != (u_int) -1) ar5212SetAckTimeout(ah, ahp->ah_acktimeout); if (ahp->ah_ctstimeout != (u_int) -1) ar5212SetCTSTimeout(ah, ahp->ah_ctstimeout); if (ahp->ah_sifstime != (u_int) -1) ar5212SetSifsTime(ah, ahp->ah_sifstime); 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 */ if (bChannelChange) { if (!(ichan->privFlags & CHANNEL_DFS)) ichan->privFlags &= ~CHANNEL_INTERFERENCE; chan->channelFlags = ichan->channelFlags; chan->privFlags = ichan->privFlags; } HALDEBUG(ah, HAL_DEBUG_RESET, "%s: done\n", __func__); OS_MARK(ah, AH_MARK_RESET_DONE, 0); return AH_TRUE;bad: OS_MARK(ah, AH_MARK_RESET_DONE, ecode); 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_BOOLar5312PhyDisable(struct ath_hal *ah){ return ar5312SetResetReg(ah, AR_RC_BB);}/* * Places all of hardware into reset */HAL_BOOLar5312Disable(struct ath_hal *ah){ if (!ar5312SetPowerMode(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 ar5312SetResetReg(ah, AR_RC_MAC | AR_RC_BB);}/* * 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_BOOLar5312ChipReset(struct ath_hal *ah, HAL_CHANNEL *chan){ OS_MARK(ah, AH_MARK_CHIPRESET, chan ? chan->channel : 0); /* * Reset the HW */ if (!ar5312SetResetReg(ah, AR_RC_MAC | AR_RC_BB)) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: ar5312SetResetReg failed\n", __func__); return AH_FALSE; } /* Bring out of sleep mode (AGAIN) */ if (!ar5312SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: ar5312SetPowerMode failed\n", __func__); return AH_FALSE; } /* Clear warm reset register */ if (!ar5312SetResetReg(ah, 0)) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: ar5312SetResetReg failed\n", __func__); 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_RAD5112_ANY(ah)) { rfMode = AR_PHY_MODE_AR5112; if (!IS_5315(ah)) { if (IS_CHAN_CCK(chan) || IS_CHAN_G(chan)) { phyPLL = AR_PHY_PLL_CTL_44_5312; } else { if (IS_CHAN_HALF_RATE(chan)) { phyPLL = AR_PHY_PLL_CTL_40_5312_HALF; } else if (IS_CHAN_QUARTER_RATE(chan)) { phyPLL = AR_PHY_PLL_CTL_40_5312_QUARTER; } else { phyPLL = AR_PHY_PLL_CTL_40_5312; } } } else { 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; } } else { 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; } 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;}/* * Write the given reset bit mask into the reset register */static HAL_BOOLar5312SetResetReg(struct ath_hal *ah, uint32_t resetMask){ uint32_t mask = resetMask ? resetMask : ~0; HAL_BOOL rt; if ((rt = ar5312MacReset(ah, mask)) == AH_FALSE) { return rt; } if ((resetMask & AR_RC_MAC) == 0) { if (isBigEndian()) { /* * Set CFG, little-endian for register * and descriptor accesses. */#ifdef AH_NEED_DESC_SWAP mask = INIT_CONFIG_STATUS | AR_CFG_SWRD;#else mask = INIT_CONFIG_STATUS | AR_CFG_SWTD | AR_CFG_SWRD;#endif OS_REG_WRITE(ah, AR_CFG, mask); } else OS_REG_WRITE(ah, AR_CFG, INIT_CONFIG_STATUS); } return rt;}/* * ar5312MacReset resets (and then un-resets) the specified * wireless components. * Note: The RCMask cannot be zero on entering from ar5312SetResetReg. */HAL_BOOLar5312MacReset(struct ath_hal *ah, unsigned int RCMask){ int wlanNum = AR5312_UNIT(ah); uint32_t resetBB, resetBits, regMask; uint32_t reg; if (RCMask == 0) return(AH_FALSE);#if ( AH_SUPPORT_2316 || AH_SUPPORT_2317 ) if (IS_5315(ah)) { switch(wlanNum) { case 0: resetBB = AR5315_RC_BB0_CRES | AR5315_RC_WBB0_RES; /* Warm and cold reset bits for wbb */ resetBits = AR5315_RC_WMAC0_RES; break; case 1: resetBB = AR5315_RC_BB1_CRES | AR5315_RC_WBB1_RES; /* Warm and cold reset bits for wbb */ resetBits = AR5315_RC_WMAC1_RES; break; default: return(AH_FALSE); } regMask = ~(resetBB | resetBits); /* read before */ reg = OS_REG_READ(ah, (AR5315_RSTIMER_BASE - ((uint32_t) ah->ah_sh) + AR5315_RESET)); if (RCMask == AR_RC_BB) { /* Put baseband in reset */ reg |= resetBB; /* Cold and warm reset the baseband bits */ } else { /* * Reset the MAC and baseband. This is a bit different than * the PCI version, but holding in reset causes problems. */ reg &= regMask; reg |= (resetBits | resetBB) ; } OS_REG_WRITE(ah, (AR5315_RSTIMER_BASE - ((uint32_t) ah->ah_sh)+AR5315_RESET), reg); /* read after */ OS_REG_READ(ah, (AR5315_RSTIMER_BASE - ((uint32_t) ah->ah_sh) +AR5315_RESET)); OS_DELAY(100); /* Bring MAC and baseband out of reset */ reg &= regMask; /* read before */ OS_REG_READ(ah, (AR5315_RSTIMER_BASE- ((uint32_t) ah->ah_sh) +AR5315_RESET)); OS_REG_WRITE(ah, (AR5315_RSTIMER_BASE - ((uint32_t) ah->ah_sh)+AR5315_RESET), reg); /* read after */ OS_REG_READ(ah, (AR5315_RSTIMER_BASE- ((uint32_t) ah->ah_sh) +AR5315_RESET)); } else #endif { switch(wlanNum) { case 0: resetBB = AR5312_RC_BB0_CRES | AR5312_RC_WBB0_RES; /* Warm and cold reset bits for wbb */ resetBits = AR5312_RC_WMAC0_RES; break; case 1: resetBB = AR5312_RC_BB1_CRES | AR5312_RC_WBB1_RES; /* Warm and cold reset bits for wbb */ resetBits = AR5312_RC_WMAC1_RES; break; default: return(AH_FALSE); } regMask = ~(resetBB | resetBits); /* read before */ reg = OS_REG_READ(ah, (AR5312_RSTIMER_BASE - ((uint32_t) ah->ah_sh) + AR5312_RESET)); if (RCMask == AR_RC_BB) { /* Put baseband in reset */ reg |= resetBB; /* Cold and warm reset the baseband bits */ } else { /* * Reset the MAC and baseband. This is a bit different than * the PCI version, but holding in reset causes problems. */ reg &= regMask; reg |= (resetBits | resetBB) ; } OS_REG_WRITE(ah, (AR5312_RSTIMER_BASE - ((uint32_t) ah->ah_sh)+AR5312_RESET), reg); /* read after */ OS_REG_READ(ah, (AR5312_RSTIMER_BASE - ((uint32_t) ah->ah_sh) +AR5312_RESET)); OS_DELAY(100); /* Bring MAC and baseband out of reset */ reg &= regMask; /* read before */ OS_REG_READ(ah, (AR5312_RSTIMER_BASE- ((uint32_t) ah->ah_sh) +AR5312_RESET)); OS_REG_WRITE(ah, (AR5312_RSTIMER_BASE - ((uint32_t) ah->ah_sh)+AR5312_RESET), reg); /* read after */ OS_REG_READ(ah, (AR5312_RSTIMER_BASE- ((uint32_t) ah->ah_sh) +AR5312_RESET)); } return(AH_TRUE);}#endif /* AH_SUPPORT_AR5312 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -