diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416.h b/sys/dev/ath/ath_hal/ar5416/ar5416.h index e6e339ec9096..deb2d20d1ce7 100644 --- a/sys/dev/ath/ath_hal/ar5416/ar5416.h +++ b/sys/dev/ath/ath_hal/ar5416/ar5416.h @@ -235,6 +235,8 @@ extern void ar5416GetTargetPowersLeg(struct ath_hal *ah, uint16_t numRates, HAL_BOOL isExtTarget); extern void ar5416InitChainMasks(struct ath_hal *ah); extern void ar5416RestoreChainMask(struct ath_hal *ah); +extern void ar5416EepromSetAddac(struct ath_hal *ah, + const struct ieee80211_channel *chan); /* TX power setup related routines in ar5416_reset.c */ extern void ar5416GetGainBoundariesAndPdadcs(struct ath_hal *ah, diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_attach.c b/sys/dev/ath/ath_hal/ar5416/ar5416_attach.c index 98d9c51c8e17..67ad0278af53 100644 --- a/sys/dev/ath/ath_hal/ar5416/ar5416_attach.c +++ b/sys/dev/ath/ath_hal/ar5416/ar5416_attach.c @@ -474,10 +474,11 @@ ar5416WriteIni(struct ath_hal *ah, const struct ieee80211_channel *chan) * Write addac shifts */ OS_REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_EXTERNAL_RADIO); -#if 0 + /* NB: only required for Sowl */ - ar5416EepromSetAddac(ah, chan); -#endif + if (AR_SREV_SOWL(ah)) + ar5416EepromSetAddac(ah, chan); + regWrites = ath_hal_ini_write(ah, &AH5416(ah)->ah_ini_addac, 1, regWrites); OS_REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_INTERNAL_ADDAC); diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_reset.c b/sys/dev/ath/ath_hal/ar5416/ar5416_reset.c index 5ac7fdc0f280..07c9daa40dca 100644 --- a/sys/dev/ath/ath_hal/ar5416/ar5416_reset.c +++ b/sys/dev/ath/ath_hal/ar5416/ar5416_reset.c @@ -2425,3 +2425,76 @@ ar5416OverrideIni(struct ath_hal *ah, const struct ieee80211_channel *chan) OS_REG_WRITE(ah, AR_PHY_HEAVY_CLIP_FACTOR_RIFS, val); } } + +struct ini { + uint32_t *data; /* NB: !const */ + int rows, cols; +}; + +/* + * Override XPA bias level based on operating frequency. + * This is a v14 EEPROM specific thing for the AR9160. + */ +void +ar5416EepromSetAddac(struct ath_hal *ah, const struct ieee80211_channel *chan) +{ +#define XPA_LVL_FREQ(cnt) (pModal->xpaBiasLvlFreq[cnt]) + MODAL_EEP_HEADER *pModal; + HAL_EEPROM_v14 *ee = AH_PRIVATE(ah)->ah_eeprom; + struct ar5416eeprom *eep = &ee->ee_base; + uint8_t biaslevel; + + if (! AR_SREV_SOWL(ah)) + return; + + if (EEP_MINOR(ah) < AR5416_EEP_MINOR_VER_7) + return; + + pModal = &(eep->modalHeader[IEEE80211_IS_CHAN_2GHZ(chan)]); + + if (pModal->xpaBiasLvl != 0xff) + biaslevel = pModal->xpaBiasLvl; + else { + uint16_t resetFreqBin, freqBin, freqCount = 0; + CHAN_CENTERS centers; + + ar5416GetChannelCenters(ah, chan, ¢ers); + + resetFreqBin = FREQ2FBIN(centers.synth_center, IEEE80211_IS_CHAN_2GHZ(chan)); + freqBin = XPA_LVL_FREQ(0) & 0xff; + biaslevel = (uint8_t) (XPA_LVL_FREQ(0) >> 14); + + freqCount++; + + while (freqCount < 3) { + if (XPA_LVL_FREQ(freqCount) == 0x0) + break; + + freqBin = XPA_LVL_FREQ(freqCount) & 0xff; + if (resetFreqBin >= freqBin) + biaslevel = (uint8_t)(XPA_LVL_FREQ(freqCount) >> 14); + else + break; + freqCount++; + } + } + + HALDEBUG(ah, HAL_DEBUG_EEPROM, "%s: overriding XPA bias level = %d\n", + __func__, biaslevel); + + /* + * This is a dirty workaround for the const initval data, + * which will upset multiple AR9160's on the same board. + * + * The HAL should likely just have a private copy of the addac + * data per instance. + */ + if (IEEE80211_IS_CHAN_2GHZ(chan)) + HAL_INI_VAL((struct ini *) &AH5416(ah)->ah_ini_addac, 7, 1) = + (HAL_INI_VAL(&AH5416(ah)->ah_ini_addac, 7, 1) & (~0x18)) | biaslevel << 3; + else + HAL_INI_VAL((struct ini *) &AH5416(ah)->ah_ini_addac, 6, 1) = + (HAL_INI_VAL(&AH5416(ah)->ah_ini_addac, 6, 1) & (~0xc0)) | biaslevel << 6; +#undef XPA_LVL_FREQ +} +