📄 ar5211_reset.c.svn-base
字号:
nf = 0 - ((nf ^ 0x1ff) + 1); return nf;}/* * Peform the noisefloor calibration for the length of time set * in runTime (valid values 1 to 7) * * Returns: The NF value at the end of the given time (or 0 for failure) */int16_tar5211RunNoiseFloor(struct ath_hal *ah, uint8_t runTime, int16_t startingNF){ int i, searchTime; HALASSERT(runTime <= 7); /* Setup noise floor run time and starting value */ OS_REG_WRITE(ah, AR_PHY(25), (OS_REG_READ(ah, AR_PHY(25)) & ~0xFFF) | ((runTime << 9) & 0xE00) | (startingNF & 0x1FF)); /* Calibrate the noise floor */ OS_REG_WRITE(ah, AR_PHY_AGC_CONTROL, OS_REG_READ(ah, AR_PHY_AGC_CONTROL) | AR_PHY_AGC_CONTROL_NF); /* Compute the required amount of searchTime needed to finish NF */ if (runTime == 0) { /* 8 search windows * 6.4us each */ searchTime = 8 * 7; } else { /* 512 * runtime search windows * 6.4us each */ searchTime = (runTime * 512) * 7; } /* * Do not read noise floor until it has been updated * * As a guesstimate - we may only get 1/60th the time on * the air to see search windows in a heavily congested * network (40 us every 2400 us of time) */ for (i = 0; i < 60; i++) { if ((OS_REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) == 0) break; OS_DELAY(searchTime); } if (i >= 60) { HALDEBUG(ah, HAL_DEBUG_NFCAL, "NF with runTime %d failed to end on channel %d\n", runTime, AH_PRIVATE(ah)->ah_curchan->channel); HALDEBUG(ah, HAL_DEBUG_NFCAL, " PHY NF Reg state: 0x%x\n", OS_REG_READ(ah, AR_PHY_AGC_CONTROL)); HALDEBUG(ah, HAL_DEBUG_NFCAL, " PHY Active Reg state: 0x%x\n", OS_REG_READ(ah, AR_PHY_ACTIVE)); return 0; } return ar5211GetNoiseFloor(ah);}static HAL_BOOLgetNoiseFloorThresh(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan, int16_t *nft){ HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; switch (chan->channelFlags & CHANNEL_ALL_NOTURBO) { case CHANNEL_A: *nft = ee->ee_noiseFloorThresh[0]; break; case CHANNEL_CCK|CHANNEL_2GHZ: *nft = ee->ee_noiseFloorThresh[1]; break; case CHANNEL_OFDM|CHANNEL_2GHZ: *nft = ee->ee_noiseFloorThresh[2]; break; default: HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n", __func__, chan->channelFlags); return AH_FALSE; } return AH_TRUE;}/* * Read the NF and check it against the noise floor threshhold * * Returns: TRUE if the NF is good */static HAL_BOOLar5211IsNfGood(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan){ int16_t nf, nfThresh; if (!getNoiseFloorThresh(ah, chan, &nfThresh)) return AH_FALSE; if (OS_REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) HALDEBUG(ah, HAL_DEBUG_ANY, "%s: NF did not complete in calibration window\n", __func__); nf = ar5211GetNoiseFloor(ah); if (nf > nfThresh) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: noise floor failed; detected %u, threshold %u\n", __func__, nf, nfThresh); /* * NB: Don't discriminate 2.4 vs 5Ghz, if this * happens it indicates a problem regardless * of the band. */ chan->channelFlags |= CHANNEL_CW_INT; } chan->rawNoiseFloor = nf; return (nf <= nfThresh);}/* * Peform the noisefloor calibration and check for any constant channel * interference. * * NOTE: preAR5211 have a lengthy carrier wave detection process - hence * it is if'ed for MKK regulatory domain only. * * Returns: TRUE for a successful noise floor calibration; else FALSE */HAL_BOOLar5211CalNoiseFloor(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan){#define N(a) (sizeof (a) / sizeof (a[0])) /* Check for Carrier Wave interference in MKK regulatory zone */ if (AH_PRIVATE(ah)->ah_macVersion < AR_SREV_VERSION_OAHU && ath_hal_getnfcheckrequired(ah, (HAL_CHANNEL *) chan)) { static const uint8_t runtime[3] = { 0, 2, 7 }; int16_t nf, nfThresh; int i; if (!getNoiseFloorThresh(ah, chan, &nfThresh)) return AH_FALSE; /* * Run a quick noise floor that will hopefully * complete (decrease delay time). */ for (i = 0; i < N(runtime); i++) { nf = ar5211RunNoiseFloor(ah, runtime[i], 0); if (nf > nfThresh) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: run failed with %u > threshold %u " "(runtime %u)\n", __func__, nf, nfThresh, runtime[i]); chan->rawNoiseFloor = 0; } else chan->rawNoiseFloor = nf; } return (i <= N(runtime)); } else { /* Calibrate the noise floor */ OS_REG_WRITE(ah, AR_PHY_AGC_CONTROL, OS_REG_READ(ah, AR_PHY_AGC_CONTROL) | AR_PHY_AGC_CONTROL_NF); } return AH_TRUE;#undef N}/* * Adjust NF based on statistical values for 5GHz frequencies. */int16_tar5211GetNfAdjust(struct ath_hal *ah, const HAL_CHANNEL_INTERNAL *c){ static const struct { uint16_t freqLow; int16_t adjust; } adjust5111[] = { { 5790, 11 }, /* NB: ordered high -> low */ { 5730, 10 }, { 5690, 9 }, { 5660, 8 }, { 5610, 7 }, { 5530, 5 }, { 5450, 4 }, { 5379, 2 }, { 5209, 0 }, /* XXX? bogus but doesn't matter */ { 0, 1 }, }; int i; for (i = 0; c->channel <= adjust5111[i].freqLow; i++) ; /* NB: placeholder for 5111's less severe requirement */ return adjust5111[i].adjust / 3;}/* * Reads EEPROM header info from device structure and programs * analog registers 6 and 7 * * REQUIRES: Access to the analog device */static HAL_BOOLar5211SetRf6and7(struct ath_hal *ah, HAL_CHANNEL *chan){#define N(a) (sizeof (a) / sizeof (a[0])) HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; struct ath_hal_5211 *ahp = AH5211(ah); uint16_t rfXpdGain, rfPloSel, rfPwdXpd; uint16_t tempOB, tempDB; uint16_t freqIndex; int i; freqIndex = (chan->channelFlags & CHANNEL_2GHZ) ? 2 : 1; /* * TODO: This array mode correspondes with the index used * during the read. * For readability, this should be changed to an enum or #define */ switch (chan->channelFlags & CHANNEL_ALL_NOTURBO) { case CHANNEL_A: if (chan->channel > 4000 && chan->channel < 5260) { tempOB = ee->ee_ob1; tempDB = ee->ee_db1; } else if (chan->channel >= 5260 && chan->channel < 5500) { tempOB = ee->ee_ob2; tempDB = ee->ee_db2; } else if (chan->channel >= 5500 && chan->channel < 5725) { tempOB = ee->ee_ob3; tempDB = ee->ee_db3; } else if (chan->channel >= 5725) { tempOB = ee->ee_ob4; tempDB = ee->ee_db4; } else { /* XXX panic?? */ tempOB = tempDB = 0; } rfXpdGain = ee->ee_xgain[0]; rfPloSel = ee->ee_xpd[0]; rfPwdXpd = !ee->ee_xpd[0]; ar5211Rf6n7[5][freqIndex] = (ar5211Rf6n7[5][freqIndex] & ~0x10000000) | (ee->ee_cornerCal.pd84<< 28); ar5211Rf6n7[6][freqIndex] = (ar5211Rf6n7[6][freqIndex] & ~0x04000000) | (ee->ee_cornerCal.pd90 << 26); ar5211Rf6n7[21][freqIndex] = (ar5211Rf6n7[21][freqIndex] & ~0x08) | (ee->ee_cornerCal.gSel << 3); break; case CHANNEL_CCK|CHANNEL_2GHZ: tempOB = ee->ee_obFor24; tempDB = ee->ee_dbFor24; rfXpdGain = ee->ee_xgain[1]; rfPloSel = ee->ee_xpd[1]; rfPwdXpd = !ee->ee_xpd[1]; break; case CHANNEL_OFDM|CHANNEL_2GHZ: tempOB = ee->ee_obFor24g; tempDB = ee->ee_dbFor24g; rfXpdGain = ee->ee_xgain[2]; rfPloSel = ee->ee_xpd[2]; rfPwdXpd = !ee->ee_xpd[2]; break; default: HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n", __func__, chan->channelFlags); return AH_FALSE; } HALASSERT(1 <= tempOB && tempOB <= 5); HALASSERT(1 <= tempDB && tempDB <= 5); /* Set rfXpdGain and rfPwdXpd */ ar5211Rf6n7[11][freqIndex] = (ar5211Rf6n7[11][freqIndex] & ~0xC0) | (((ath_hal_reverseBits(rfXpdGain, 4) << 7) | (rfPwdXpd << 6)) & 0xC0); ar5211Rf6n7[12][freqIndex] = (ar5211Rf6n7[12][freqIndex] & ~0x07) | ((ath_hal_reverseBits(rfXpdGain, 4) >> 1) & 0x07); /* Set OB */ ar5211Rf6n7[12][freqIndex] = (ar5211Rf6n7[12][freqIndex] & ~0x80) | ((ath_hal_reverseBits(tempOB, 3) << 7) & 0x80); ar5211Rf6n7[13][freqIndex] = (ar5211Rf6n7[13][freqIndex] & ~0x03) | ((ath_hal_reverseBits(tempOB, 3) >> 1) & 0x03); /* Set DB */ ar5211Rf6n7[13][freqIndex] = (ar5211Rf6n7[13][freqIndex] & ~0x1C) | ((ath_hal_reverseBits(tempDB, 3) << 2) & 0x1C); /* Set rfPloSel */ ar5211Rf6n7[17][freqIndex] = (ar5211Rf6n7[17][freqIndex] & ~0x08) | ((rfPloSel << 3) & 0x08); /* Write the Rf registers 6 & 7 */ for (i = 0; i < N(ar5211Rf6n7); i++) OS_REG_WRITE(ah, ar5211Rf6n7[i][0], ar5211Rf6n7[i][freqIndex]); /* Now that we have reprogrammed rfgain value, clear the flag. */ ahp->ah_rfgainState = RFGAIN_INACTIVE; return AH_TRUE;#undef N}HAL_BOOLar5211SetAntennaSwitchInternal(struct ath_hal *ah, HAL_ANT_SETTING settings, const HAL_CHANNEL *chan){#define ANT_SWITCH_TABLE1 0x9960#define ANT_SWITCH_TABLE2 0x9964 HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; struct ath_hal_5211 *ahp = AH5211(ah); uint32_t antSwitchA, antSwitchB; int ix; switch (chan->channelFlags & CHANNEL_ALL_NOTURBO) { case CHANNEL_A: ix = 0; break; case CHANNEL_B: ix = 1; break; case CHANNEL_PUREG: ix = 2; break; default: HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n", __func__, chan->channelFlags); return AH_FALSE; } antSwitchA = ee->ee_antennaControl[1][ix] | (ee->ee_antennaControl[2][ix] << 6) | (ee->ee_antennaControl[3][ix] << 12) | (ee->ee_antennaControl[4][ix] << 18) | (ee->ee_antennaControl[5][ix] << 24) ; antSwitchB = ee->ee_antennaControl[6][ix] | (ee->ee_antennaControl[7][ix] << 6) | (ee->ee_antennaControl[8][ix] << 12) | (ee->ee_antennaControl[9][ix] << 18) | (ee->ee_antennaControl[10][ix] << 24) ; /* * For fixed antenna, give the same setting for both switch banks */ switch (settings) { case HAL_ANT_FIXED_A: antSwitchB = antSwitchA; break; case HAL_ANT_FIXED_B: antSwitchA = antSwitchB; break; case HAL_ANT_VARIABLE: break; default: HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad antenna setting %u\n", __func__, settings); return AH_FALSE; } ahp->ah_diversityControl = settings; OS_REG_WRITE(ah, ANT_SWITCH_TABLE1, antSwitchA); OS_REG_WRITE(ah, ANT_SWITCH_TABLE2, antSwitchB); return AH_TRUE;#undef ANT_SWITCH_TABLE1#undef ANT_SWITCH_TABLE2}/* * Reads EEPROM header info and programs the device for correct operation * given the channel value */static HAL_BOOLar5211SetBoardValues(struct ath_hal *ah, HAL_CHANNEL *chan){ HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; struct ath_hal_5211 *ahp = AH5211(ah); int arrayMode, falseDectectBackoff; switch (chan->channelFlags & CHANNEL_ALL_NOTURBO) { case CHANNEL_A: arrayMode = 0; OS_REG_RMW_FIELD(ah, AR_PHY_FRAME_CTL, AR_PHY_FRAME_CTL_TX_CLIP, ee->ee_cornerCal.clip); break; case CHANNEL_CCK|CHANNEL_2GHZ: arrayMode = 1; break; case CHANNEL_OFDM|CHANNEL_2GHZ: arrayMode = 2; break; default: HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n", __func__, chan->channelFlags); return AH_FALSE; } /* Set the antenna register(s) correctly for the chip revision */ if (AH_PRIVATE(ah)->ah_macVersion < AR_SREV_VERSION_OAHU) { OS_REG_WRITE(ah, AR_PHY(68), (OS_REG_READ(ah, AR_PHY(68)) & 0xFFFFFFFC) | 0x3); } else { OS_REG_WRITE(ah, AR_PHY(68), (OS_REG_READ(ah, AR_PHY(68)) & 0xFFFFFC06) | (ee->ee_antennaControl[0][arrayMode] << 4) | 0x1); ar5211SetAntennaSwitchInternal(ah, ahp->ah_diversityControl, chan); /* Set the Noise Floor Thresh on ar5211 devices */ OS_REG_WRITE(ah, AR_PHY_BASE + (90 << 2), (ee->ee_noiseFloorThresh[arrayMode] & 0x1FF) | (1<<9)); } OS_REG_WRITE(ah, AR_PHY_BASE + (17 << 2), (OS_REG_READ(ah, AR_PHY_BASE + (17 << 2)) & 0xFFFFC07F) | ((ee->ee_switchSettling[arrayMode] << 7) & 0x3F80)); OS_REG_WRITE(ah, AR_PHY_BASE + (18 << 2), (OS_REG_READ(ah, AR_PHY_BASE + (18 << 2)) & 0xFFFC0FFF) | ((ee->ee_txrxAtten[arrayMode] << 12) & 0x3F000)); OS_REG_WRITE(ah, AR_PHY_BASE + (20 << 2), (OS_REG_READ(ah, AR_PHY_BASE + (20 << 2)) & 0xFFFF0000) | ((ee->ee_pgaDesiredSize[arrayMode] << 8) & 0xFF00) | (ee->ee_adcDesiredSize[arrayMode] & 0x00FF)); OS_REG_WRITE(ah, AR_PHY_BASE + (13 << 2), (ee->ee_txEndToXPAOff[arrayMode] << 24) | (ee->ee_txEndToXPAOff[arrayMode] << 16) | (ee->ee_txFrameToXPAOn[arrayMode] << 8) | ee->ee_txFrameToXPAOn[arrayMode]); OS_REG_WRITE(ah, AR_PHY_BASE + (10 << 2), (OS_REG_READ(ah, AR_PHY_BASE + (10 << 2)) & 0xFFFF00FF) | (ee->ee_txEndToXLNAOn[arrayMode] << 8)); OS_REG_WRITE(ah, AR_PHY_BASE + (25 << 2),
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -