ar5413.c revision 188979
189580Smsmith/* 289580Smsmith * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting 3120477Sscottl * Copyright (c) 2002-2008 Atheros Communications, Inc. 4120477Sscottl * 5120477Sscottl * Permission to use, copy, modify, and/or distribute this software for any 689580Smsmith * purpose with or without fee is hereby granted, provided that the above 789580Smsmith * copyright notice and this permission notice appear in all copies. 889580Smsmith * 989580Smsmith * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 1089580Smsmith * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 1189580Smsmith * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 1289580Smsmith * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 1389580Smsmith * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 1489580Smsmith * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 1589580Smsmith * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 1689580Smsmith * 1789580Smsmith * $FreeBSD: head/sys/dev/ath/ath_hal/ar5212/ar5413.c 188979 2009-02-24 01:07:06Z sam $ 1889580Smsmith */ 1989580Smsmith#include "opt_ah.h" 2089580Smsmith 2189580Smsmith#include "ah.h" 2289580Smsmith#include "ah_internal.h" 2389580Smsmith 2489580Smsmith#include "ah_eeprom_v3.h" 2589580Smsmith 2689580Smsmith#include "ar5212/ar5212.h" 2789580Smsmith#include "ar5212/ar5212reg.h" 2889580Smsmith#include "ar5212/ar5212phy.h" 2989580Smsmith 3089580Smsmith#define AH_5212_5413 3189580Smsmith#include "ar5212/ar5212.ini" 3289580Smsmith 3389580Smsmith#define N(a) (sizeof(a)/sizeof(a[0])) 3489580Smsmith 3589580Smsmithstruct ar5413State { 3689580Smsmith RF_HAL_FUNCS base; /* public state, must be first */ 3789580Smsmith uint16_t pcdacTable[PWR_TABLE_SIZE_2413]; 38120477Sscottl 3989580Smsmith uint32_t Bank1Data[N(ar5212Bank1_5413)]; 4089580Smsmith uint32_t Bank2Data[N(ar5212Bank2_5413)]; 4189580Smsmith uint32_t Bank3Data[N(ar5212Bank3_5413)]; 4289580Smsmith uint32_t Bank6Data[N(ar5212Bank6_5413)]; 43120477Sscottl uint32_t Bank7Data[N(ar5212Bank7_5413)]; 44120477Sscottl 4589580Smsmith /* 4689580Smsmith * Private state for reduced stack usage. 4789580Smsmith */ 4889580Smsmith /* filled out Vpd table for all pdGains (chanL) */ 4989580Smsmith uint16_t vpdTable_L[MAX_NUM_PDGAINS_PER_CHANNEL] 5089580Smsmith [MAX_PWR_RANGE_IN_HALF_DB]; 51120477Sscottl /* filled out Vpd table for all pdGains (chanR) */ 5289580Smsmith uint16_t vpdTable_R[MAX_NUM_PDGAINS_PER_CHANNEL] 5389580Smsmith [MAX_PWR_RANGE_IN_HALF_DB]; 5489580Smsmith /* filled out Vpd table for all pdGains (interpolated) */ 55120477Sscottl uint16_t vpdTable_I[MAX_NUM_PDGAINS_PER_CHANNEL] 56120477Sscottl [MAX_PWR_RANGE_IN_HALF_DB]; 57120477Sscottl}; 58120477Sscottl#define AR5413(ah) ((struct ar5413State *) AH5212(ah)->ah_rfHal) 5989580Smsmith 6089580Smsmithextern void ar5212ModifyRfBuffer(uint32_t *rfBuf, uint32_t reg32, 6189580Smsmith uint32_t numBits, uint32_t firstBit, uint32_t column); 6289580Smsmith 6389580Smsmithstatic void 6489580Smsmithar5413WriteRegs(struct ath_hal *ah, u_int modesIndex, u_int freqIndex, 6589580Smsmith int writes) 6689580Smsmith{ 6789580Smsmith HAL_INI_WRITE_ARRAY(ah, ar5212Modes_5413, modesIndex, writes); 6889580Smsmith HAL_INI_WRITE_ARRAY(ah, ar5212Common_5413, 1, writes); 6989580Smsmith HAL_INI_WRITE_ARRAY(ah, ar5212BB_RfGain_5413, freqIndex, writes); 7089580Smsmith} 7189580Smsmith 7289580Smsmith/* 7389580Smsmith * Take the MHz channel value and set the Channel value 7489580Smsmith * 7589580Smsmith * ASSUMES: Writes enabled to analog bus 7689580Smsmith */ 7789580Smsmithstatic HAL_BOOL 7889580Smsmithar5413SetChannel(struct ath_hal *ah, const struct ieee80211_channel *chan) 7989580Smsmith{ 8089580Smsmith uint16_t freq = ath_hal_gethwchannel(ah, chan); 8189580Smsmith uint32_t channelSel = 0; 8289580Smsmith uint32_t bModeSynth = 0; 8389580Smsmith uint32_t aModeRefSel = 0; 8489580Smsmith uint32_t reg32 = 0; 8589580Smsmith 8689580Smsmith OS_MARK(ah, AH_MARK_SETCHANNEL, freq); 8789580Smsmith 8889580Smsmith if (freq < 4800) { 8989580Smsmith uint32_t txctl; 9089580Smsmith 9189580Smsmith if (((freq - 2192) % 5) == 0) { 9289580Smsmith channelSel = ((freq - 672) * 2 - 3040)/10; 9389580Smsmith bModeSynth = 0; 9489580Smsmith } else if (((freq - 2224) % 5) == 0) { 9589580Smsmith channelSel = ((freq - 704) * 2 - 3040) / 10; 9689580Smsmith bModeSynth = 1; 9789580Smsmith } else { 9889580Smsmith HALDEBUG(ah, HAL_DEBUG_ANY, 9989580Smsmith "%s: invalid channel %u MHz\n", 10089580Smsmith __func__, freq); 10189580Smsmith return AH_FALSE; 10289580Smsmith } 10389580Smsmith 10489580Smsmith channelSel = (channelSel << 2) & 0xff; 10589580Smsmith channelSel = ath_hal_reverseBits(channelSel, 8); 10689580Smsmith 10789580Smsmith txctl = OS_REG_READ(ah, AR_PHY_CCK_TX_CTRL); 10889580Smsmith if (freq == 2484) { 10989580Smsmith /* Enable channel spreading for channel 14 */ 11089580Smsmith OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, 11189580Smsmith txctl | AR_PHY_CCK_TX_CTRL_JAPAN); 11289580Smsmith } else { 11389580Smsmith OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, 11489580Smsmith txctl &~ AR_PHY_CCK_TX_CTRL_JAPAN); 11589580Smsmith } 11689580Smsmith } else if (((freq % 5) == 2) && (freq <= 5435)) { 11789580Smsmith freq = freq - 2; /* Align to even 5MHz raster */ 11889580Smsmith channelSel = ath_hal_reverseBits( 11989580Smsmith (uint32_t)(((freq - 4800)*10)/25 + 1), 8); 12089580Smsmith aModeRefSel = ath_hal_reverseBits(0, 2); 12189580Smsmith } else if ((freq % 20) == 0 && freq >= 5120) { 12289580Smsmith channelSel = ath_hal_reverseBits( 12389580Smsmith ((freq - 4800) / 20 << 2), 8); 12489580Smsmith aModeRefSel = ath_hal_reverseBits(1, 2); 12589580Smsmith } else if ((freq % 10) == 0) { 12689580Smsmith channelSel = ath_hal_reverseBits( 12789580Smsmith ((freq - 4800) / 10 << 1), 8); 12889580Smsmith aModeRefSel = ath_hal_reverseBits(1, 2); 12989580Smsmith } else if ((freq % 5) == 0) { 13089580Smsmith channelSel = ath_hal_reverseBits( 13189580Smsmith (freq - 4800) / 5, 8); 13289580Smsmith aModeRefSel = ath_hal_reverseBits(1, 2); 13389580Smsmith } else { 13489580Smsmith HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel %u MHz\n", 13589580Smsmith __func__, freq); 13689580Smsmith return AH_FALSE; 13789580Smsmith } 13889580Smsmith 13989580Smsmith reg32 = (channelSel << 4) | (aModeRefSel << 2) | (bModeSynth << 1) | 14089580Smsmith (1 << 12) | 0x1; 14189580Smsmith OS_REG_WRITE(ah, AR_PHY(0x27), reg32 & 0xff); 14289580Smsmith 14389580Smsmith reg32 >>= 8; 14489580Smsmith OS_REG_WRITE(ah, AR_PHY(0x36), reg32 & 0x7f); 14589580Smsmith 14689580Smsmith AH_PRIVATE(ah)->ah_curchan = chan; 14789580Smsmith return AH_TRUE; 14889580Smsmith} 14989580Smsmith 150114001Sscottl/* 15189580Smsmith * Reads EEPROM header info from device structure and programs 15289580Smsmith * all rf registers 15389580Smsmith * 15489580Smsmith * REQUIRES: Access to the analog rf device 15589580Smsmith */ 15689580Smsmithstatic HAL_BOOL 157120477Sscottlar5413SetRfRegs(struct ath_hal *ah, 158120477Sscottl const struct ieee80211_channel *chan, 15989580Smsmith uint16_t modesIndex, uint16_t *rfXpdGain) 16089580Smsmith{ 16189580Smsmith#define RF_BANK_SETUP(_priv, _ix, _col) do { \ 16289580Smsmith int i; \ 16389580Smsmith for (i = 0; i < N(ar5212Bank##_ix##_5413); i++) \ 16489580Smsmith (_priv)->Bank##_ix##Data[i] = ar5212Bank##_ix##_5413[i][_col];\ 16589580Smsmith} while (0) 16689580Smsmith struct ath_hal_5212 *ahp = AH5212(ah); 16789580Smsmith uint16_t freq = ath_hal_gethwchannel(ah, chan); 16889580Smsmith const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; 16989580Smsmith uint16_t ob5GHz = 0, db5GHz = 0; 17089580Smsmith uint16_t ob2GHz = 0, db2GHz = 0; 17189580Smsmith struct ar5413State *priv = AR5413(ah); 17289580Smsmith int regWrites = 0; 17389580Smsmith 17489580Smsmith HALDEBUG(ah, HAL_DEBUG_RFPARAM, "%s: chan %u/0x%x modesIndex %u\n", 17589580Smsmith __func__, chan->ic_freq, chan->ic_flags, modesIndex); 17689580Smsmith 17789580Smsmith HALASSERT(priv != AH_NULL); 17889580Smsmith 17989580Smsmith /* Setup rf parameters */ 18089580Smsmith switch (chan->ic_flags & IEEE80211_CHAN_ALLFULL) { 18189580Smsmith case IEEE80211_CHAN_A: 18289580Smsmith if (freq > 4000 && freq < 5260) { 18389580Smsmith ob5GHz = ee->ee_ob1; 18489580Smsmith db5GHz = ee->ee_db1; 18589580Smsmith } else if (freq >= 5260 && freq < 5500) { 18689580Smsmith ob5GHz = ee->ee_ob2; 18789580Smsmith db5GHz = ee->ee_db2; 18889580Smsmith } else if (freq >= 5500 && freq < 5725) { 18989580Smsmith ob5GHz = ee->ee_ob3; 19089580Smsmith db5GHz = ee->ee_db3; 19189580Smsmith } else if (freq >= 5725) { 19289580Smsmith ob5GHz = ee->ee_ob4; 19389580Smsmith db5GHz = ee->ee_db4; 19489580Smsmith } else { 19589580Smsmith /* XXX else */ 19689580Smsmith } 19789580Smsmith break; 19889580Smsmith case IEEE80211_CHAN_B: 19989580Smsmith ob2GHz = ee->ee_obFor24; 20089580Smsmith db2GHz = ee->ee_dbFor24; 20189580Smsmith break; 20289580Smsmith case IEEE80211_CHAN_G: 20389580Smsmith case IEEE80211_CHAN_PUREG: /* NB: really 108G */ 20489580Smsmith ob2GHz = ee->ee_obFor24g; 20589580Smsmith db2GHz = ee->ee_dbFor24g; 20689580Smsmith break; 20789580Smsmith default: 20889580Smsmith HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n", 20989580Smsmith __func__, chan->ic_flags); 21089580Smsmith return AH_FALSE; 21189580Smsmith } 21289580Smsmith 21389580Smsmith /* Bank 1 Write */ 21489580Smsmith RF_BANK_SETUP(priv, 1, 1); 21589580Smsmith 21689580Smsmith /* Bank 2 Write */ 21789580Smsmith RF_BANK_SETUP(priv, 2, modesIndex); 21889580Smsmith 21989580Smsmith /* Bank 3 Write */ 22089580Smsmith RF_BANK_SETUP(priv, 3, modesIndex); 22189580Smsmith 22289580Smsmith /* Bank 6 Write */ 22389580Smsmith RF_BANK_SETUP(priv, 6, modesIndex); 22489580Smsmith 22589580Smsmith /* Only the 5 or 2 GHz OB/DB need to be set for a mode */ 22689580Smsmith if (IEEE80211_IS_CHAN_2GHZ(chan)) { 22789580Smsmith ar5212ModifyRfBuffer(priv->Bank6Data, ob2GHz, 3, 241, 0); 22889580Smsmith ar5212ModifyRfBuffer(priv->Bank6Data, db2GHz, 3, 238, 0); 22989580Smsmith 23089580Smsmith /* TODO - only for Eagle 1.0 2GHz - remove for production */ 23189580Smsmith /* XXX: but without this bit G doesn't work. */ 23289580Smsmith ar5212ModifyRfBuffer(priv->Bank6Data, 1 , 1, 291, 2); 23389580Smsmith 23489580Smsmith /* Optimum value for rf_pwd_iclobuf2G for PCIe chips only */ 23589580Smsmith if (AH_PRIVATE(ah)->ah_ispcie) { 23689580Smsmith ar5212ModifyRfBuffer(priv->Bank6Data, ath_hal_reverseBits(6, 3), 23789580Smsmith 3, 131, 3); 23889580Smsmith } 23989580Smsmith } else { 24089580Smsmith ar5212ModifyRfBuffer(priv->Bank6Data, ob5GHz, 3, 247, 0); 24189580Smsmith ar5212ModifyRfBuffer(priv->Bank6Data, db5GHz, 3, 244, 0); 24289580Smsmith 24389580Smsmith } 24489580Smsmith 24589580Smsmith /* Bank 7 Setup */ 24689580Smsmith RF_BANK_SETUP(priv, 7, modesIndex); 24789580Smsmith 24889580Smsmith /* Write Analog registers */ 24989580Smsmith HAL_INI_WRITE_BANK(ah, ar5212Bank1_5413, priv->Bank1Data, regWrites); 25089580Smsmith HAL_INI_WRITE_BANK(ah, ar5212Bank2_5413, priv->Bank2Data, regWrites); 25189580Smsmith HAL_INI_WRITE_BANK(ah, ar5212Bank3_5413, priv->Bank3Data, regWrites); 25289580Smsmith HAL_INI_WRITE_BANK(ah, ar5212Bank6_5413, priv->Bank6Data, regWrites); 25389580Smsmith HAL_INI_WRITE_BANK(ah, ar5212Bank7_5413, priv->Bank7Data, regWrites); 25489580Smsmith 25589580Smsmith /* Now that we have reprogrammed rfgain value, clear the flag. */ 25689580Smsmith ahp->ah_rfgainState = HAL_RFGAIN_INACTIVE; 25789580Smsmith 25889580Smsmith return AH_TRUE; 25989580Smsmith#undef RF_BANK_SETUP 26089580Smsmith} 26189580Smsmith 26289580Smsmith/* 26389580Smsmith * Return a reference to the requested RF Bank. 26489580Smsmith */ 26589580Smsmithstatic uint32_t * 26689580Smsmithar5413GetRfBank(struct ath_hal *ah, int bank) 26789580Smsmith{ 26889580Smsmith struct ar5413State *priv = AR5413(ah); 26989580Smsmith 27089580Smsmith HALASSERT(priv != AH_NULL); 27189580Smsmith switch (bank) { 27289580Smsmith case 1: return priv->Bank1Data; 27389580Smsmith case 2: return priv->Bank2Data; 27489580Smsmith case 3: return priv->Bank3Data; 27589580Smsmith case 6: return priv->Bank6Data; 27689580Smsmith case 7: return priv->Bank7Data; 27789580Smsmith } 27889580Smsmith HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unknown RF Bank %d requested\n", 27989580Smsmith __func__, bank); 28089580Smsmith return AH_NULL; 28189580Smsmith} 28289580Smsmith 28389580Smsmith/* 28489580Smsmith * Return indices surrounding the value in sorted integer lists. 28589580Smsmith * 28689580Smsmith * NB: the input list is assumed to be sorted in ascending order 28789580Smsmith */ 28889580Smsmithstatic void 28989580SmsmithGetLowerUpperIndex(int16_t v, const uint16_t *lp, uint16_t listSize, 29089580Smsmith uint32_t *vlo, uint32_t *vhi) 29189580Smsmith{ 29289580Smsmith int16_t target = v; 29389580Smsmith const uint16_t *ep = lp+listSize; 29489580Smsmith const uint16_t *tp; 29589580Smsmith 29689580Smsmith /* 29789580Smsmith * Check first and last elements for out-of-bounds conditions. 29889580Smsmith */ 29989580Smsmith if (target < lp[0]) { 30089580Smsmith *vlo = *vhi = 0; 30189580Smsmith return; 30289580Smsmith } 30389580Smsmith if (target >= ep[-1]) { 30489580Smsmith *vlo = *vhi = listSize - 1; 30589580Smsmith return; 30689580Smsmith } 30789580Smsmith 30889580Smsmith /* look for value being near or between 2 values in list */ 30989580Smsmith for (tp = lp; tp < ep; tp++) { 31089580Smsmith /* 31189580Smsmith * If value is close to the current value of the list 31289580Smsmith * then target is not between values, it is one of the values 31389580Smsmith */ 31489580Smsmith if (*tp == target) { 31589580Smsmith *vlo = *vhi = tp - (const uint16_t *) lp; 31689580Smsmith return; 31789580Smsmith } 31889580Smsmith /* 31989580Smsmith * Look for value being between current value and next value 32089580Smsmith * if so return these 2 values 32189580Smsmith */ 32289580Smsmith if (target < tp[1]) { 32389580Smsmith *vlo = tp - (const uint16_t *) lp; 32489580Smsmith *vhi = *vlo + 1; 32589580Smsmith return; 32689580Smsmith } 32789580Smsmith } 32889580Smsmith} 32989580Smsmith 33089580Smsmith/* 33189580Smsmith * Fill the Vpdlist for indices Pmax-Pmin 33289580Smsmith */ 33389580Smsmithstatic HAL_BOOL 33489580Smsmithar5413FillVpdTable(uint32_t pdGainIdx, int16_t Pmin, int16_t Pmax, 33589580Smsmith const int16_t *pwrList, const uint16_t *VpdList, 33689580Smsmith uint16_t numIntercepts, 33789580Smsmith uint16_t retVpdList[][64]) 33889580Smsmith{ 33989580Smsmith uint16_t ii, jj, kk; 34089580Smsmith int16_t currPwr = (int16_t)(2*Pmin); 34189580Smsmith /* since Pmin is pwr*2 and pwrList is 4*pwr */ 34289580Smsmith uint32_t idxL, idxR; 34389580Smsmith 34489580Smsmith ii = 0; 34589580Smsmith jj = 0; 34689580Smsmith 34789580Smsmith if (numIntercepts < 2) 34889580Smsmith return AH_FALSE; 34989580Smsmith 35089580Smsmith while (ii <= (uint16_t)(Pmax - Pmin)) { 35189580Smsmith GetLowerUpperIndex(currPwr, (const uint16_t *) pwrList, 35289580Smsmith numIntercepts, &(idxL), &(idxR)); 35389580Smsmith if (idxR < 1) 35489580Smsmith idxR = 1; /* extrapolate below */ 35589580Smsmith if (idxL == (uint32_t)(numIntercepts - 1)) 35689580Smsmith idxL = numIntercepts - 2; /* extrapolate above */ 35789580Smsmith if (pwrList[idxL] == pwrList[idxR]) 35889580Smsmith kk = VpdList[idxL]; 35989580Smsmith else 36089580Smsmith kk = (uint16_t) 36189580Smsmith (((currPwr - pwrList[idxL])*VpdList[idxR]+ 36289580Smsmith (pwrList[idxR] - currPwr)*VpdList[idxL])/ 36389580Smsmith (pwrList[idxR] - pwrList[idxL])); 36489580Smsmith retVpdList[pdGainIdx][ii] = kk; 36589580Smsmith ii++; 36689580Smsmith currPwr += 2; /* half dB steps */ 36789580Smsmith } 36889580Smsmith 36989580Smsmith return AH_TRUE; 37089580Smsmith} 37189580Smsmith 37289580Smsmith/* 37389580Smsmith * Returns interpolated or the scaled up interpolated value 37489580Smsmith */ 37589580Smsmithstatic int16_t 37689580Smsmithinterpolate_signed(uint16_t target, uint16_t srcLeft, uint16_t srcRight, 37789580Smsmith int16_t targetLeft, int16_t targetRight) 37889580Smsmith{ 37989580Smsmith int16_t rv; 38089580Smsmith 38189580Smsmith if (srcRight != srcLeft) { 38289580Smsmith rv = ((target - srcLeft)*targetRight + 38389580Smsmith (srcRight - target)*targetLeft) / (srcRight - srcLeft); 38489580Smsmith } else { 38589580Smsmith rv = targetLeft; 38689580Smsmith } 38789580Smsmith return rv; 38889580Smsmith} 38989580Smsmith 39089580Smsmith/* 39189580Smsmith * Uses the data points read from EEPROM to reconstruct the pdadc power table 39289580Smsmith * Called by ar5413SetPowerTable() 39389580Smsmith */ 39489580Smsmithstatic int 39589580Smsmithar5413getGainBoundariesAndPdadcsForPowers(struct ath_hal *ah, uint16_t channel, 39689580Smsmith const RAW_DATA_STRUCT_2413 *pRawDataset, 39789580Smsmith uint16_t pdGainOverlap_t2, 39889580Smsmith int16_t *pMinCalPower, uint16_t pPdGainBoundaries[], 39989580Smsmith uint16_t pPdGainValues[], uint16_t pPDADCValues[]) 40089580Smsmith{ 40189580Smsmith struct ar5413State *priv = AR5413(ah); 40289580Smsmith#define VpdTable_L priv->vpdTable_L 40389580Smsmith#define VpdTable_R priv->vpdTable_R 40489580Smsmith#define VpdTable_I priv->vpdTable_I 40589580Smsmith uint32_t ii, jj, kk; 40689580Smsmith int32_t ss;/* potentially -ve index for taking care of pdGainOverlap */ 40789580Smsmith uint32_t idxL, idxR; 40889580Smsmith uint32_t numPdGainsUsed = 0; 40989580Smsmith /* 41089580Smsmith * If desired to support -ve power levels in future, just 41189580Smsmith * change pwr_I_0 to signed 5-bits. 41289580Smsmith */ 41389580Smsmith int16_t Pmin_t2[MAX_NUM_PDGAINS_PER_CHANNEL]; 41489580Smsmith /* to accomodate -ve power levels later on. */ 41589580Smsmith int16_t Pmax_t2[MAX_NUM_PDGAINS_PER_CHANNEL]; 41689580Smsmith /* to accomodate -ve power levels later on */ 41789580Smsmith uint16_t numVpd = 0; 41889580Smsmith uint16_t Vpd_step; 41989580Smsmith int16_t tmpVal ; 42089580Smsmith uint32_t sizeCurrVpdTable, maxIndex, tgtIndex; 42189580Smsmith 42289580Smsmith /* Get upper lower index */ 42389580Smsmith GetLowerUpperIndex(channel, pRawDataset->pChannels, 42489580Smsmith pRawDataset->numChannels, &(idxL), &(idxR)); 42589580Smsmith 42689580Smsmith for (ii = 0; ii < MAX_NUM_PDGAINS_PER_CHANNEL; ii++) { 42789580Smsmith jj = MAX_NUM_PDGAINS_PER_CHANNEL - ii - 1; 42889580Smsmith /* work backwards 'cause highest pdGain for lowest power */ 42989580Smsmith numVpd = pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].numVpd; 43089580Smsmith if (numVpd > 0) { 43189580Smsmith pPdGainValues[numPdGainsUsed] = pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].pd_gain; 43289580Smsmith Pmin_t2[numPdGainsUsed] = pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].pwr_t4[0]; 43389580Smsmith if (Pmin_t2[numPdGainsUsed] >pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[0]) { 43489580Smsmith Pmin_t2[numPdGainsUsed] = pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[0]; 43589580Smsmith } 43689580Smsmith Pmin_t2[numPdGainsUsed] = (int16_t) 43789580Smsmith (Pmin_t2[numPdGainsUsed] / 2); 43889580Smsmith Pmax_t2[numPdGainsUsed] = pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].pwr_t4[numVpd-1]; 43989580Smsmith if (Pmax_t2[numPdGainsUsed] > pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[numVpd-1]) 44089580Smsmith Pmax_t2[numPdGainsUsed] = 44189580Smsmith pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[numVpd-1]; 44289580Smsmith Pmax_t2[numPdGainsUsed] = (int16_t)(Pmax_t2[numPdGainsUsed] / 2); 44389580Smsmith ar5413FillVpdTable( 44489580Smsmith numPdGainsUsed, Pmin_t2[numPdGainsUsed], Pmax_t2[numPdGainsUsed], 44589580Smsmith &(pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].pwr_t4[0]), 44689580Smsmith &(pRawDataset->pDataPerChannel[idxL].pDataPerPDGain[jj].Vpd[0]), numVpd, VpdTable_L 44789580Smsmith ); 44889580Smsmith ar5413FillVpdTable( 44989580Smsmith numPdGainsUsed, Pmin_t2[numPdGainsUsed], Pmax_t2[numPdGainsUsed], 45089580Smsmith &(pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].pwr_t4[0]), 45189580Smsmith &(pRawDataset->pDataPerChannel[idxR].pDataPerPDGain[jj].Vpd[0]), numVpd, VpdTable_R 45289580Smsmith ); 45389580Smsmith for (kk = 0; kk < (uint16_t)(Pmax_t2[numPdGainsUsed] - Pmin_t2[numPdGainsUsed]); kk++) { 45489580Smsmith VpdTable_I[numPdGainsUsed][kk] = 45589580Smsmith interpolate_signed( 45689580Smsmith channel, pRawDataset->pChannels[idxL], pRawDataset->pChannels[idxR], 45789580Smsmith (int16_t)VpdTable_L[numPdGainsUsed][kk], (int16_t)VpdTable_R[numPdGainsUsed][kk]); 45889580Smsmith } 45989580Smsmith /* fill VpdTable_I for this pdGain */ 46089580Smsmith numPdGainsUsed++; 46189580Smsmith } 46289580Smsmith /* if this pdGain is used */ 463114001Sscottl } 464114001Sscottl 465114001Sscottl *pMinCalPower = Pmin_t2[0]; 466114001Sscottl kk = 0; /* index for the final table */ 467114001Sscottl for (ii = 0; ii < numPdGainsUsed; ii++) { 468114001Sscottl if (ii == (numPdGainsUsed - 1)) 469114001Sscottl pPdGainBoundaries[ii] = Pmax_t2[ii] + 470114001Sscottl PD_GAIN_BOUNDARY_STRETCH_IN_HALF_DB; 471114001Sscottl else 472114001Sscottl pPdGainBoundaries[ii] = (uint16_t) 473114001Sscottl ((Pmax_t2[ii] + Pmin_t2[ii+1]) / 2 ); 474114001Sscottl if (pPdGainBoundaries[ii] > 63) { 475114001Sscottl HALDEBUG(ah, HAL_DEBUG_ANY, 476114001Sscottl "%s: clamp pPdGainBoundaries[%d] %d\n", 477114001Sscottl __func__, ii, pPdGainBoundaries[ii]);/*XXX*/ 478114001Sscottl pPdGainBoundaries[ii] = 63; 479114001Sscottl } 480114001Sscottl 481114001Sscottl /* Find starting index for this pdGain */ 482114001Sscottl if (ii == 0) 483114001Sscottl ss = 0; /* for the first pdGain, start from index 0 */ 484114001Sscottl else 485114001Sscottl ss = (pPdGainBoundaries[ii-1] - Pmin_t2[ii]) - 486114001Sscottl pdGainOverlap_t2; 487114001Sscottl Vpd_step = (uint16_t)(VpdTable_I[ii][1] - VpdTable_I[ii][0]); 488114001Sscottl Vpd_step = (uint16_t)((Vpd_step < 1) ? 1 : Vpd_step); 489114001Sscottl /* 490114001Sscottl *-ve ss indicates need to extrapolate data below for this pdGain 491114001Sscottl */ 492114001Sscottl while (ss < 0) { 493114001Sscottl tmpVal = (int16_t)(VpdTable_I[ii][0] + ss*Vpd_step); 494114001Sscottl pPDADCValues[kk++] = (uint16_t)((tmpVal < 0) ? 0 : tmpVal); 495114001Sscottl ss++; 496114001Sscottl } 497114001Sscottl 498114001Sscottl sizeCurrVpdTable = Pmax_t2[ii] - Pmin_t2[ii]; 499114001Sscottl tgtIndex = pPdGainBoundaries[ii] + pdGainOverlap_t2 - Pmin_t2[ii]; 500114001Sscottl maxIndex = (tgtIndex < sizeCurrVpdTable) ? tgtIndex : sizeCurrVpdTable; 501114001Sscottl 502114001Sscottl while (ss < (int16_t)maxIndex) 503114001Sscottl pPDADCValues[kk++] = VpdTable_I[ii][ss++]; 504114001Sscottl 505114001Sscottl Vpd_step = (uint16_t)(VpdTable_I[ii][sizeCurrVpdTable-1] - 506114001Sscottl VpdTable_I[ii][sizeCurrVpdTable-2]); 507114001Sscottl Vpd_step = (uint16_t)((Vpd_step < 1) ? 1 : Vpd_step); 508114001Sscottl /* 50989580Smsmith * for last gain, pdGainBoundary == Pmax_t2, so will 51089580Smsmith * have to extrapolate 51189580Smsmith */ 51289580Smsmith if (tgtIndex > maxIndex) { /* need to extrapolate above */ 51389580Smsmith while(ss < (int16_t)tgtIndex) { 51489580Smsmith tmpVal = (uint16_t) 51589580Smsmith (VpdTable_I[ii][sizeCurrVpdTable-1] + 51689580Smsmith (ss-maxIndex)*Vpd_step); 51789580Smsmith pPDADCValues[kk++] = (tmpVal > 127) ? 51889580Smsmith 127 : tmpVal; 51989580Smsmith ss++; 52089580Smsmith } 52189580Smsmith } /* extrapolated above */ 52289580Smsmith } /* for all pdGainUsed */ 52389580Smsmith 52489580Smsmith while (ii < MAX_NUM_PDGAINS_PER_CHANNEL) { 52589580Smsmith pPdGainBoundaries[ii] = pPdGainBoundaries[ii-1]; 52689580Smsmith ii++; 52789580Smsmith } 52889580Smsmith while (kk < 128) { 52989580Smsmith pPDADCValues[kk] = pPDADCValues[kk-1]; 53089580Smsmith kk++; 53189580Smsmith } 53289580Smsmith 53389580Smsmith return numPdGainsUsed; 53489580Smsmith#undef VpdTable_L 53589580Smsmith#undef VpdTable_R 53689580Smsmith#undef VpdTable_I 53789580Smsmith} 53889580Smsmith 53989580Smsmithstatic HAL_BOOL 54089580Smsmithar5413SetPowerTable(struct ath_hal *ah, 54189580Smsmith int16_t *minPower, int16_t *maxPower, 54289580Smsmith const struct ieee80211_channel *chan, 54389580Smsmith uint16_t *rfXpdGain) 54489580Smsmith{ 54589580Smsmith struct ath_hal_5212 *ahp = AH5212(ah); 54689580Smsmith uint16_t freq = ath_hal_gethwchannel(ah, chan); 54789580Smsmith const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; 54889580Smsmith const RAW_DATA_STRUCT_2413 *pRawDataset = AH_NULL; 54989580Smsmith uint16_t pdGainOverlap_t2; 55089580Smsmith int16_t minCalPower5413_t2; 55189580Smsmith uint16_t *pdadcValues = ahp->ah_pcdacTable; 55289580Smsmith uint16_t gainBoundaries[4]; 55389580Smsmith uint32_t reg32, regoffset; 55489580Smsmith int i, numPdGainsUsed; 55589580Smsmith#ifndef AH_USE_INIPDGAIN 55689580Smsmith uint32_t tpcrg1; 55789580Smsmith#endif 55889580Smsmith 55989580Smsmith HALDEBUG(ah, HAL_DEBUG_RFPARAM, "%s: chan 0x%x flag 0x%x\n", 56089580Smsmith __func__, chan->ic_freq, chan->ic_flags); 56189580Smsmith 56289580Smsmith if (IEEE80211_IS_CHAN_G(chan) || IEEE80211_IS_CHAN_108G(chan)) 56389580Smsmith pRawDataset = &ee->ee_rawDataset2413[headerInfo11G]; 56489580Smsmith else if (IEEE80211_IS_CHAN_B(chan)) 56589580Smsmith pRawDataset = &ee->ee_rawDataset2413[headerInfo11B]; 56689580Smsmith else { 56789580Smsmith HALASSERT(IEEE80211_IS_CHAN_5GHZ(chan)); 56889580Smsmith pRawDataset = &ee->ee_rawDataset2413[headerInfo11A]; 56989580Smsmith } 57089580Smsmith 57189580Smsmith pdGainOverlap_t2 = (uint16_t) SM(OS_REG_READ(ah, AR_PHY_TPCRG5), 57289580Smsmith AR_PHY_TPCRG5_PD_GAIN_OVERLAP); 57389580Smsmith 57489580Smsmith numPdGainsUsed = ar5413getGainBoundariesAndPdadcsForPowers(ah, 57589580Smsmith freq, pRawDataset, pdGainOverlap_t2, 57689580Smsmith &minCalPower5413_t2,gainBoundaries, rfXpdGain, pdadcValues); 57789580Smsmith HALASSERT(1 <= numPdGainsUsed && numPdGainsUsed <= 3); 57889580Smsmith 57989580Smsmith#ifdef AH_USE_INIPDGAIN 58089580Smsmith /* 58189580Smsmith * Use pd_gains curve from eeprom; Atheros always uses 58289580Smsmith * the default curve from the ini file but some vendors 58389580Smsmith * (e.g. Zcomax) want to override this curve and not 58489580Smsmith * honoring their settings results in tx power 5dBm low. 58589580Smsmith */ 58689580Smsmith OS_REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN, 58789580Smsmith (pRawDataset->pDataPerChannel[0].numPdGains - 1)); 58889580Smsmith#else 58989580Smsmith tpcrg1 = OS_REG_READ(ah, AR_PHY_TPCRG1); 59089580Smsmith tpcrg1 = (tpcrg1 &~ AR_PHY_TPCRG1_NUM_PD_GAIN) 59189580Smsmith | SM(numPdGainsUsed-1, AR_PHY_TPCRG1_NUM_PD_GAIN); 59289580Smsmith switch (numPdGainsUsed) { 59389580Smsmith case 3: 59489580Smsmith tpcrg1 &= ~AR_PHY_TPCRG1_PDGAIN_SETTING3; 59589580Smsmith tpcrg1 |= SM(rfXpdGain[2], AR_PHY_TPCRG1_PDGAIN_SETTING3); 596114001Sscottl /* fall thru... */ 59789580Smsmith case 2: 59889580Smsmith tpcrg1 &= ~AR_PHY_TPCRG1_PDGAIN_SETTING2; 59989580Smsmith tpcrg1 |= SM(rfXpdGain[1], AR_PHY_TPCRG1_PDGAIN_SETTING2); 60089580Smsmith /* fall thru... */ 60189580Smsmith case 1: 60289580Smsmith tpcrg1 &= ~AR_PHY_TPCRG1_PDGAIN_SETTING1; 60389580Smsmith tpcrg1 |= SM(rfXpdGain[0], AR_PHY_TPCRG1_PDGAIN_SETTING1); 60489580Smsmith break; 60589580Smsmith } 60689580Smsmith#ifdef AH_DEBUG 60789580Smsmith if (tpcrg1 != OS_REG_READ(ah, AR_PHY_TPCRG1)) 60889580Smsmith HALDEBUG(ah, HAL_DEBUG_RFPARAM, "%s: using non-default " 60989580Smsmith "pd_gains (default 0x%x, calculated 0x%x)\n", 61089580Smsmith __func__, OS_REG_READ(ah, AR_PHY_TPCRG1), tpcrg1); 61189580Smsmith#endif 61289580Smsmith OS_REG_WRITE(ah, AR_PHY_TPCRG1, tpcrg1); 61389580Smsmith#endif 61489580Smsmith 61589580Smsmith /* 61689580Smsmith * Note the pdadc table may not start at 0 dBm power, could be 61789580Smsmith * negative or greater than 0. Need to offset the power 61889580Smsmith * values by the amount of minPower for griffin 61989580Smsmith */ 62089580Smsmith if (minCalPower5413_t2 != 0) 62189580Smsmith ahp->ah_txPowerIndexOffset = (int16_t)(0 - minCalPower5413_t2); 62289580Smsmith else 62389580Smsmith ahp->ah_txPowerIndexOffset = 0; 62489580Smsmith 62589580Smsmith /* Finally, write the power values into the baseband power table */ 62689580Smsmith regoffset = 0x9800 + (672 <<2); /* beginning of pdadc table in griffin */ 62789580Smsmith for (i = 0; i < 32; i++) { 62889580Smsmith reg32 = ((pdadcValues[4*i + 0] & 0xFF) << 0) | 62989580Smsmith ((pdadcValues[4*i + 1] & 0xFF) << 8) | 63089580Smsmith ((pdadcValues[4*i + 2] & 0xFF) << 16) | 63189580Smsmith ((pdadcValues[4*i + 3] & 0xFF) << 24) ; 63289580Smsmith OS_REG_WRITE(ah, regoffset, reg32); 63389580Smsmith regoffset += 4; 63489580Smsmith } 63589580Smsmith 63689580Smsmith OS_REG_WRITE(ah, AR_PHY_TPCRG5, 63789580Smsmith SM(pdGainOverlap_t2, AR_PHY_TPCRG5_PD_GAIN_OVERLAP) | 63889580Smsmith SM(gainBoundaries[0], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1) | 63989580Smsmith SM(gainBoundaries[1], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2) | 64089580Smsmith SM(gainBoundaries[2], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3) | 64189580Smsmith SM(gainBoundaries[3], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4)); 64289580Smsmith 64389580Smsmith return AH_TRUE; 64489580Smsmith} 64589580Smsmith 64689580Smsmithstatic int16_t 64789580Smsmithar5413GetMinPower(struct ath_hal *ah, const RAW_DATA_PER_CHANNEL_2413 *data) 64889580Smsmith{ 64989580Smsmith uint32_t ii,jj; 65089580Smsmith uint16_t Pmin=0,numVpd; 65189580Smsmith 65289580Smsmith for (ii = 0; ii < MAX_NUM_PDGAINS_PER_CHANNEL; ii++) { 65389580Smsmith jj = MAX_NUM_PDGAINS_PER_CHANNEL - ii - 1; 65489580Smsmith /* work backwards 'cause highest pdGain for lowest power */ 65589580Smsmith numVpd = data->pDataPerPDGain[jj].numVpd; 65689580Smsmith if (numVpd > 0) { 65789580Smsmith Pmin = data->pDataPerPDGain[jj].pwr_t4[0]; 658114001Sscottl return(Pmin); 65989580Smsmith } 66089580Smsmith } 66189580Smsmith return(Pmin); 66289580Smsmith} 66392739Salfred 66492739Salfredstatic int16_t 66592739Salfredar5413GetMaxPower(struct ath_hal *ah, const RAW_DATA_PER_CHANNEL_2413 *data) 66692739Salfred{ 66792739Salfred uint32_t ii; 66892739Salfred uint16_t Pmax=0,numVpd; 66989580Smsmith 67089580Smsmith for (ii=0; ii< MAX_NUM_PDGAINS_PER_CHANNEL; ii++) { 67189580Smsmith /* work forwards cuase lowest pdGain for highest power */ 67289580Smsmith numVpd = data->pDataPerPDGain[ii].numVpd; 67389580Smsmith if (numVpd > 0) { 67489580Smsmith Pmax = data->pDataPerPDGain[ii].pwr_t4[numVpd-1]; 67589580Smsmith return(Pmax); 67689580Smsmith } 67789580Smsmith } 67889580Smsmith return(Pmax); 67989580Smsmith} 68089580Smsmith 68189580Smsmithstatic HAL_BOOL 68289580Smsmithar5413GetChannelMaxMinPower(struct ath_hal *ah, 68389580Smsmith const struct ieee80211_channel *chan, 68489580Smsmith int16_t *maxPow, int16_t *minPow) 68589580Smsmith{ 68689580Smsmith uint16_t freq = chan->ic_freq; /* NB: never mapped */ 68789580Smsmith const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; 68889580Smsmith const RAW_DATA_STRUCT_2413 *pRawDataset = AH_NULL; 68989580Smsmith const RAW_DATA_PER_CHANNEL_2413 *data=AH_NULL; 69089580Smsmith uint16_t numChannels; 69189580Smsmith int totalD,totalF, totalMin,last, i; 69289580Smsmith 69389580Smsmith *maxPow = 0; 69489580Smsmith 69589580Smsmith if (IEEE80211_IS_CHAN_G(chan) || IEEE80211_IS_CHAN_108G(chan)) 69689580Smsmith pRawDataset = &ee->ee_rawDataset2413[headerInfo11G]; 69792739Salfred else if (IEEE80211_IS_CHAN_B(chan)) 69892739Salfred pRawDataset = &ee->ee_rawDataset2413[headerInfo11B]; 69992739Salfred else { 70092739Salfred HALASSERT(IEEE80211_IS_CHAN_5GHZ(chan)); 70189580Smsmith pRawDataset = &ee->ee_rawDataset2413[headerInfo11A]; 70289580Smsmith } 70389580Smsmith 70492739Salfred numChannels = pRawDataset->numChannels; 70592739Salfred data = pRawDataset->pDataPerChannel; 70692739Salfred 70792739Salfred /* Make sure the channel is in the range of the TP values 70889580Smsmith * (freq piers) 70989580Smsmith */ 71089580Smsmith if (numChannels < 1) 71189580Smsmith return(AH_FALSE); 71289580Smsmith 71389580Smsmith if ((freq < data[0].channelValue) || 71489580Smsmith (freq > data[numChannels-1].channelValue)) { 71589580Smsmith if (freq < data[0].channelValue) { 71689580Smsmith *maxPow = ar5413GetMaxPower(ah, &data[0]); 71789580Smsmith *minPow = ar5413GetMinPower(ah, &data[0]); 71889580Smsmith return(AH_TRUE); 71989580Smsmith } else { 72089580Smsmith *maxPow = ar5413GetMaxPower(ah, &data[numChannels - 1]); 72189580Smsmith *minPow = ar5413GetMinPower(ah, &data[numChannels - 1]); 72289580Smsmith return(AH_TRUE); 72389580Smsmith } 72489580Smsmith } 72589580Smsmith 72689580Smsmith /* Linearly interpolate the power value now */ 72789580Smsmith for (last=0,i=0; (i<numChannels) && (freq > data[i].channelValue); 72889580Smsmith last = i++); 729114001Sscottl totalD = data[i].channelValue - data[last].channelValue; 73089580Smsmith if (totalD > 0) { 73189580Smsmith totalF = ar5413GetMaxPower(ah, &data[i]) - ar5413GetMaxPower(ah, &data[last]); 73289580Smsmith *maxPow = (int8_t) ((totalF*(freq-data[last].channelValue) + 73389580Smsmith ar5413GetMaxPower(ah, &data[last])*totalD)/totalD); 73489580Smsmith totalMin = ar5413GetMinPower(ah, &data[i]) - ar5413GetMinPower(ah, &data[last]); 73589580Smsmith *minPow = (int8_t) ((totalMin*(freq-data[last].channelValue) + 736114001Sscottl ar5413GetMinPower(ah, &data[last])*totalD)/totalD); 73789580Smsmith return(AH_TRUE); 73889580Smsmith } else { 73989580Smsmith if (freq == data[i].channelValue) { 74089580Smsmith *maxPow = ar5413GetMaxPower(ah, &data[i]); 74189580Smsmith *minPow = ar5413GetMinPower(ah, &data[i]); 74289580Smsmith return(AH_TRUE); 74389580Smsmith } else 74489580Smsmith return(AH_FALSE); 74589580Smsmith } 74689580Smsmith} 74789580Smsmith 74889580Smsmith/* 74989580Smsmith * Free memory for analog bank scratch buffers 75089580Smsmith */ 75189580Smsmithstatic void 75289580Smsmithar5413RfDetach(struct ath_hal *ah) 75389580Smsmith{ 75489580Smsmith struct ath_hal_5212 *ahp = AH5212(ah); 75589580Smsmith 75689580Smsmith HALASSERT(ahp->ah_rfHal != AH_NULL); 75789580Smsmith ath_hal_free(ahp->ah_rfHal); 75889580Smsmith ahp->ah_rfHal = AH_NULL; 75989580Smsmith} 76089580Smsmith 761/* 762 * Allocate memory for analog bank scratch buffers 763 * Scratch Buffer will be reinitialized every reset so no need to zero now 764 */ 765static HAL_BOOL 766ar5413RfAttach(struct ath_hal *ah, HAL_STATUS *status) 767{ 768 struct ath_hal_5212 *ahp = AH5212(ah); 769 struct ar5413State *priv; 770 771 HALASSERT(ah->ah_magic == AR5212_MAGIC); 772 773 HALASSERT(ahp->ah_rfHal == AH_NULL); 774 priv = ath_hal_malloc(sizeof(struct ar5413State)); 775 if (priv == AH_NULL) { 776 HALDEBUG(ah, HAL_DEBUG_ANY, 777 "%s: cannot allocate private state\n", __func__); 778 *status = HAL_ENOMEM; /* XXX */ 779 return AH_FALSE; 780 } 781 priv->base.rfDetach = ar5413RfDetach; 782 priv->base.writeRegs = ar5413WriteRegs; 783 priv->base.getRfBank = ar5413GetRfBank; 784 priv->base.setChannel = ar5413SetChannel; 785 priv->base.setRfRegs = ar5413SetRfRegs; 786 priv->base.setPowerTable = ar5413SetPowerTable; 787 priv->base.getChannelMaxMinPower = ar5413GetChannelMaxMinPower; 788 priv->base.getNfAdjust = ar5212GetNfAdjust; 789 790 ahp->ah_pcdacTable = priv->pcdacTable; 791 ahp->ah_pcdacTableSize = sizeof(priv->pcdacTable); 792 ahp->ah_rfHal = &priv->base; 793 794 return AH_TRUE; 795} 796 797static HAL_BOOL 798ar5413Probe(struct ath_hal *ah) 799{ 800 return IS_5413(ah); 801} 802AH_RF(RF5413, ar5413Probe, ar5413RfAttach); 803