📄 ar5111.c.svn-base
字号:
/* * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting * Copyright (c) 2002-2008 Atheros Communications, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * $Id: ar5111.c,v 1.7 2008/11/10 04:08:03 sam Exp $ */#include "opt_ah.h"#include "ah.h"#include "ah_internal.h"#include "ah_eeprom_v3.h"#include "ar5212/ar5212.h"#include "ar5212/ar5212reg.h"#include "ar5212/ar5212phy.h"#define AH_5212_5111#include "ar5212/ar5212.ini"#define N(a) (sizeof(a)/sizeof(a[0]))struct ar5111State { RF_HAL_FUNCS base; /* public state, must be first */ uint16_t pcdacTable[PWR_TABLE_SIZE]; uint32_t Bank0Data[N(ar5212Bank0_5111)]; uint32_t Bank1Data[N(ar5212Bank1_5111)]; uint32_t Bank2Data[N(ar5212Bank2_5111)]; uint32_t Bank3Data[N(ar5212Bank3_5111)]; uint32_t Bank6Data[N(ar5212Bank6_5111)]; uint32_t Bank7Data[N(ar5212Bank7_5111)];};#define AR5111(ah) ((struct ar5111State *) AH5212(ah)->ah_rfHal)static uint16_t ar5212GetScaledPower(uint16_t channel, uint16_t pcdacValue, const PCDACS_EEPROM *pSrcStruct);static HAL_BOOL ar5212FindValueInList(uint16_t channel, uint16_t pcdacValue, const PCDACS_EEPROM *pSrcStruct, uint16_t *powerValue);static void ar5212GetLowerUpperPcdacs(uint16_t pcdac, uint16_t channel, const PCDACS_EEPROM *pSrcStruct, uint16_t *pLowerPcdac, uint16_t *pUpperPcdac);extern void ar5212GetLowerUpperValues(uint16_t value, const uint16_t *pList, uint16_t listSize, uint16_t *pLowerValue, uint16_t *pUpperValue);extern void ar5212ModifyRfBuffer(uint32_t *rfBuf, uint32_t reg32, uint32_t numBits, uint32_t firstBit, uint32_t column);static voidar5111WriteRegs(struct ath_hal *ah, u_int modesIndex, u_int freqIndex, int writes){ HAL_INI_WRITE_ARRAY(ah, ar5212Modes_5111, modesIndex, writes); HAL_INI_WRITE_ARRAY(ah, ar5212Common_5111, 1, writes); HAL_INI_WRITE_ARRAY(ah, ar5212BB_RfGain_5111, freqIndex, writes);}/* * Take the MHz channel value and set the Channel value * * ASSUMES: Writes enabled to analog bus */static HAL_BOOLar5111SetChannel(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan){#define CI_2GHZ_INDEX_CORRECTION 19 uint32_t refClk, reg32, data2111; int16_t chan5111, chanIEEE; /* * Structure to hold 11b tuning information for 5111/2111 * 16 MHz mode, divider ratio = 198 = NP+S. N=16, S=4 or 6, P=12 */ typedef struct { uint32_t refClkSel; /* reference clock, 1 for 16 MHz */ uint32_t channelSelect; /* P[7:4]S[3:0] bits */ uint16_t channel5111; /* 11a channel for 5111 */ } CHAN_INFO_2GHZ; const static CHAN_INFO_2GHZ chan2GHzData[] = { { 1, 0x46, 96 }, /* 2312 -19 */ { 1, 0x46, 97 }, /* 2317 -18 */ { 1, 0x46, 98 }, /* 2322 -17 */ { 1, 0x46, 99 }, /* 2327 -16 */ { 1, 0x46, 100 }, /* 2332 -15 */ { 1, 0x46, 101 }, /* 2337 -14 */ { 1, 0x46, 102 }, /* 2342 -13 */ { 1, 0x46, 103 }, /* 2347 -12 */ { 1, 0x46, 104 }, /* 2352 -11 */ { 1, 0x46, 105 }, /* 2357 -10 */ { 1, 0x46, 106 }, /* 2362 -9 */ { 1, 0x46, 107 }, /* 2367 -8 */ { 1, 0x46, 108 }, /* 2372 -7 */ /* index -6 to 0 are pad to make this a nolookup table */ { 1, 0x46, 116 }, /* -6 */ { 1, 0x46, 116 }, /* -5 */ { 1, 0x46, 116 }, /* -4 */ { 1, 0x46, 116 }, /* -3 */ { 1, 0x46, 116 }, /* -2 */ { 1, 0x46, 116 }, /* -1 */ { 1, 0x46, 116 }, /* 0 */ { 1, 0x46, 116 }, /* 2412 1 */ { 1, 0x46, 117 }, /* 2417 2 */ { 1, 0x46, 118 }, /* 2422 3 */ { 1, 0x46, 119 }, /* 2427 4 */ { 1, 0x46, 120 }, /* 2432 5 */ { 1, 0x46, 121 }, /* 2437 6 */ { 1, 0x46, 122 }, /* 2442 7 */ { 1, 0x46, 123 }, /* 2447 8 */ { 1, 0x46, 124 }, /* 2452 9 */ { 1, 0x46, 125 }, /* 2457 10 */ { 1, 0x46, 126 }, /* 2462 11 */ { 1, 0x46, 127 }, /* 2467 12 */ { 1, 0x46, 128 }, /* 2472 13 */ { 1, 0x44, 124 }, /* 2484 14 */ { 1, 0x46, 136 }, /* 2512 15 */ { 1, 0x46, 140 }, /* 2532 16 */ { 1, 0x46, 144 }, /* 2552 17 */ { 1, 0x46, 148 }, /* 2572 18 */ { 1, 0x46, 152 }, /* 2592 19 */ { 1, 0x46, 156 }, /* 2612 20 */ { 1, 0x46, 160 }, /* 2632 21 */ { 1, 0x46, 164 }, /* 2652 22 */ { 1, 0x46, 168 }, /* 2672 23 */ { 1, 0x46, 172 }, /* 2692 24 */ { 1, 0x46, 176 }, /* 2712 25 */ { 1, 0x46, 180 } /* 2732 26 */ }; OS_MARK(ah, AH_MARK_SETCHANNEL, chan->channel); chanIEEE = ath_hal_mhz2ieee(ah, chan->channel, chan->channelFlags); if (IS_CHAN_2GHZ(chan)) { const CHAN_INFO_2GHZ* ci = &chan2GHzData[chanIEEE + CI_2GHZ_INDEX_CORRECTION]; uint32_t txctl; data2111 = ((ath_hal_reverseBits(ci->channelSelect, 8) & 0xff) << 5) | (ci->refClkSel << 4); chan5111 = ci->channel5111; 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 { chan5111 = chanIEEE; /* no conversion needed */ data2111 = 0; } /* Rest of the code is common for 5 GHz and 2.4 GHz. */ if (chan5111 >= 145 || (chan5111 & 0x1)) { reg32 = ath_hal_reverseBits(chan5111 - 24, 8) & 0xff; refClk = 1; } else { reg32 = ath_hal_reverseBits(((chan5111 - 24)/2), 8) & 0xff; refClk = 0; } reg32 = (reg32 << 2) | (refClk << 1) | (1 << 10) | 0x1; OS_REG_WRITE(ah, AR_PHY(0x27), ((data2111 & 0xff) << 8) | (reg32 & 0xff)); reg32 >>= 8; OS_REG_WRITE(ah, AR_PHY(0x34), (data2111 & 0xff00) | (reg32 & 0xff)); AH_PRIVATE(ah)->ah_curchan = chan; return AH_TRUE;#undef CI_2GHZ_INDEX_CORRECTION}/* * Return a reference to the requested RF Bank. */static uint32_t *ar5111GetRfBank(struct ath_hal *ah, int bank){ struct ar5111State *priv = AR5111(ah); HALASSERT(priv != AH_NULL); switch (bank) { case 0: return priv->Bank0Data; case 1: return priv->Bank1Data; case 2: return priv->Bank2Data; case 3: return priv->Bank3Data; case 6: return priv->Bank6Data; case 7: return priv->Bank7Data; } HALDEBUG(ah, HAL_DEBUG_ANY, "%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_BOOLar5111SetRfRegs(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan, uint16_t modesIndex, uint16_t *rfXpdGain){ struct ath_hal_5212 *ahp = AH5212(ah); const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; uint16_t rfXpdGainFixed, rfPloSel, rfPwdXpd, gainI; uint16_t tempOB, tempDB; uint32_t ob2GHz, db2GHz, rfReg[N(ar5212Bank6_5111)]; int i, regWrites = 0; /* Setup rf parameters */ switch (chan->channelFlags & CHANNEL_ALL) { case CHANNEL_A: case CHANNEL_T: if (4000 < chan->channel && chan->channel < 5260) { tempOB = ee->ee_ob1; tempDB = ee->ee_db1; } else if (5260 <= chan->channel && chan->channel < 5500) { tempOB = ee->ee_ob2; tempDB = ee->ee_db2; } else if (5500 <= chan->channel && 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 when does this happen??? */ tempOB = tempDB = 0; } ob2GHz = db2GHz = 0; rfXpdGainFixed = ee->ee_xgain[headerInfo11A]; rfPloSel = ee->ee_xpd[headerInfo11A]; rfPwdXpd = !ee->ee_xpd[headerInfo11A]; gainI = ee->ee_gainI[headerInfo11A]; break; case CHANNEL_B: tempOB = ee->ee_obFor24; tempDB = ee->ee_dbFor24; ob2GHz = ee->ee_ob2GHz[0]; db2GHz = ee->ee_db2GHz[0]; rfXpdGainFixed = ee->ee_xgain[headerInfo11B]; rfPloSel = ee->ee_xpd[headerInfo11B]; rfPwdXpd = !ee->ee_xpd[headerInfo11B]; gainI = ee->ee_gainI[headerInfo11B]; break; case CHANNEL_G: tempOB = ee->ee_obFor24g; tempDB = ee->ee_dbFor24g; ob2GHz = ee->ee_ob2GHz[1]; db2GHz = ee->ee_db2GHz[1]; rfXpdGainFixed = ee->ee_xgain[headerInfo11G]; rfPloSel = ee->ee_xpd[headerInfo11G]; rfPwdXpd = !ee->ee_xpd[headerInfo11G]; gainI = ee->ee_gainI[headerInfo11G]; 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); /* Bank 0 Write */ for (i = 0; i < N(ar5212Bank0_5111); i++) rfReg[i] = ar5212Bank0_5111[i][modesIndex]; if (IS_CHAN_2GHZ(chan)) { ar5212ModifyRfBuffer(rfReg, ob2GHz, 3, 119, 0); ar5212ModifyRfBuffer(rfReg, db2GHz, 3, 122, 0); } HAL_INI_WRITE_BANK(ah, ar5212Bank0_5111, rfReg, regWrites); /* Bank 1 Write */ HAL_INI_WRITE_ARRAY(ah, ar5212Bank1_5111, 1, regWrites); /* Bank 2 Write */ HAL_INI_WRITE_ARRAY(ah, ar5212Bank2_5111, modesIndex, regWrites); /* Bank 3 Write */ HAL_INI_WRITE_ARRAY(ah, ar5212Bank3_5111, modesIndex, regWrites); /* Bank 6 Write */ for (i = 0; i < N(ar5212Bank6_5111); i++) rfReg[i] = ar5212Bank6_5111[i][modesIndex]; if (IS_CHAN_A(chan)) { /* NB: CHANNEL_A | CHANNEL_T */ ar5212ModifyRfBuffer(rfReg, ee->ee_cornerCal.pd84, 1, 51, 3); ar5212ModifyRfBuffer(rfReg, ee->ee_cornerCal.pd90, 1, 45, 3); } ar5212ModifyRfBuffer(rfReg, rfPwdXpd, 1, 95, 0); ar5212ModifyRfBuffer(rfReg, rfXpdGainFixed, 4, 96, 0); /* Set 5212 OB & DB */ ar5212ModifyRfBuffer(rfReg, tempOB, 3, 104, 0); ar5212ModifyRfBuffer(rfReg, tempDB, 3, 107, 0); HAL_INI_WRITE_BANK(ah, ar5212Bank6_5111, rfReg, regWrites); /* Bank 7 Write */ for (i = 0; i < N(ar5212Bank7_5111); i++) rfReg[i] = ar5212Bank7_5111[i][modesIndex]; ar5212ModifyRfBuffer(rfReg, gainI, 6, 29, 0); ar5212ModifyRfBuffer(rfReg, rfPloSel, 1, 4, 0); if (IS_CHAN_QUARTER_RATE(chan) || IS_CHAN_HALF_RATE(chan)) { uint32_t rfWaitI, rfWaitS, rfMaxTime; rfWaitS = 0x1f; rfWaitI = (IS_CHAN_HALF_RATE(chan)) ? 0x10 : 0x1f; rfMaxTime = 3; ar5212ModifyRfBuffer(rfReg, rfWaitS, 5, 19, 0); ar5212ModifyRfBuffer(rfReg, rfWaitI, 5, 24, 0); ar5212ModifyRfBuffer(rfReg, rfMaxTime, 2, 49, 0); } HAL_INI_WRITE_BANK(ah, ar5212Bank7_5111, rfReg, regWrites); /* Now that we have reprogrammed rfgain value, clear the flag. */ ahp->ah_rfgainState = HAL_RFGAIN_INACTIVE; return AH_TRUE;}/* * Returns interpolated or the scaled up interpolated value */static uint16_tinterpolate(uint16_t target, uint16_t srcLeft, uint16_t srcRight, uint16_t targetLeft, uint16_t targetRight){ uint16_t rv; int16_t lRatio; /* to get an accurate ratio, always scale, if want to scale, then don't scale back down */ if ((targetLeft * targetRight) == 0) return 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -