📄 ar5112.c
字号:
/* * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting * Copyright (c) 2002-2005 Atheros Communications, Inc. * All rights reserved. * * $Id: ar5112.c,v 1.1.1.1 2006/09/12 03:45:29 steven Exp $ */#include "opt_ah.h"#ifdef AH_SUPPORT_5112#include "ah.h"#include "ah_internal.h"#include "ar5212/ar5212.h"#include "ar5212/ar5212reg.h"#include "ar5212/ar5212phy.h"/* Add static register initialization vectors */#define AH_5212_5112#include "ar5212/ar5212.ini"#define N(a) (sizeof(a)/sizeof(a[0]))/* * WAR for bug 6773. OS_DELAY() does a PIO READ on the PCI bus which allows * other cards' DMA reads to complete in the middle of our reset. */#define WAR_6773(x) do { \ if ((++(x) % 64) == 0) \ OS_DELAY(1); \} while (0)#define REG_WRITE_ARRAY(regArray, column, regWr) do { \ int r; \ for (r = 0; r < N(regArray); r++) { \ OS_REG_WRITE(ah, (regArray)[r][0], (regArray)[r][(column)]);\ WAR_6773(regWr); \ } \} while (0)#define REG_WRITE_RF_ARRAY(regArray, regData, regWr) do { \ int r; \ for (r = 0; r < N(regArray); r++) { \ OS_REG_WRITE(ah, (regArray)[r][0], (regData)[r]); \ WAR_6773(regWr); \ } \} while (0)static void ar5212GetLowerUpperIndex(u_int16_t v, u_int16_t *lp, u_int16_t listSize, u_int32_t *vlo, u_int32_t *vhi);static HAL_BOOL getFullPwrTable(u_int16_t numPcdacs, u_int16_t *pcdacs, int16_t *power, int16_t maxPower, int16_t *retVals);static int16_t getPminAndPcdacTableFromPowerTable(int16_t *pwrTableT4, u_int16_t retVals[]);static int16_t getPminAndPcdacTableFromTwoPowerTables(int16_t *pwrTableLXpdT4, int16_t *pwrTableHXpdT4, u_int16_t retVals[], int16_t *pMid);static int16_t interpolate_signed(u_int16_t target, u_int16_t srcLeft, u_int16_t srcRight, int16_t targetLeft, int16_t targetRight);extern void ar5212ModifyRfBuffer(u_int32_t *rfBuf, u_int32_t reg32, u_int32_t numBits, u_int32_t firstBit, u_int32_t column);typedef struct { u_int32_t Bank1Data[N(ar5212Bank1_5112)]; u_int32_t Bank2Data[N(ar5212Bank2_5112)]; u_int32_t Bank3Data[N(ar5212Bank3_5112)]; u_int32_t Bank6Data[N(ar5212Bank6_5112)]; u_int32_t Bank7Data[N(ar5212Bank7_5112)];} AR5212_RF_BANKS_5112;static voidar5112WriteRegs(struct ath_hal *ah, u_int modesIndex, u_int freqIndex, int regWrites){ REG_WRITE_ARRAY(ar5212Modes_5112, modesIndex, regWrites); REG_WRITE_ARRAY(ar5212Common_5112, 1, regWrites); REG_WRITE_ARRAY(ar5212BB_RfGain_5112, freqIndex, regWrites);}/* * Take the MHz channel value and set the Channel value * * ASSUMES: Writes enabled to analog bus */static HAL_BOOLar5112SetChannel(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan){ u_int32_t channelSel = 0; u_int32_t bModeSynth = 0; u_int32_t aModeRefSel = 0; u_int32_t reg32 = 0; u_int16_t freq; OS_MARK(ah, AH_MARK_SETCHANNEL, chan->channel); if (chan->channel < 4800) { u_int32_t txctl; if (((chan->channel - 2192) % 5) == 0) { channelSel = ((chan->channel - 672) * 2 - 3040)/10; bModeSynth = 0; } else if (((chan->channel - 2224) % 5) == 0) { channelSel = ((chan->channel - 704) * 2 - 3040) / 10; bModeSynth = 1; } else { HALDEBUG(ah, "%s: invalid channel %u MHz\n", __func__, chan->channel); return AH_FALSE; } channelSel = (channelSel << 2) & 0xff; channelSel = ath_hal_reverseBits(channelSel, 8); txctl = OS_REG_READ(ah, AR_PHY_CCK_TX_CTRL); if (chan->channel == 2484) { /* Enable channel spreading for channel 14 */ OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, txctl | AR_PHY_CCK_TX_CTRL_JAPAN); } else { OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, txctl &~ AR_PHY_CCK_TX_CTRL_JAPAN); } } else if (((chan->channel % 5) == 2) && (chan->channel <= 5435)) { freq = chan->channel - 2; /* Align to even 5MHz raster */ channelSel = ath_hal_reverseBits( (u_int32_t)(((freq - 4800)*10)/25 + 1), 8); aModeRefSel = ath_hal_reverseBits(0, 2); } else if ((chan->channel % 20) == 0 && chan->channel >= 5120) { channelSel = ath_hal_reverseBits( ((chan->channel - 4800) / 20 << 2), 8); aModeRefSel = ath_hal_reverseBits(3, 2); } else if ((chan->channel % 10) == 0) { channelSel = ath_hal_reverseBits( ((chan->channel - 4800) / 10 << 1), 8); aModeRefSel = ath_hal_reverseBits(2, 2); } else if ((chan->channel % 5) == 0) { channelSel = ath_hal_reverseBits( (chan->channel - 4800) / 5, 8); aModeRefSel = ath_hal_reverseBits(1, 2); } else { HALDEBUG(ah, "%s: invalid channel %u MHz\n", __func__, chan->channel); return AH_FALSE; } reg32 = (channelSel << 4) | (aModeRefSel << 2) | (bModeSynth << 1) | (1 << 12) | 0x1; OS_REG_WRITE(ah, AR_PHY(0x27), reg32 & 0xff); reg32 >>= 8; OS_REG_WRITE(ah, AR_PHY(0x36), reg32 & 0x7f); AH_PRIVATE(ah)->ah_curchan = chan; return AH_TRUE;}/* * Return a reference to the requested RF Bank. */static u_int32_t *ar5112GetRfBank(struct ath_hal *ah, int bank){ struct ath_hal_5212 *ahp = AH5212(ah); AR5212_RF_BANKS_5112 *pRfBank5112 = ahp->ah_analogBanks; HALASSERT(ahp->ah_analogBanks != AH_NULL); switch (bank) { case 1: return pRfBank5112->Bank1Data; case 2: return pRfBank5112->Bank2Data; case 3: return pRfBank5112->Bank3Data; case 6: return pRfBank5112->Bank6Data; case 7: return pRfBank5112->Bank7Data; } HALDEBUG(ah, "%s: unknown RF Bank %d requested\n", __func__, bank); return AH_NULL;}/* * Reads EEPROM header info from device structure and programs * all rf registers * * REQUIRES: Access to the analog rf device */static HAL_BOOLar5112SetRfRegs(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan, u_int16_t modesIndex, u_int16_t *rfXpdGain){#define RF_BANK_SETUP(_pb, _ix, _col) do { \ int i; \ for (i = 0; i < N(ar5212Bank##_ix##_5112); i++) \ (_pb)->Bank##_ix##Data[i] = ar5212Bank##_ix##_5112[i][_col];\} while (0) struct ath_hal_5212 *ahp = AH5212(ah); u_int16_t rfXpdSel, gainI; u_int16_t ob5GHz = 0, db5GHz = 0; u_int16_t ob2GHz = 0, db2GHz = 0; AR5212_RF_BANKS_5112 *pRfBanks = ahp->ah_analogBanks; GAIN_VALUES *gv = &ahp->ah_gainValues; int regWrites = 0; HALASSERT(pRfBanks); /* Setup rf parameters */ switch (chan->channelFlags & CHANNEL_ALL) { case CHANNEL_A: case CHANNEL_T: case CHANNEL_XR: if (chan->channel > 4000 && chan->channel < 5260) { ob5GHz = ahp->ah_ob1; db5GHz = ahp->ah_db1; } else if (chan->channel >= 5260 && chan->channel < 5500) { ob5GHz = ahp->ah_ob2; db5GHz = ahp->ah_db2; } else if (chan->channel >= 5500 && chan->channel < 5725) { ob5GHz = ahp->ah_ob3; db5GHz = ahp->ah_db3; } else if (chan->channel >= 5725) { ob5GHz = ahp->ah_ob4; db5GHz = ahp->ah_db4; } else { /* XXX else */ } rfXpdSel = ahp->ah_xpd[headerInfo11A]; gainI = ahp->ah_gainI[headerInfo11A]; break; case CHANNEL_B: ob2GHz = ahp->ah_ob2GHz[0]; db2GHz = ahp->ah_db2GHz[0]; rfXpdSel = ahp->ah_xpd[headerInfo11B]; gainI = ahp->ah_gainI[headerInfo11B]; break; case CHANNEL_G: case CHANNEL_108G:#ifdef notyet case CHANNEL_XR_G:#endif ob2GHz = ahp->ah_ob2GHz[1]; db2GHz = ahp->ah_ob2GHz[1]; rfXpdSel = ahp->ah_xpd[headerInfo11G]; gainI = ahp->ah_gainI[headerInfo11G]; break; default: HALDEBUG(ah, "%s: invalid channel flags 0x%x\n", __func__, chan->channelFlags); return AH_FALSE; } /* Setup Bank 1 Write */ RF_BANK_SETUP(pRfBanks, 1, 1); /* Setup Bank 2 Write */ RF_BANK_SETUP(pRfBanks, 2, modesIndex); /* Setup Bank 3 Write */ RF_BANK_SETUP(pRfBanks, 3, modesIndex); /* Setup Bank 6 Write */ RF_BANK_SETUP(pRfBanks, 6, modesIndex); ar5212ModifyRfBuffer(pRfBanks->Bank6Data, rfXpdSel, 1, 302, 0); ar5212ModifyRfBuffer(pRfBanks->Bank6Data, rfXpdGain[0], 2, 270, 0); ar5212ModifyRfBuffer(pRfBanks->Bank6Data, rfXpdGain[1], 2, 257, 0); if (IS_CHAN_OFDM(chan)) { ar5212ModifyRfBuffer(pRfBanks->Bank6Data, gv->currStep->paramVal[GP_PWD_138], 1, 168, 3); ar5212ModifyRfBuffer(pRfBanks->Bank6Data, gv->currStep->paramVal[GP_PWD_137], 1, 169, 3); ar5212ModifyRfBuffer(pRfBanks->Bank6Data, gv->currStep->paramVal[GP_PWD_136], 1, 170, 3); ar5212ModifyRfBuffer(pRfBanks->Bank6Data, gv->currStep->paramVal[GP_PWD_132], 1, 174, 3); ar5212ModifyRfBuffer(pRfBanks->Bank6Data, gv->currStep->paramVal[GP_PWD_131], 1, 175, 3); ar5212ModifyRfBuffer(pRfBanks->Bank6Data, gv->currStep->paramVal[GP_PWD_130], 1, 176, 3); } /* Only the 5 or 2 GHz OB/DB need to be set for a mode */ if (IS_CHAN_2GHZ(chan)) { ar5212ModifyRfBuffer(pRfBanks->Bank6Data, ob2GHz, 3, 287, 0); ar5212ModifyRfBuffer(pRfBanks->Bank6Data, db2GHz, 3, 290, 0); } else { ar5212ModifyRfBuffer(pRfBanks->Bank6Data, ob5GHz, 3, 279, 0); ar5212ModifyRfBuffer(pRfBanks->Bank6Data, db5GHz, 3, 282, 0); } /* Lower synth voltage for X112 Rev 2.0 only */ if (IS_RADX112_REV2(ah)) { /* Non-Reversed analyg registers - so values are pre-reversed */ ar5212ModifyRfBuffer(pRfBanks->Bank6Data, 2, 2, 90, 2); ar5212ModifyRfBuffer(pRfBanks->Bank6Data, 2, 2, 92, 2); ar5212ModifyRfBuffer(pRfBanks->Bank6Data, 2, 2, 94, 2); ar5212ModifyRfBuffer(pRfBanks->Bank6Data, 2, 1, 254, 2); } /* Decrease Power Consumption for 5312/5213 and up */ if (AH_PRIVATE(ah)->ah_phyRev >= AR_PHY_CHIP_ID_REV_2) { ar5212ModifyRfBuffer(pRfBanks->Bank6Data, 1, 1, 281, 1); ar5212ModifyRfBuffer(pRfBanks->Bank6Data, 1, 2, 1, 3); ar5212ModifyRfBuffer(pRfBanks->Bank6Data, 1, 2, 3, 3); ar5212ModifyRfBuffer(pRfBanks->Bank6Data, 1, 1, 139, 3); ar5212ModifyRfBuffer(pRfBanks->Bank6Data, 1, 1, 140, 3); } /* Setup Bank 7 Setup */ RF_BANK_SETUP(pRfBanks, 7, modesIndex); if (IS_CHAN_OFDM(chan)) ar5212ModifyRfBuffer(pRfBanks->Bank7Data, gv->currStep->paramVal[GP_MIXGAIN_OVR], 2, 37, 0); ar5212ModifyRfBuffer(pRfBanks->Bank7Data, gainI, 6, 14, 0); /* Adjust params for Derby TX power control */ if (IS_CHAN_HALF_RATE(chan) || IS_CHAN_QUARTER_RATE(chan)) { u_int32_t rfDelay, rfPeriod; rfDelay = 0xf; rfPeriod = (IS_CHAN_HALF_RATE(chan)) ? 0x8 : 0xf; ar5212ModifyRfBuffer(pRfBanks->Bank7Data, rfDelay, 4, 58, 0); ar5212ModifyRfBuffer(pRfBanks->Bank7Data, rfPeriod, 4, 70, 0); }#ifdef notyet /* Analog registers are setup - EAR can modify */ if (ar5212IsEarEngaged(pDev, chan)) u_int32_t modifier; ar5212EarModify(pDev, EAR_LC_RF_WRITE, chan, &modifier);#endif /* Write Analog registers */ REG_WRITE_RF_ARRAY(ar5212Bank1_5112, pRfBanks->Bank1Data, regWrites); REG_WRITE_RF_ARRAY(ar5212Bank2_5112, pRfBanks->Bank2Data, regWrites); REG_WRITE_RF_ARRAY(ar5212Bank3_5112, pRfBanks->Bank3Data, regWrites); REG_WRITE_RF_ARRAY(ar5212Bank6_5112, pRfBanks->Bank6Data, regWrites); REG_WRITE_RF_ARRAY(ar5212Bank7_5112, pRfBanks->Bank7Data, regWrites); /* Now that we have reprogrammed rfgain value, clear the flag. */ ahp->ah_rfgainState = HAL_RFGAIN_INACTIVE; return AH_TRUE;#undef RF_BANK_SETUP}/* * Read the transmit power levels from the structures taken from EEPROM * Interpolate read transmit power values for this channel * Organize the transmit power values into a table for writing into the hardware */static HAL_BOOLar5112SetPowerTable(struct ath_hal *ah, int16_t *pPowerMin, int16_t *pPowerMax, HAL_CHANNEL_INTERNAL *chan, u_int16_t *rfXpdGain){ struct ath_hal_5212 *ahp = AH5212(ah); u_int32_t numXpdGain = IS_RADX112_REV2(ah) ? 2 : 1; u_int32_t xpdGainMask = 0; int16_t powerMid, *pPowerMid = &powerMid; EXPN_DATA_PER_CHANNEL_5112 *pRawCh; EEPROM_POWER_EXPN_5112 *pPowerExpn = AH_NULL; u_int32_t ii, jj, kk; int16_t minPwr_t4, maxPwr_t4, Pmin, Pmid; u_int32_t chan_idx_L, chan_idx_R; u_int16_t chan_L, chan_R; int16_t pwr_table0[64]; int16_t pwr_table1[64]; u_int16_t pcdacs[10]; int16_t powers[10]; u_int16_t numPcd; int16_t powTableLXPD[2][64]; int16_t powTableHXPD[2][64]; int16_t tmpPowerTable[64]; u_int16_t xgainList[2]; u_int16_t xpdMask; switch (chan->channelFlags & CHANNEL_ALL) { case CHANNEL_A: case CHANNEL_T: case CHANNEL_XR: pPowerExpn = &ahp->ah_modePowerArray5112[headerInfo11A]; xpdGainMask = ahp->ah_xgain[headerInfo11A]; break; case CHANNEL_B: pPowerExpn = &ahp->ah_modePowerArray5112[headerInfo11B]; xpdGainMask = ahp->ah_xgain[headerInfo11B]; break; case CHANNEL_G: case CHANNEL_108G:#ifdef notyet case CHANNEL_XR_G:#endif pPowerExpn = &ahp->ah_modePowerArray5112[headerInfo11G]; xpdGainMask = ahp->ah_xgain[headerInfo11G]; break; default: HALDEBUG(ah, "%s: unknown channel flags 0x%x\n", __func__, chan->channelFlags & CHANNEL_ALL); return AH_FALSE; } if ((xpdGainMask & pPowerExpn->xpdMask) < 1) { HALDEBUG(ah, "%s: desired xpdGainMask 0x%x not supported by " "calibrated xpdMask 0x%x\n", __func__, xpdGainMask, pPowerExpn->xpdMask); return AH_FALSE; } maxPwr_t4 = (int16_t)(2*(*pPowerMax)); /* pwr_t2 -> pwr_t4 */ minPwr_t4 = (int16_t)(2*(*pPowerMin)); /* pwr_t2 -> pwr_t4 */ xgainList[0] = 0xDEAD; xgainList[1] = 0xDEAD; kk = 0; xpdMask = pPowerExpn->xpdMask; for (jj = 0; jj < NUM_XPD_PER_CHANNEL; jj++) { if (((xpdMask >> jj) & 1) > 0) { if (kk > 1) { HALDEBUG(ah, "A maximum of 2 xpdGains supported" "in pExpnPower data\n"); return AH_FALSE; } xgainList[kk++] = (u_int16_t)jj; } } ar5212GetLowerUpperIndex(chan->channel, &pPowerExpn->pChannels[0], pPowerExpn->numChannels, &chan_idx_L, &chan_idx_R); kk = 0; for (ii = chan_idx_L; ii <= chan_idx_R; ii++) { pRawCh = &(pPowerExpn->pDataPerChannel[ii]); if (xgainList[1] == 0xDEAD) { jj = xgainList[0]; numPcd = pRawCh->pDataPerXPD[jj].numPcdacs; OS_MEMCPY(&pcdacs[0], &pRawCh->pDataPerXPD[jj].pcdac[0], numPcd * sizeof(u_int16_t)); OS_MEMCPY(&powers[0], &pRawCh->pDataPerXPD[jj].pwr_t4[0], numPcd * sizeof(int16_t)); if (!getFullPwrTable(numPcd, &pcdacs[0], &powers[0], pRawCh->maxPower_t4, &tmpPowerTable[0])) { return AH_FALSE; } OS_MEMCPY(&powTableLXPD[kk][0], &tmpPowerTable[0], 64*sizeof(int16_t)); } else { jj = xgainList[0]; numPcd = pRawCh->pDataPerXPD[jj].numPcdacs; OS_MEMCPY(&pcdacs[0], &pRawCh->pDataPerXPD[jj].pcdac[0], numPcd*sizeof(u_int16_t)); OS_MEMCPY(&powers[0], &pRawCh->pDataPerXPD[jj].pwr_t4[0], numPcd*sizeof(int16_t)); if (!getFullPwrTable(numPcd, &pcdacs[0], &powers[0], pRawCh->maxPower_t4, &tmpPowerTable[0])) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -