📄 ar5211_reset.c.svn-base
字号:
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 + -