📄 ar5212_eeprom.c
字号:
/* * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting * Copyright (c) 2002-2005 Atheros Communications, Inc. * All rights reserved. * * $Id: ar5212_eeprom.c,v 1.2 2006/10/13 07:10:49 steven Exp $ */#include "opt_ah.h"#ifdef AH_SUPPORT_AR5212#include "ah.h"#include "ah_internal.h"#include "ah_devid.h"#ifdef AH_DEBUG#include "ah_desc.h" /* NB: for HAL_PHYERR* */#endif#include "ah_eeprom.h"#include "ar5212/ar5212.h"#include "ar5212/ar5212reg.h"#include "ar5212/ar5212phy.h"#ifdef AH_SUPPORT_AR5311#include "ar5212/ar5311reg.h"#endifstatic HAL_BOOL ar5212IsSpurChannel(struct ath_hal *ah, HAL_CHANNEL *chan);static HAL_BOOL ar5212SetBoardValues(struct ath_hal *, HAL_CHANNEL_INTERNAL *);#ifdef AH_SUPPORT_WRITE_EEPROMstatic HAL_BOOL ar5212EepromWrite(struct ath_hal *ah, u_int off, u_int16_t data);#endif static HAL_BOOL ar5212EepromRead(struct ath_hal *ah, u_int off, u_int16_t *data);static u_int16_t ar5212EepromGetSpurChan(struct ath_hal *ah, u_int16_t spurChan,HAL_BOOL is2GHz);HAL_BOOL ar5212SetTransmitPower(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan, u_int16_t *rfXpdGain);static HAL_BOOL ar5212SetRateTable(struct ath_hal *ah, HAL_CHANNEL *chan, int16_t tpcScaleReduction, int16_t powerLimit, HAL_BOOL commit, int16_t *pMinPower, int16_t *pMaxPower);static void ar5212CorrectGainDelta(struct ath_hal *, int twiceOfdmCckDelta);static u_int16_t ar5212GetMaxEdgePower(u_int16_t channel, RD_EDGES_POWER *pRdEdgesPower);static u_int16_t interpolate(u_int16_t target, u_int16_t srcLeft, u_int16_t srcRight, u_int16_t targetLeft, u_int16_t targetRight);static void ar5212GetTargetPowers(struct ath_hal *ah, HAL_CHANNEL *chan, TRGT_POWER_INFO *powInfo, u_int16_t numChannels, TRGT_POWER_INFO *pNewPower);void ar5212GetLowerUpperValues(u_int16_t v, u_int16_t *lp, u_int16_t listSize, u_int16_t *vlo, u_int16_t *vhi);static HAL_BOOL ar5212GetChipPowerLimits(struct ath_hal *ah, HAL_CHANNEL *chans, u_int32_t nchans);static HAL_BOOL ar5212GetEepromCapabilityInfo(struct ath_hal *ah, u_int16_t *capField);static HAL_STATUS ar5212EepromDetach(struct ath_hal *ah);static HAL_BOOL ar5212GetEepromNoiseFloorThresh(struct ath_hal *ah, const HAL_CHANNEL_INTERNAL *chan, int16_t *nft); /* * Read 16 bits of data from offset into *data */HAL_BOOLar5212EepromRead(struct ath_hal *ah, u_int off, u_int16_t *data){ OS_REG_WRITE(ah, AR_EEPROM_ADDR, off); OS_REG_WRITE(ah, AR_EEPROM_CMD, AR_EEPROM_CMD_READ); if (!ath_hal_wait(ah, AR_EEPROM_STS, AR_EEPROM_STS_READ_COMPLETE | AR_EEPROM_STS_READ_ERROR, AR_EEPROM_STS_READ_COMPLETE)) { HALDEBUG(ah, "%s: read failed for entry 0x%x\n", __func__, off); return AH_FALSE; } *data = OS_REG_READ(ah, AR_EEPROM_DATA) & 0xffff; return AH_TRUE;}#ifdef AH_SUPPORT_WRITE_EEPROM/* * Write 16 bits of data from data to the specified EEPROM offset. */HAL_BOOLar5212EepromWrite(struct ath_hal *ah, u_int off, u_int16_t data){ OS_REG_WRITE(ah, AR_EEPROM_ADDR, off); OS_REG_WRITE(ah, AR_EEPROM_DATA, data); OS_REG_WRITE(ah, AR_EEPROM_CMD, AR_EEPROM_CMD_WRITE); if (!ath_hal_wait(ah, AR_EEPROM_STS, AR_EEPROM_STS_WRITE_COMPLETE | AR_EEPROM_STS_WRITE_ERROR, AR_EEPROM_STS_WRITE_COMPLETE)) { HALDEBUG(ah, "%s: write failed for entry 0x%x, data 0x%x\n", __func__, off, data); return AH_FALSE; } return AH_TRUE;}#endif /* AH_SUPPORT_WRITE_EEPROM */HAL_STATUSar5212EepromAttach(struct ath_hal *ah) { struct ath_hal_5212 *ahp = AH5212(ah); u_int32_t i, eepMax, sum, val; u_int16_t eeval; /* * TODO: Need to talk to Praveen about this, these are * not valid 2.4 channels, either we change these * or I need to change the beanie coding to accept these */ static const u_int16_t channels11b[] = { 2412, 2447, 2484 }; static const u_int16_t channels11g[] = { 2312, 2412, 2484 }; if (AH_PRIVATE(ah)->ah_eepromRead == AH_NULL) AH_PRIVATE(ah)->ah_eepromRead = ar5212EepromRead; //ahp->ah_eepromAttach = ar5212EepromAttach; ath_hal_printf(ah, "Setting ah_eepromDetach\n"); AH_PRIVATE(ah)->ah_eepromDetach = ar5212EepromDetach; AH_PRIVATE(ah)->ah_eepromSetBoardValues = ar5212SetBoardValues; AH_PRIVATE(ah)->ah_eepromGetSpurChan = ar5212EepromGetSpurChan; AH_PRIVATE(ah)->ah_setTransmitPower = ar5212SetTransmitPower; AH_PRIVATE(ah)->ah_getChipPowerLimits = ar5212GetChipPowerLimits; AH_PRIVATE(ah)->ah_getEepromCapabilityInfo = ar5212GetEepromCapabilityInfo; AH_PRIVATE(ah)->ah_getEepromNoiseFloorThresh = ar5212GetEepromNoiseFloorThresh; if (!AH_PRIVATE(ah)->ah_eepromRead(ah, AR_EEPROM_VERSION, &eeval)) { HALDEBUG(ah, "%s: unable to read EEPROM version\n", __func__); return HAL_EEREAD; } if (eeval < AR_EEPROM_VER3_2) { HALDEBUG(ah, "%s: unsupported EEPROM version %u (0x%x)\n", __func__, eeval, eeval); return HAL_EEVERSION; } ahp->ah_eeversion = eeval; switch (AH_PRIVATE(ah)->ah_devid) {#ifdef AH_SUPPORT_AR5312 u_int16_t data16; u_int32_t eepEndLoc; case AR5212_AR5312_REV2: case AR5212_AR5312_REV7: case AR5212_AR2313_REV8: case AR5212_AR2315_REV6: case AR5212_AR2315_REV7: case AR5212_AR2317_REV1: /* Read sizing information */ if (!AH_PRIVATE(ah)->ah_eepromRead(ah, AR_EEPROM_SIZE_UPPER, &data16)) { HALDEBUG(ah, "%s: cannot read eeprom upper size\n", __func__); return HAL_EEREAD; } if (data16 == 0) { eepEndLoc = AR_EEPROM_ATHEROS_MAX_LOC; } else { eepEndLoc = (data16 & AR_EEPROM_SIZE_UPPER_MASK) << AR_EEPROM_SIZE_UPPER_SHIFT; if (!AH_PRIVATE(ah)->ah_eepromRead(ah, AR_EEPROM_SIZE_LOWER, &data16)) { HALDEBUG(ah, "%s: cannot read eeprom lower size\n", __func__); return HAL_EEREAD; } } eepEndLoc |= data16; if (eepEndLoc < AR_EEPROM_ATHEROS_BASE) return HAL_EESIZE; break;#endif default: val = OS_REG_READ(ah, AR_PCICFG); val = MS(val, AR_PCICFG_EEPROM_SIZE); if (val != AR_PCICFG_EEPROM_SIZE_16K) { if (AR_PCICFG_EEPROM_SIZE_FAILED == val) { HALDEBUG(ah, "%s: unsupported EEPROM size " "%u (0x%x) found\n", __func__, val, val); return HAL_EESIZE; } if (!IS_5424(ah)) { HALDEBUG(ah, "%s: EEPROM size = %d. Must be %d (16k).\n", __func__, val, AR_PCICFG_EEPROM_SIZE_16K); return HAL_EESIZE; } } } if (!AH_PRIVATE(ah)->ah_eepromRead(ah, AR_EEPROM_PROTECT, &eeval)) { HALDEBUG(ah, "%s: cannot read EEPROM protection " "bits; read locked?\n", __func__); return HAL_EEREAD; } HALDEBUG(ah, "EEPROM protect 0x%x\n", eeval); ahp->ah_eeprotect = eeval; /* XXX check proper access before continuing */ /* * Read the Atheros EEPROM entries and calculate the checksum. */ if (!AH_PRIVATE(ah)->ah_eepromRead(ah, AR_EEPROM_SIZE_UPPER, &eeval)) { HALDEBUG(ah, "%s: cannot read EEPROM upper size\n" , __func__); return HAL_EEREAD; } if (eeval != 0) { eepMax = (eeval & AR_EEPROM_SIZE_UPPER_MASK) << AR_EEPROM_SIZE_ENDLOC_SHIFT; if (!AH_PRIVATE(ah)->ah_eepromRead(ah, AR_EEPROM_SIZE_LOWER, &eeval)) { HALDEBUG(ah, "%s: cannot read EEPROM lower size\n" , __func__); return HAL_EEREAD; } eepMax = (eepMax | eeval) - AR_EEPROM_ATHEROS_BASE; } else eepMax = AR_EEPROM_ATHEROS_MAX; sum = 0; for (i = 0; i < eepMax; i++) { if (!AH_PRIVATE(ah)->ah_eepromRead(ah, AR_EEPROM_ATHEROS(i), &eeval)) { return HAL_EEREAD; } sum ^= eeval; } if (sum != 0xffff) { HALDEBUG(ah, "%s: bad EEPROM checksum 0x%x\n", __func__, sum); return HAL_EEBADSUM; } ahp->ah_numChannels11a = NUM_11A_EEPROM_CHANNELS; ahp->ah_numChannels2_4 = NUM_2_4_EEPROM_CHANNELS; for (i = 0; i < NUM_11A_EEPROM_CHANNELS; i ++) ahp->ah_dataPerChannel11a[i].numPcdacValues = NUM_PCDAC_VALUES; /* the channel list for 2.4 is fixed, fill this in here */ for (i = 0; i < NUM_2_4_EEPROM_CHANNELS; i++) { ahp->ah_channels11b[i] = channels11b[i]; ahp->ah_channels11g[i] = channels11g[i]; ahp->ah_dataPerChannel11b[i].numPcdacValues = NUM_PCDAC_VALUES; ahp->ah_dataPerChannel11g[i].numPcdacValues = NUM_PCDAC_VALUES; } ath_hal_printf(ah,"**** Going to ath_hal_readEepromIntoDataset\n"); if (!ath_hal_readEepromIntoDataset(ah, &ahp->ah_eeprom)) { return HAL_EEREAD; /* XXX */ } if ((ahp->ah_eeversion < AR_EEPROM_VER5_3) && (IS_5413(ah))) { ahp->ah_eeprom.ee_spurChans[0][1] = AR_SPUR_5413_1; ahp->ah_eeprom.ee_spurChans[1][1] = AR_SPUR_5413_2; ahp->ah_eeprom.ee_spurChans[2][1] = AR_NO_SPUR; ahp->ah_eeprom.ee_spurChans[0][0] = AR_NO_SPUR; } return HAL_OK;}//static HAL_STATUSHAL_STATUSar5212EepromDetach(struct ath_hal *ah) { ath_hal_printf(ah, "In %s\n", __func__); ath_hal_eepromDetach(ah, &AH5212(ah)->ah_eeprom); return HAL_OK;}/* * Read EEPROM header info and program the device for correct operation * given the channel value. */HAL_BOOLstatic ar5212SetBoardValues(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan){#define NO_FALSE_DETECT_BACKOFF 2#define CB22_FALSE_DETECT_BACKOFF 6#define AR_PHY_BIS(_ah, _reg, _mask, _val) \ OS_REG_WRITE(_ah, AR_PHY(_reg), \ (OS_REG_READ(_ah, AR_PHY(_reg)) & _mask) | (_val)); struct ath_hal_5212 *ahp = AH5212(ah); int arrayMode, falseDectectBackoff; int is2GHz = IS_CHAN_2GHZ(chan); int8_t adcDesiredSize, pgaDesiredSize; u_int16_t switchSettling, txrxAtten, rxtxMargin; int iCoff, qCoff; switch (chan->channelFlags & CHANNEL_ALL) { case CHANNEL_A: case CHANNEL_T: case CHANNEL_XR_A: case CHANNEL_XR_T: arrayMode = headerInfo11A; if (!IS_5112(ah) && !IS_2413(ah) && !IS_5413(ah)) OS_REG_RMW_FIELD(ah, AR_PHY_FRAME_CTL, AR_PHY_FRAME_CTL_TX_CLIP, ahp->ah_gainValues.currStep->paramVal[GP_TXCLIP]); break; case CHANNEL_B: arrayMode = headerInfo11B; break; case CHANNEL_G: case CHANNEL_108G: case CHANNEL_XR_G: arrayMode = headerInfo11G; break; default: HALDEBUG(ah, "%s: invalid channel flags 0x%x\n", __func__, chan->channelFlags); return AH_FALSE; } /* Set the antenna register(s) correctly for the chip revision */ AR_PHY_BIS(ah, 68, 0xFFFFFC06, (ahp->ah_antennaControl[0][arrayMode] << 4) | 0x1); ahp->ah_diversityControl &= ~HAL_ANT_OPT_MASK; ar5212SetAntennaSwitch(ah, ahp->ah_diversityControl, (HAL_CHANNEL *) chan); /* Set the Noise Floor Thresh on ar5211 devices */ OS_REG_WRITE(ah, AR_PHY(90), (ahp->ah_noiseFloorThresh[arrayMode] & 0x1FF) | (1 << 9)); if (ahp->ah_eeversion >= AR_EEPROM_VER5_0 && IS_CHAN_TURBO(chan)) { switchSettling = ahp->ah_switchSettlingTurbo[is2GHz]; adcDesiredSize = ahp->ah_adcDesiredSizeTurbo[is2GHz]; pgaDesiredSize = ahp->ah_pgaDesiredSizeTurbo[is2GHz]; txrxAtten = ahp->ah_txrxAttenTurbo[is2GHz]; rxtxMargin = ahp->ah_rxtxMarginTurbo[is2GHz]; } else { switchSettling = ahp->ah_switchSettling[arrayMode]; adcDesiredSize = ahp->ah_adcDesiredSize[arrayMode]; pgaDesiredSize = ahp->ah_pgaDesiredSize[is2GHz]; txrxAtten = ahp->ah_txrxAtten[is2GHz]; rxtxMargin = ahp->ah_rxtxMargin[is2GHz]; } OS_REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH, switchSettling); OS_REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_ADC, adcDesiredSize); OS_REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_PGA, pgaDesiredSize); OS_REG_RMW_FIELD(ah, AR_PHY_RXGAIN, AR_PHY_RXGAIN_TXRX_ATTEN, txrxAtten); OS_REG_WRITE(ah, AR_PHY(13), (ahp->ah_txEndToXPAOff[arrayMode] << 24) | (ahp->ah_txEndToXPAOff[arrayMode] << 16) | (ahp->ah_txFrameToXPAOn[arrayMode] << 8) | ahp->ah_txFrameToXPAOn[arrayMode]); AR_PHY_BIS(ah, 10, 0xFFFF00FF, ahp->ah_txEndToXLNAOn[arrayMode] << 8); AR_PHY_BIS(ah, 25, 0xFFF80FFF, (ahp->ah_thresh62[arrayMode] << 12) & 0x7F000); /* * False detect backoff - suspected 32 MHz spur causes false * detects in OFDM, causing Tx Hangs. Decrease weak signal * sensitivity for this card. */ falseDectectBackoff = NO_FALSE_DETECT_BACKOFF; if (ahp->ah_eeversion < AR_EEPROM_VER3_3) { /* XXX magic number */ if (AH_PRIVATE(ah)->ah_subvendorid == 0x1022 && IS_CHAN_OFDM(chan)) falseDectectBackoff += CB22_FALSE_DETECT_BACKOFF; } else { if (ar5212IsSpurChannel(ah, (HAL_CHANNEL *)chan)) { falseDectectBackoff += ahp->ah_falseDetectBackoff[arrayMode]; } } AR_PHY_BIS(ah, 73, 0xFFFFFF01, (falseDectectBackoff << 1) & 0xF7); if (chan->iqCalValid) { iCoff = chan->iCoff; qCoff = chan->qCoff; } else { iCoff = ahp->ah_iqCalI[is2GHz]; qCoff = ahp->ah_iqCalQ[is2GHz]; } /* write previous IQ results */ OS_REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4, AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF, iCoff); OS_REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4, AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF, qCoff); OS_REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4, AR_PHY_TIMING_CTRL4_IQCORR_ENABLE); if (ahp->ah_eeversion >= AR_EEPROM_VER4_1) { if (!IS_CHAN_108G(chan) || ahp->ah_eeversion >= AR_EEPROM_VER5_0) OS_REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ, AR_PHY_GAIN_2GHZ_RXTX_MARGIN, rxtxMargin); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -