📄 ar5212_reset.c
字号:
/* Change the synth */ if (!ahp->ah_rfHal.setChannel(ah, ichan)) return AH_FALSE; /* * Wait for the frequency synth to settle (synth goes on via 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_DELAY; if (IS_CHAN_CCK(ichan)) synthDelay = (4 * data) / 22; else synthDelay = data / 10; OS_DELAY(synthDelay + BASE_ACTIVATE_DELAY); /* Setup the transmit power values. */ if (!AH_PRIVATE(ah)->ah_setTransmitPower(ah, ichan, rfXpdGain)) { HALDEBUG(ah, "%s: error init'ing transmit power\n", __func__); return AH_FALSE; } /* Release the RFBus Grant */ OS_REG_WRITE(ah, AR_PHY_RFBUS_REQ, 0); /* Start Noise Floor Cal */ OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF); /* Copy over internal channel flags to public hal channel */ if (!(ichan->channelFlags & CHANNEL_DFS)) ichan->privFlags &= ~CHANNEL_INTERFERENCE; chan->channelFlags = ichan->channelFlags; chan->privFlags = ichan->privFlags; chan->maxRegTxPower = ichan->maxRegTxPower; chan->maxTxPower = ichan->maxTxPower; chan->minTxPower = ichan->minTxPower; AH_PRIVATE(ah)->ah_curchan->ah_channel_time=0; AH_PRIVATE(ah)->ah_curchan->ah_tsf_last = ar5212GetTsf64(ah);#ifdef AH_SUPPORT_DFS if ((AH_PRIVATE(ah)->ah_opmode == HAL_M_HOSTAP) && (chan->channelFlags & CHANNEL_DFS)) { OS_REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_TOT_DES, -34); OS_REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1, AR_PHY_AGC_CTL1_COARSE_LOW, -52); OS_REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1, AR_PHY_AGC_CTL1_COARSE_HIGH, -18); OS_REG_RMW_FIELD(ah, AR_PHY_FIND_SIG, AR_PHY_FIND_SIG_FIRPWR, -70); /* Reset all ANI parameters now to a good value */#if 0 ar5212AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL, 0);#endif ar5212AniControl(ah, HAL_ANI_SPUR_IMMUNITY_LEVEL, 0); ar5212AniControl(ah, HAL_ANI_FIRSTEP_LEVEL, 0); ar5212AniControl(ah, HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION, HAL_ANI_USE_OFDM_WEAK_SIG); ar5212AniControl(ah, HAL_ANI_CCK_WEAK_SIGNAL_THR, !HAL_ANI_CCK_WEAK_SIG_THR); if ((chan->privFlags & CHANNEL_DFS_CLEAR) == 0) ar5212TxEnable(ah,AH_FALSE); } else#endif ar5212TxEnable(ah,AH_TRUE); return AH_TRUE;}voidar5212SetOperatingMode(struct ath_hal *ah, int opmode){ u_int32_t val; val = OS_REG_READ(ah, AR_STA_ID1); val &= ~(AR_STA_ID1_STA_AP | AR_STA_ID1_ADHOC); switch (opmode) { case HAL_M_HOSTAP: OS_REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_STA_AP | AR_STA_ID1_KSRCH_MODE); OS_REG_CLR_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION); break; case HAL_M_IBSS: OS_REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_ADHOC | AR_STA_ID1_KSRCH_MODE); OS_REG_SET_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION); break; case HAL_M_STA: case HAL_M_MONITOR: OS_REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_KSRCH_MODE); break; }}#ifdef AH_SUPPORT_XR/* * Configure XR mode support. */HAL_BOOLar5212SetXrMode(struct ath_hal *ah, HAL_OPMODE opmode,HAL_CHANNEL *chan){#define MAC_CLKS(_usec) (IS_CHAN_5GHZ(chan) ? (_usec) * 40 : (_usec) * 44) OS_REG_WRITE(ah, AR_XRMODE, (OS_REG_READ(ah, AR_XRMODE) &~ (AR_XRMODE_XR_POLL_TYPE|AR_XRMODE_XR_POLL_SUBTYPE)) | SM(FRAME_DATA, AR_XRMODE_XR_POLL_TYPE) | SM(SUBT_NODATA_CFPOLL, AR_XRMODE_XR_POLL_SUBTYPE) ); /* * Acks to XR frames require longer timeouts - we end * up increasing timeout corresponding to all types of * frames on the AP; the sta will anyway do XR frames * only; given by HW guys to be 100usec */ OS_REG_RMW_FIELD(ah, AR_TIME_OUT, AR_TIME_OUT_ACK, MAC_CLKS(100)); if (opmode == HAL_M_HOSTAP) { /* * timeout values on the AP side corresponding to * ctsChirp->xrData and grpPoll->rtsChirp; the former is * from the detection of the rtsChirp to the detection * of XR data - so a rtsChirp slot, a ctsChirp slot, * the XR data detection time and a fudge; the latter * i.e. the group poll timeout value depends on the * XR mode aifs and cwMin/Max in slot time units plus * time for a chirp and some fudge; the AP also needs * the slot delay to figure out the timing between * rtsChirp->ctsChirp */ OS_REG_WRITE(ah, AR_XRTO, (OS_REG_READ(ah, AR_XRTO) &~ (AR_XRTO_CHIRP_TO|AR_XRTO_POLL_TO)) | SM(MAC_CLKS(2 * XR_SLOT_DELAY + XR_DATA_DETECT_DELAY + 80), AR_XRTO_CHIRP_TO) | SM(MAC_CLKS((INIT_AIFS_XR + INIT_CWMAX_XR) * XR_SLOT_DELAY + XR_CHIRP_DUR + 16), AR_XRTO_POLL_TO) ); OS_REG_WRITE(ah, AR_XRDEL, (OS_REG_READ(ah, AR_XRDEL) &~ (AR_XRDEL_SLOT_DELAY)) | SM(MAC_CLKS(XR_SLOT_DELAY), AR_XRDEL_SLOT_DELAY)); } else { /* * used by the station to figure out timing between * end of rtsChirp->xrData; there is one ctsChirp * slot to be left in between - so two slots minus * the chirp duration and a fudge */ OS_REG_RMW_FIELD(ah, AR_XRDEL, AR_XRDEL_CHIRP_DATA_DELAY, MAC_CLKS(2 * XR_SLOT_DELAY - (XR_CHIRP_DUR + 1))); OS_REG_WRITE(ah, AR_D_GBL_IFS_SLOT, MAC_CLKS(XR_SLOT_DELAY)); OS_REG_WRITE(ah, AR_XRMODE, OS_REG_READ(ah, AR_XRMODE) | AR_XRMODE_XR_WAIT_FOR_POLL); } return AH_TRUE;#undef MAC_CLKS}#endif /* AH_SUPPORT_XR *//* * 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_BOOLar5212PhyDisable(struct ath_hal *ah){ return ar5212SetResetReg(ah, AR_RC_BB);}/* * Places all of hardware into reset */HAL_BOOLar5212Disable(struct ath_hal *ah){ 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){ struct ath_hal_5212 *ahp = AH5212(ah); 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 */ u_int32_t rfMode, phyPLL = 0, curPhyPLL, turbo; if (IS_5413(ah)) { 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_5112(ah) || IS_2413(ah)) { rfMode = AR_PHY_MODE_AR5112; if (IS_CHAN_CCK(chan) || IS_CHAN_G(chan)) { phyPLL = AR_PHY_PLL_CTL_44_5112; } else { if (IS_CHAN_HALF_RATE(chan)) { phyPLL = AR_PHY_PLL_CTL_40_5112_HALF; } else if (IS_CHAN_QUARTER_RATE(chan)) { phyPLL = AR_PHY_PLL_CTL_40_5112_QUARTER; } else { phyPLL = AR_PHY_PLL_CTL_40_5112; } } } else { rfMode = AR_PHY_MODE_AR5111; if (IS_CHAN_CCK(chan) || IS_CHAN_G(chan)) { phyPLL = AR_PHY_PLL_CTL_44; } else { if (IS_CHAN_HALF_RATE(chan)) { phyPLL = AR_PHY_PLL_CTL_40_HALF; } else if (IS_CHAN_QUARTER_RATE(chan)) { phyPLL = AR_PHY_PLL_CTL_40_QUARTER; } else { phyPLL = AR_PHY_PLL_CTL_40; } } } 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);#ifdef AH_SUPPORT_XR if (ahp->ah_xrEnable) { rfMode |= AR_PHY_MODE_XR; }#endif /* * 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_BOOLar5212PerCalibration(struct ath_hal *ah, HAL_CHANNEL *chan, HAL_BOOL *isIQdone){#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; u_int32_t powerMeasQ, powerMeasI; OS_MARK(ah, AH_MARK_PERCAL, chan->channel); *isIQdone = AH_FALSE; ichan = ath_hal_checkchannel(ah, chan); if (ichan == AH_NULL) { HALDEBUG(ah, "%s: invalid channel %u/0x%x; no mapping\n", __func__, chan->channel, chan->channelFlags); return AH_FALSE; }#ifdef AH_SUPPORT_DFS if (((ichan->channelFlags & CHANNEL_DFS) != 0) && ((ichan->privFlags & CHANNEL_INTERFERENCE) != 0)) { HALDEBUG(ah, "%s: invalid channel %u/0x%x; Radar detected on channel\n", __func__, chan->channel, chan->channelFlags); return AH_FALSE; }#endif /* XXX EAR */ if ((ahp->ah_bIQCalibration == IQ_CAL_DONE) || (ahp->ah_bIQCalibration == IQ_CAL_INACTIVE)) *isIQdone = 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; *isIQdone = AH_TRUE; /* workaround for misgated IQ Cal results */ for (i = 0; i < IQ_CAL_TRIES; i++) { /* 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); } /* * 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; }#ifdef CALIBRATION_DEBUG HALDEBUG(ah, "****************** MISGATED IQ CAL! *******************\n"); HALDEBUG(ah, "time = %d, i = %d, \n", OS_GETUPTIME(ah), i); HALDEBUG(ah, "powerMeasI = 0x%08x\n", powerMeasI); HALDEBUG(ah, "powerMeasQ = 0x%08x\n", powerMeasQ);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -