Date: Thu, 26 May 2011 14:29:05 +0000 (UTC) From: Adrian Chadd <adrian@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r222308 - head/sys/dev/ath/ath_hal/ar9002 Message-ID: <201105261429.p4QET5Im068248@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: adrian Date: Thu May 26 14:29:05 2011 New Revision: 222308 URL: http://svn.freebsd.org/changeset/base/222308 Log: Flesh out the TX power calibration for the AR9287. I'm assuming for now that the AR9287 is only open-loop TX power control (as mine is) so I've hard-coded the attach path to fail if the NIC is not open-loop. This greatly simplifies the TX calibration path and the amount of code which needs to be ported over. This still isn't complete - the rate calculation code still needs to be ported and it all needs to be glued together. Obtained from: Linux ath9k Modified: head/sys/dev/ath/ath_hal/ar9002/ar9287_attach.c head/sys/dev/ath/ath_hal/ar9002/ar9287_olc.c head/sys/dev/ath/ath_hal/ar9002/ar9287_olc.h head/sys/dev/ath/ath_hal/ar9002/ar9287_reset.c Modified: head/sys/dev/ath/ath_hal/ar9002/ar9287_attach.c ============================================================================== --- head/sys/dev/ath/ath_hal/ar9002/ar9287_attach.c Thu May 26 13:54:07 2011 (r222307) +++ head/sys/dev/ath/ath_hal/ar9002/ar9287_attach.c Thu May 26 14:29:05 2011 (r222308) @@ -276,6 +276,17 @@ ar9287Attach(uint16_t devid, HAL_SOFTC s goto bad; } + /* + * We only implement open-loop TX power control + * for the AR9287 in this codebase. + */ + if (! ath_hal_eepromGetFlag(ah, AR_EEP_OL_PWRCTRL)) { + ath_hal_printf(ah, "[ath] AR9287 w/ closed-loop TX power control" + " isn't supported.\n"); + ecode = HAL_ENOTSUPP; + goto bad; + } + /* * Check whether the power table offset isn't the default. * This can occur with eeprom minor V21 or greater on Merlin. Modified: head/sys/dev/ath/ath_hal/ar9002/ar9287_olc.c ============================================================================== --- head/sys/dev/ath/ath_hal/ar9002/ar9287_olc.c Thu May 26 13:54:07 2011 (r222307) +++ head/sys/dev/ath/ath_hal/ar9002/ar9287_olc.c Thu May 26 14:29:05 2011 (r222308) @@ -30,6 +30,7 @@ #include "ah_internal.h" #include "ah_eeprom_v14.h" +#include "ah_eeprom_9287.h" #include "ar9002/ar9280.h" #include "ar5416/ar5416reg.h" @@ -92,3 +93,74 @@ ar9287olcTemperatureCompensation(struct AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, delta); } } + +void +ar9287olcGetTxGainIndex(struct ath_hal *ah, + const struct ieee80211_channel *chan, + struct cal_data_op_loop_ar9287 *pRawDatasetOpLoop, + uint8_t *pCalChans, uint16_t availPiers, int8_t *pPwr) +{ + uint16_t idxL = 0, idxR = 0, numPiers; + HAL_BOOL match; + CHAN_CENTERS centers; + + ar5416GetChannelCenters(ah, chan, ¢ers); + + for (numPiers = 0; numPiers < availPiers; numPiers++) { + if (pCalChans[numPiers] == AR5416_BCHAN_UNUSED) + break; + } + + match = ath_ee_getLowerUpperIndex( + (uint8_t)FREQ2FBIN(centers.synth_center, IEEE80211_IS_CHAN_2GHZ(chan)), + pCalChans, numPiers, &idxL, &idxR); + + if (match) { + *pPwr = (int8_t) pRawDatasetOpLoop[idxL].pwrPdg[0][0]; + } else { + *pPwr = ((int8_t) pRawDatasetOpLoop[idxL].pwrPdg[0][0] + + (int8_t) pRawDatasetOpLoop[idxR].pwrPdg[0][0])/2; + } +} + +void +ar9287olcSetPDADCs(struct ath_hal *ah, int32_t txPower, + uint16_t chain) +{ + uint32_t tmpVal; + uint32_t a; + + /* Enable OLPC for chain 0 */ + + tmpVal = OS_REG_READ(ah, 0xa270); + tmpVal = tmpVal & 0xFCFFFFFF; + tmpVal = tmpVal | (0x3 << 24); + OS_REG_WRITE(ah, 0xa270, tmpVal); + + /* Enable OLPC for chain 1 */ + + tmpVal = OS_REG_READ(ah, 0xb270); + tmpVal = tmpVal & 0xFCFFFFFF; + tmpVal = tmpVal | (0x3 << 24); + OS_REG_WRITE(ah, 0xb270, tmpVal); + + /* Write the OLPC ref power for chain 0 */ + + if (chain == 0) { + tmpVal = OS_REG_READ(ah, 0xa398); + tmpVal = tmpVal & 0xff00ffff; + a = (txPower)&0xff; + tmpVal = tmpVal | (a << 16); + OS_REG_WRITE(ah, 0xa398, tmpVal); + } + + /* Write the OLPC ref power for chain 1 */ + + if (chain == 1) { + tmpVal = OS_REG_READ(ah, 0xb398); + tmpVal = tmpVal & 0xff00ffff; + a = (txPower)&0xff; + tmpVal = tmpVal | (a << 16); + OS_REG_WRITE(ah, 0xb398, tmpVal); + } +} Modified: head/sys/dev/ath/ath_hal/ar9002/ar9287_olc.h ============================================================================== --- head/sys/dev/ath/ath_hal/ar9002/ar9287_olc.h Thu May 26 13:54:07 2011 (r222307) +++ head/sys/dev/ath/ath_hal/ar9002/ar9287_olc.h Thu May 26 14:29:05 2011 (r222308) @@ -21,5 +21,11 @@ extern void ar9287olcInit(struct ath_hal *ah); extern void ar9287olcTemperatureCompensation(struct ath_hal *ah); +extern void ar9287olcGetTxGainIndex(struct ath_hal *ah, + const struct ieee80211_channel *chan, + struct cal_data_op_loop_ar9287 *pRawDatasetOpLoop, + uint8_t *pCalChans, uint16_t availPiers, int8_t *pPwr); +extern void ar9287olcSetPDADCs(struct ath_hal *ah, + int32_t txPower, uint16_t chain); #endif /* __AR9287_OLC_H__ */ Modified: head/sys/dev/ath/ath_hal/ar9002/ar9287_reset.c ============================================================================== --- head/sys/dev/ath/ath_hal/ar9002/ar9287_reset.c Thu May 26 13:54:07 2011 (r222307) +++ head/sys/dev/ath/ath_hal/ar9002/ar9287_reset.c Thu May 26 14:29:05 2011 (r222308) @@ -33,13 +33,103 @@ #include "ar9002/ar9287phy.h" #include "ar9002/ar9287an.h" +#include "ar9002/ar9287_olc.h" #include "ar9002/ar9287_reset.h" +/* + * Set the TX power calibration table per-chain. + * + * This only supports open-loop TX power control for the AR9287. + */ +static void +ar9287SetPowerCalTable(struct ath_hal *ah, + const struct ieee80211_channel *chan, int16_t *pTxPowerIndexOffset) +{ + struct cal_data_op_loop_ar9287 *pRawDatasetOpenLoop; + uint8_t *pCalBChans = NULL; + uint16_t pdGainOverlap_t2; + uint16_t numPiers = 0, i; + uint16_t numXpdGain, xpdMask; + uint16_t xpdGainValues[AR5416_NUM_PD_GAINS] = {0, 0, 0, 0}; + uint32_t regChainOffset; + HAL_EEPROM_9287 *ee = AH_PRIVATE(ah)->ah_eeprom; + struct ar9287_eeprom *pEepData = &ee->ee_base; + + xpdMask = pEepData->modalHeader.xpdGain; + + if ((pEepData->baseEepHeader.version & AR9287_EEP_VER_MINOR_MASK) >= + AR9287_EEP_MINOR_VER_2) + pdGainOverlap_t2 = pEepData->modalHeader.pdGainOverlap; + else + pdGainOverlap_t2 = (uint16_t)(MS(OS_REG_READ(ah, AR_PHY_TPCRG5), + AR_PHY_TPCRG5_PD_GAIN_OVERLAP)); + + /* Note: Kiwi should only be 2ghz.. */ + if (IEEE80211_IS_CHAN_2GHZ(chan)) { + pCalBChans = pEepData->calFreqPier2G; + numPiers = AR9287_NUM_2G_CAL_PIERS; + pRawDatasetOpenLoop = (struct cal_data_op_loop_ar9287 *)pEepData->calPierData2G[0]; + AH5416(ah)->initPDADC = pRawDatasetOpenLoop->vpdPdg[0][0]; + } + numXpdGain = 0; + + /* Calculate the value of xpdgains from the xpdGain Mask */ + for (i = 1; i <= AR5416_PD_GAINS_IN_MASK; i++) { + if ((xpdMask >> (AR5416_PD_GAINS_IN_MASK - i)) & 1) { + if (numXpdGain >= AR5416_NUM_PD_GAINS) + break; + xpdGainValues[numXpdGain] = + (uint16_t)(AR5416_PD_GAINS_IN_MASK-i); + numXpdGain++; + } + } + + OS_REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN, + (numXpdGain - 1) & 0x3); + OS_REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_1, + xpdGainValues[0]); + OS_REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_2, + xpdGainValues[1]); + OS_REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3, + xpdGainValues[2]); + + for (i = 0; i < AR9287_MAX_CHAINS; i++) { + regChainOffset = i * 0x1000; + + if (pEepData->baseEepHeader.txMask & (1 << i)) { + int8_t txPower; + pRawDatasetOpenLoop = + (struct cal_data_op_loop_ar9287 *)pEepData->calPierData2G[i]; + ar9287olcGetTxGainIndex(ah, chan, + pRawDatasetOpenLoop, + pCalBChans, numPiers, + &txPower); + ar9287olcSetPDADCs(ah, txPower, i); + } + } + + *pTxPowerIndexOffset = 0; +} + HAL_BOOL ar9287SetTransmitPower(struct ath_hal *ah, const struct ieee80211_channel *chan, uint16_t *rfXpdGain) { + int16_t txPowerIndexOffset = 0; + /* XXX TODO */ + + /* Fetch per-rate power table for the given channel */ + + /* Set open-loop TX power control calibration */ + ar9287SetPowerCalTable(ah, chan, &txPowerIndexOffset); + + /* Calculate regulatory maximum power level */ + + /* Kiwi TX power starts at -5 dBm */ + + /* Write TX power registers */ + return AH_TRUE; }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201105261429.p4QET5Im068248>