📄 ar2425.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: ar2425.c,v 1.8 2008/11/16 21:33:05 sam Exp $ */#include "opt_ah.h"#include "ah.h"#include "ah_internal.h"#include "ar5212/ar5212.h"#include "ar5212/ar5212reg.h"#include "ar5212/ar5212phy.h"#include "ah_eeprom_v3.h"#define AH_5212_2425#define AH_5212_2417#include "ar5212/ar5212.ini"#define N(a) (sizeof(a)/sizeof(a[0]))struct ar2425State { RF_HAL_FUNCS base; /* public state, must be first */ uint16_t pcdacTable[PWR_TABLE_SIZE_2413]; uint32_t Bank1Data[N(ar5212Bank1_2425)]; uint32_t Bank2Data[N(ar5212Bank2_2425)]; uint32_t Bank3Data[N(ar5212Bank3_2425)]; uint32_t Bank6Data[N(ar5212Bank6_2425)]; /* 2417 is same size */ uint32_t Bank7Data[N(ar5212Bank7_2425)];};#define AR2425(ah) ((struct ar2425State *) AH5212(ah)->ah_rfHal)extern void ar5212ModifyRfBuffer(uint32_t *rfBuf, uint32_t reg32, uint32_t numBits, uint32_t firstBit, uint32_t column);static voidar2425WriteRegs(struct ath_hal *ah, u_int modesIndex, u_int freqIndex, int writes){ HAL_INI_WRITE_ARRAY(ah, ar5212Modes_2425, modesIndex, writes); HAL_INI_WRITE_ARRAY(ah, ar5212Common_2425, 1, writes); HAL_INI_WRITE_ARRAY(ah, ar5212BB_RfGain_2425, freqIndex, writes);#if 0 /* * for SWAN similar to Condor * Bit 0 enables link to go to L1 when MAC goes to sleep. * Bit 3 enables the loop back the link down to reset. */ if (IS_PCIE(ah) && ath_hal_pcieL1SKPEnable) { OS_REG_WRITE(ah, AR_PCIE_PMC, AR_PCIE_PMC_ENA_L1 | AR_PCIE_PMC_ENA_RESET); } /* * for Standby issue in Swan/Condor. * Bit 9 (MAC_WOW_PWR_STATE_MASK_D2)to be set to avoid skips * before last Training Sequence 2 (TS2) * Bit 8 (MAC_WOW_PWR_STATE_MASK_D1)to be unset to assert * Power Reset along with PCI Reset */ OS_REG_SET_BIT(ah, AR_PCIE_PMC, MAC_WOW_PWR_STATE_MASK_D2);#endif}/* * Take the MHz channel value and set the Channel value * * ASSUMES: Writes enabled to analog bus */static HAL_BOOLar2425SetChannel(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan){ uint32_t channelSel = 0; uint32_t bModeSynth = 0; uint32_t aModeRefSel = 0; uint32_t reg32 = 0; uint16_t freq; OS_MARK(ah, AH_MARK_SETCHANNEL, chan->channel); if (chan->channel < 4800) { uint32_t txctl; channelSel = chan->channel - 2272; 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( (uint32_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(1, 2); } else if ((chan->channel % 10) == 0) { channelSel = ath_hal_reverseBits( ((chan->channel - 4800) / 10 << 1), 8); aModeRefSel = ath_hal_reverseBits(1, 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, HAL_DEBUG_ANY, "%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;}/* * Reads EEPROM header info from device structure and programs * all rf registers * * REQUIRES: Access to the analog rf device */static HAL_BOOLar2425SetRfRegs(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan, uint16_t modesIndex, uint16_t *rfXpdGain){#define RF_BANK_SETUP(_priv, _ix, _col) do { \ int i; \ for (i = 0; i < N(ar5212Bank##_ix##_2425); i++) \ (_priv)->Bank##_ix##Data[i] = ar5212Bank##_ix##_2425[i][_col];\} while (0) struct ath_hal_5212 *ahp = AH5212(ah); const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; struct ar2425State *priv = AR2425(ah); uint16_t ob2GHz = 0, db2GHz = 0; int regWrites = 0; HALDEBUG(ah, HAL_DEBUG_RFPARAM, "==>%s:chan 0x%x flag 0x%x modesIndex 0x%x\n", __func__, chan->channel, chan->channelFlags, modesIndex); HALASSERT(priv); /* Setup rf parameters */ switch (chan->channelFlags & CHANNEL_ALL) { case CHANNEL_B: ob2GHz = ee->ee_obFor24; db2GHz = ee->ee_dbFor24; break; case CHANNEL_G: case CHANNEL_108G: ob2GHz = ee->ee_obFor24g; db2GHz = ee->ee_dbFor24g; break; default: HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n", __func__, chan->channelFlags); return AH_FALSE; } /* Bank 1 Write */ RF_BANK_SETUP(priv, 1, 1); /* Bank 2 Write */ RF_BANK_SETUP(priv, 2, modesIndex); /* Bank 3 Write */ RF_BANK_SETUP(priv, 3, modesIndex); /* Bank 6 Write */ RF_BANK_SETUP(priv, 6, modesIndex); ar5212ModifyRfBuffer(priv->Bank6Data, ob2GHz, 3, 193, 0); ar5212ModifyRfBuffer(priv->Bank6Data, db2GHz, 3, 190, 0); /* Bank 7 Setup */ RF_BANK_SETUP(priv, 7, modesIndex); /* Write Analog registers */ HAL_INI_WRITE_BANK(ah, ar5212Bank1_2425, priv->Bank1Data, regWrites); HAL_INI_WRITE_BANK(ah, ar5212Bank2_2425, priv->Bank2Data, regWrites); HAL_INI_WRITE_BANK(ah, ar5212Bank3_2425, priv->Bank3Data, regWrites); if (IS_2417(ah)) { HALASSERT(N(ar5212Bank6_2425) == N(ar5212Bank6_2417)); HAL_INI_WRITE_BANK(ah, ar5212Bank6_2417, priv->Bank6Data, regWrites); } else HAL_INI_WRITE_BANK(ah, ar5212Bank6_2425, priv->Bank6Data, regWrites); HAL_INI_WRITE_BANK(ah, ar5212Bank7_2425, priv->Bank7Data, regWrites); /* Now that we have reprogrammed rfgain value, clear the flag. */ ahp->ah_rfgainState = HAL_RFGAIN_INACTIVE; HALDEBUG(ah, HAL_DEBUG_RFPARAM, "<==%s\n", __func__); return AH_TRUE;#undef RF_BANK_SETUP}/* * Return a reference to the requested RF Bank. */static uint32_t *ar2425GetRfBank(struct ath_hal *ah, int bank){ struct ar2425State *priv = AR2425(ah); HALASSERT(priv != AH_NULL); switch (bank) { 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;}/* * Return indices surrounding the value in sorted integer lists. * * NB: the input list is assumed to be sorted in ascending order */static voidGetLowerUpperIndex(int16_t v, const uint16_t *lp, uint16_t listSize, uint32_t *vlo, uint32_t *vhi){ int16_t target = v; const uint16_t *ep = lp+listSize; const uint16_t *tp; /* * Check first and last elements for out-of-bounds conditions. */ if (target < lp[0]) { *vlo = *vhi = 0; return; } if (target >= ep[-1]) { *vlo = *vhi = listSize - 1; return; } /* look for value being near or between 2 values in list */ for (tp = lp; tp < ep; tp++) { /* * If value is close to the current value of the list * then target is not between values, it is one of the values */ if (*tp == target) { *vlo = *vhi = tp - (const uint16_t *) lp; return; } /* * Look for value being between current value and next value * if so return these 2 values */ if (target < tp[1]) { *vlo = tp - (const uint16_t *) lp; *vhi = *vlo + 1; return; } }}/* * Fill the Vpdlist for indices Pmax-Pmin */static HAL_BOOLar2425FillVpdTable(uint32_t pdGainIdx, int16_t Pmin, int16_t Pmax, const int16_t *pwrList, const uint16_t *VpdList, uint16_t numIntercepts, uint16_t retVpdList[][64]){ uint16_t ii, jj, kk; int16_t currPwr = (int16_t)(2*Pmin); /* since Pmin is pwr*2 and pwrList is 4*pwr */ uint32_t idxL, idxR; ii = 0; jj = 0; if (numIntercepts < 2) return AH_FALSE; while (ii <= (uint16_t)(Pmax - Pmin)) { GetLowerUpperIndex(currPwr, (const uint16_t *) pwrList, numIntercepts, &(idxL), &(idxR)); if (idxR < 1) idxR = 1; /* extrapolate below */ if (idxL == (uint32_t)(numIntercepts - 1)) idxL = numIntercepts - 2; /* extrapolate above */ if (pwrList[idxL] == pwrList[idxR]) kk = VpdList[idxL]; else kk = (uint16_t) (((currPwr - pwrList[idxL])*VpdList[idxR]+ (pwrList[idxR] - currPwr)*VpdList[idxL])/ (pwrList[idxR] - pwrList[idxL])); retVpdList[pdGainIdx][ii] = kk; ii++; currPwr += 2; /* half dB steps */ } return AH_TRUE;}/* * Returns interpolated or the scaled up interpolated value */static int16_tinterpolate_signed(uint16_t target, uint16_t srcLeft, uint16_t srcRight, int16_t targetLeft, int16_t targetRight){ int16_t rv; if (srcRight != srcLeft) { rv = ((target - srcLeft)*targetRight + (srcRight - target)*targetLeft) / (srcRight - srcLeft); } else { rv = targetLeft; } return rv;}/* * Uses the data points read from EEPROM to reconstruct the pdadc power table * Called by ar2425SetPowerTable() */static void ar2425getGainBoundariesAndPdadcsForPowers(struct ath_hal *ah, uint16_t channel, const RAW_DATA_STRUCT_2413 *pRawDataset, uint16_t pdGainOverlap_t2,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -