ar2133.c revision 223459
1185377Ssam/* 2187831Ssam * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting 3185377Ssam * Copyright (c) 2002-2008 Atheros Communications, Inc. 4185377Ssam * 5185377Ssam * Permission to use, copy, modify, and/or distribute this software for any 6185377Ssam * purpose with or without fee is hereby granted, provided that the above 7185377Ssam * copyright notice and this permission notice appear in all copies. 8185377Ssam * 9185377Ssam * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10185377Ssam * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11185377Ssam * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12185377Ssam * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13185377Ssam * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14185377Ssam * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15185377Ssam * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16185377Ssam * 17187831Ssam * $FreeBSD: head/sys/dev/ath/ath_hal/ar5416/ar2133.c 223459 2011-06-23 02:38:36Z adrian $ 18185377Ssam */ 19185377Ssam#include "opt_ah.h" 20185377Ssam 21185377Ssam#include "ah.h" 22185377Ssam#include "ah_internal.h" 23185377Ssam 24185377Ssam#include "ah_eeprom_v14.h" 25185377Ssam 26185377Ssam#include "ar5416/ar5416.h" 27185377Ssam#include "ar5416/ar5416reg.h" 28185377Ssam#include "ar5416/ar5416phy.h" 29185377Ssam 30185377Ssam#define N(a) (sizeof(a)/sizeof(a[0])) 31185377Ssam 32185377Ssamstruct ar2133State { 33185377Ssam RF_HAL_FUNCS base; /* public state, must be first */ 34185377Ssam uint16_t pcdacTable[1]; 35185377Ssam 36185377Ssam uint32_t *Bank0Data; 37185377Ssam uint32_t *Bank1Data; 38185377Ssam uint32_t *Bank2Data; 39185377Ssam uint32_t *Bank3Data; 40185377Ssam uint32_t *Bank6Data; 41185377Ssam uint32_t *Bank7Data; 42185377Ssam 43185377Ssam /* NB: Bank*Data storage follows */ 44185377Ssam}; 45185377Ssam#define AR2133(ah) ((struct ar2133State *) AH5212(ah)->ah_rfHal) 46185377Ssam 47185377Ssam#define ar5416ModifyRfBuffer ar5212ModifyRfBuffer /*XXX*/ 48185377Ssam 49187831Ssamvoid ar5416ModifyRfBuffer(uint32_t *rfBuf, uint32_t reg32, 50187831Ssam uint32_t numBits, uint32_t firstBit, uint32_t column); 51185377Ssam 52185377Ssamstatic void 53185377Ssamar2133WriteRegs(struct ath_hal *ah, u_int modesIndex, u_int freqIndex, 54185377Ssam int writes) 55185377Ssam{ 56185377Ssam (void) ath_hal_ini_write(ah, &AH5416(ah)->ah_ini_bb_rfgain, 57185377Ssam freqIndex, writes); 58185377Ssam} 59185377Ssam 60185377Ssam/* 61217881Sadrian * Fix on 2.4 GHz band for orientation sensitivity issue by increasing 62217881Sadrian * rf_pwd_icsyndiv. 63217881Sadrian * 64217881Sadrian * Theoretical Rules: 65217881Sadrian * if 2 GHz band 66217881Sadrian * if forceBiasAuto 67217881Sadrian * if synth_freq < 2412 68217881Sadrian * bias = 0 69217881Sadrian * else if 2412 <= synth_freq <= 2422 70217881Sadrian * bias = 1 71217881Sadrian * else // synth_freq > 2422 72217881Sadrian * bias = 2 73217881Sadrian * else if forceBias > 0 74217881Sadrian * bias = forceBias & 7 75217881Sadrian * else 76217881Sadrian * no change, use value from ini file 77217881Sadrian * else 78217881Sadrian * no change, invalid band 79217881Sadrian * 80217881Sadrian * 1st Mod: 81217881Sadrian * 2422 also uses value of 2 82217881Sadrian * <approved> 83217881Sadrian * 84217881Sadrian * 2nd Mod: 85217881Sadrian * Less than 2412 uses value of 0, 2412 and above uses value of 2 86217881Sadrian */ 87217881Sadrianstatic void 88217881Sadrianar2133ForceBias(struct ath_hal *ah, uint16_t synth_freq) 89217881Sadrian{ 90217881Sadrian uint32_t tmp_reg; 91217881Sadrian int reg_writes = 0; 92217881Sadrian uint32_t new_bias = 0; 93217881Sadrian struct ar2133State *priv = AR2133(ah); 94217881Sadrian 95217881Sadrian /* XXX this is a bit of a silly check for 2.4ghz channels -adrian */ 96217881Sadrian if (synth_freq >= 3000) 97217881Sadrian return; 98217881Sadrian 99217881Sadrian if (synth_freq < 2412) 100217881Sadrian new_bias = 0; 101217881Sadrian else if (synth_freq < 2422) 102217881Sadrian new_bias = 1; 103217881Sadrian else 104217881Sadrian new_bias = 2; 105217881Sadrian 106217881Sadrian /* pre-reverse this field */ 107217881Sadrian tmp_reg = ath_hal_reverseBits(new_bias, 3); 108217881Sadrian 109217881Sadrian HALDEBUG(ah, HAL_DEBUG_ANY, "%s: Force rf_pwd_icsyndiv to %1d on %4d\n", 110217881Sadrian __func__, new_bias, synth_freq); 111217881Sadrian 112217881Sadrian /* swizzle rf_pwd_icsyndiv */ 113217881Sadrian ar5416ModifyRfBuffer(priv->Bank6Data, tmp_reg, 3, 181, 3); 114217881Sadrian 115217881Sadrian /* write Bank 6 with new params */ 116217881Sadrian ath_hal_ini_bank_write(ah, &AH5416(ah)->ah_ini_bank6, priv->Bank6Data, reg_writes); 117217881Sadrian} 118217881Sadrian 119217881Sadrian/* 120185377Ssam * Take the MHz channel value and set the Channel value 121185377Ssam * 122185377Ssam * ASSUMES: Writes enabled to analog bus 123185377Ssam */ 124185377Ssamstatic HAL_BOOL 125187831Ssamar2133SetChannel(struct ath_hal *ah, const struct ieee80211_channel *chan) 126185377Ssam{ 127185377Ssam uint32_t channelSel = 0; 128185377Ssam uint32_t bModeSynth = 0; 129185377Ssam uint32_t aModeRefSel = 0; 130185377Ssam uint32_t reg32 = 0; 131185377Ssam uint16_t freq; 132185377Ssam CHAN_CENTERS centers; 133185377Ssam 134187831Ssam OS_MARK(ah, AH_MARK_SETCHANNEL, chan->ic_freq); 135185377Ssam 136187831Ssam ar5416GetChannelCenters(ah, chan, ¢ers); 137185377Ssam freq = centers.synth_center; 138185377Ssam 139185377Ssam if (freq < 4800) { 140185377Ssam uint32_t txctl; 141185377Ssam 142185377Ssam if (((freq - 2192) % 5) == 0) { 143185377Ssam channelSel = ((freq - 672) * 2 - 3040)/10; 144185377Ssam bModeSynth = 0; 145185377Ssam } else if (((freq - 2224) % 5) == 0) { 146185377Ssam channelSel = ((freq - 704) * 2 - 3040) / 10; 147185377Ssam bModeSynth = 1; 148185377Ssam } else { 149185377Ssam HALDEBUG(ah, HAL_DEBUG_ANY, 150185377Ssam "%s: invalid channel %u MHz\n", __func__, freq); 151185377Ssam return AH_FALSE; 152185377Ssam } 153185377Ssam 154185377Ssam channelSel = (channelSel << 2) & 0xff; 155185377Ssam channelSel = ath_hal_reverseBits(channelSel, 8); 156185377Ssam 157185377Ssam txctl = OS_REG_READ(ah, AR_PHY_CCK_TX_CTRL); 158185377Ssam if (freq == 2484) { 159185377Ssam /* Enable channel spreading for channel 14 */ 160185377Ssam OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, 161185377Ssam txctl | AR_PHY_CCK_TX_CTRL_JAPAN); 162185377Ssam } else { 163185377Ssam OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, 164185377Ssam txctl &~ AR_PHY_CCK_TX_CTRL_JAPAN); 165185377Ssam } 166185377Ssam } else if ((freq % 20) == 0 && freq >= 5120) { 167185377Ssam channelSel = ath_hal_reverseBits(((freq - 4800) / 20 << 2), 8); 168221483Sadrian if (AR_SREV_HOWL(ah) || AR_SREV_SOWL_10_OR_LATER(ah)) 169185377Ssam aModeRefSel = ath_hal_reverseBits(3, 2); 170185377Ssam else 171185377Ssam aModeRefSel = ath_hal_reverseBits(1, 2); 172185377Ssam } else if ((freq % 10) == 0) { 173185377Ssam channelSel = ath_hal_reverseBits(((freq - 4800) / 10 << 1), 8); 174221163Sadrian if (AR_SREV_HOWL(ah) || AR_SREV_SOWL_10_OR_LATER(ah)) 175185377Ssam aModeRefSel = ath_hal_reverseBits(2, 2); 176185377Ssam else 177185377Ssam aModeRefSel = ath_hal_reverseBits(1, 2); 178185377Ssam } else if ((freq % 5) == 0) { 179185377Ssam channelSel = ath_hal_reverseBits((freq - 4800) / 5, 8); 180185377Ssam aModeRefSel = ath_hal_reverseBits(1, 2); 181185377Ssam } else { 182185377Ssam HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel %u MHz\n", 183185377Ssam __func__, freq); 184185377Ssam return AH_FALSE; 185185377Ssam } 186185377Ssam 187217881Sadrian /* Workaround for hw bug - AR5416 specific */ 188223459Sadrian if (AR_SREV_OWL(ah) && ah->ah_config.ah_ar5416_biasadj) 189217881Sadrian ar2133ForceBias(ah, freq); 190217881Sadrian 191185377Ssam reg32 = (channelSel << 8) | (aModeRefSel << 2) | (bModeSynth << 1) | 192185377Ssam (1 << 5) | 0x1; 193185377Ssam 194185377Ssam OS_REG_WRITE(ah, AR_PHY(0x37), reg32); 195185377Ssam 196185377Ssam AH_PRIVATE(ah)->ah_curchan = chan; 197185377Ssam return AH_TRUE; 198185377Ssam 199185377Ssam} 200185377Ssam 201185377Ssam/* 202185377Ssam * Return a reference to the requested RF Bank. 203185377Ssam */ 204185377Ssamstatic uint32_t * 205185377Ssamar2133GetRfBank(struct ath_hal *ah, int bank) 206185377Ssam{ 207185377Ssam struct ar2133State *priv = AR2133(ah); 208185377Ssam 209185377Ssam HALASSERT(priv != AH_NULL); 210185377Ssam switch (bank) { 211185377Ssam case 1: return priv->Bank1Data; 212185377Ssam case 2: return priv->Bank2Data; 213185377Ssam case 3: return priv->Bank3Data; 214185377Ssam case 6: return priv->Bank6Data; 215185377Ssam case 7: return priv->Bank7Data; 216185377Ssam } 217185377Ssam HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unknown RF Bank %d requested\n", 218185377Ssam __func__, bank); 219185377Ssam return AH_NULL; 220185377Ssam} 221185377Ssam 222185377Ssam/* 223185377Ssam * Reads EEPROM header info from device structure and programs 224185377Ssam * all rf registers 225185377Ssam * 226185377Ssam * REQUIRES: Access to the analog rf device 227185377Ssam */ 228185377Ssamstatic HAL_BOOL 229187831Ssamar2133SetRfRegs(struct ath_hal *ah, const struct ieee80211_channel *chan, 230185377Ssam uint16_t modesIndex, uint16_t *rfXpdGain) 231185377Ssam{ 232185377Ssam struct ar2133State *priv = AR2133(ah); 233185377Ssam int writes; 234185377Ssam 235185377Ssam HALASSERT(priv); 236185377Ssam 237185377Ssam /* Setup Bank 0 Write */ 238185377Ssam ath_hal_ini_bank_setup(priv->Bank0Data, &AH5416(ah)->ah_ini_bank0, 1); 239185377Ssam 240185377Ssam /* Setup Bank 1 Write */ 241185377Ssam ath_hal_ini_bank_setup(priv->Bank1Data, &AH5416(ah)->ah_ini_bank1, 1); 242185377Ssam 243185377Ssam /* Setup Bank 2 Write */ 244185377Ssam ath_hal_ini_bank_setup(priv->Bank2Data, &AH5416(ah)->ah_ini_bank2, 1); 245185377Ssam 246185377Ssam /* Setup Bank 3 Write */ 247185377Ssam ath_hal_ini_bank_setup(priv->Bank3Data, &AH5416(ah)->ah_ini_bank3, modesIndex); 248185377Ssam 249185377Ssam /* Setup Bank 6 Write */ 250185377Ssam ath_hal_ini_bank_setup(priv->Bank6Data, &AH5416(ah)->ah_ini_bank6, modesIndex); 251185377Ssam 252185377Ssam /* Only the 5 or 2 GHz OB/DB need to be set for a mode */ 253187831Ssam if (IEEE80211_IS_CHAN_2GHZ(chan)) { 254220258Sadrian HALDEBUG(ah, HAL_DEBUG_EEPROM, "%s: 2ghz: OB_2:%d, DB_2:%d\n", 255220258Sadrian __func__, 256220258Sadrian ath_hal_eepromGet(ah, AR_EEP_OB_2, AH_NULL), 257220258Sadrian ath_hal_eepromGet(ah, AR_EEP_DB_2, AH_NULL)); 258185377Ssam ar5416ModifyRfBuffer(priv->Bank6Data, 259185377Ssam ath_hal_eepromGet(ah, AR_EEP_OB_2, AH_NULL), 3, 197, 0); 260185377Ssam ar5416ModifyRfBuffer(priv->Bank6Data, 261185377Ssam ath_hal_eepromGet(ah, AR_EEP_DB_2, AH_NULL), 3, 194, 0); 262185377Ssam } else { 263220258Sadrian HALDEBUG(ah, HAL_DEBUG_EEPROM, "%s: 5ghz: OB_5:%d, DB_5:%d\n", 264220258Sadrian __func__, 265220258Sadrian ath_hal_eepromGet(ah, AR_EEP_OB_5, AH_NULL), 266220258Sadrian ath_hal_eepromGet(ah, AR_EEP_DB_5, AH_NULL)); 267185377Ssam ar5416ModifyRfBuffer(priv->Bank6Data, 268185377Ssam ath_hal_eepromGet(ah, AR_EEP_OB_5, AH_NULL), 3, 203, 0); 269185377Ssam ar5416ModifyRfBuffer(priv->Bank6Data, 270185377Ssam ath_hal_eepromGet(ah, AR_EEP_DB_5, AH_NULL), 3, 200, 0); 271185377Ssam } 272185377Ssam /* Setup Bank 7 Setup */ 273185377Ssam ath_hal_ini_bank_setup(priv->Bank7Data, &AH5416(ah)->ah_ini_bank7, 1); 274185377Ssam 275185377Ssam /* Write Analog registers */ 276185377Ssam writes = ath_hal_ini_bank_write(ah, &AH5416(ah)->ah_ini_bank0, 277185377Ssam priv->Bank0Data, 0); 278185377Ssam writes = ath_hal_ini_bank_write(ah, &AH5416(ah)->ah_ini_bank1, 279185377Ssam priv->Bank1Data, writes); 280185377Ssam writes = ath_hal_ini_bank_write(ah, &AH5416(ah)->ah_ini_bank2, 281185377Ssam priv->Bank2Data, writes); 282185377Ssam writes = ath_hal_ini_bank_write(ah, &AH5416(ah)->ah_ini_bank3, 283185377Ssam priv->Bank3Data, writes); 284185377Ssam writes = ath_hal_ini_bank_write(ah, &AH5416(ah)->ah_ini_bank6, 285185377Ssam priv->Bank6Data, writes); 286185377Ssam (void) ath_hal_ini_bank_write(ah, &AH5416(ah)->ah_ini_bank7, 287185377Ssam priv->Bank7Data, writes); 288185377Ssam 289185377Ssam return AH_TRUE; 290185377Ssam#undef RF_BANK_SETUP 291185377Ssam} 292185377Ssam 293185377Ssam/* 294185377Ssam * Read the transmit power levels from the structures taken from EEPROM 295185377Ssam * Interpolate read transmit power values for this channel 296185377Ssam * Organize the transmit power values into a table for writing into the hardware 297185377Ssam */ 298185377Ssam 299185377Ssamstatic HAL_BOOL 300185377Ssamar2133SetPowerTable(struct ath_hal *ah, int16_t *pPowerMin, int16_t *pPowerMax, 301187831Ssam const struct ieee80211_channel *chan, uint16_t *rfXpdGain) 302185377Ssam{ 303185377Ssam return AH_TRUE; 304185377Ssam} 305185377Ssam 306185377Ssam#if 0 307185377Ssamstatic int16_t 308185377Ssamar2133GetMinPower(struct ath_hal *ah, EXPN_DATA_PER_CHANNEL_5112 *data) 309185377Ssam{ 310185377Ssam int i, minIndex; 311185377Ssam int16_t minGain,minPwr,minPcdac,retVal; 312185377Ssam 313185377Ssam /* Assume NUM_POINTS_XPD0 > 0 */ 314185377Ssam minGain = data->pDataPerXPD[0].xpd_gain; 315185377Ssam for (minIndex=0,i=1; i<NUM_XPD_PER_CHANNEL; i++) { 316185377Ssam if (data->pDataPerXPD[i].xpd_gain < minGain) { 317185377Ssam minIndex = i; 318185377Ssam minGain = data->pDataPerXPD[i].xpd_gain; 319185377Ssam } 320185377Ssam } 321185377Ssam minPwr = data->pDataPerXPD[minIndex].pwr_t4[0]; 322185377Ssam minPcdac = data->pDataPerXPD[minIndex].pcdac[0]; 323185377Ssam for (i=1; i<NUM_POINTS_XPD0; i++) { 324185377Ssam if (data->pDataPerXPD[minIndex].pwr_t4[i] < minPwr) { 325185377Ssam minPwr = data->pDataPerXPD[minIndex].pwr_t4[i]; 326185377Ssam minPcdac = data->pDataPerXPD[minIndex].pcdac[i]; 327185377Ssam } 328185377Ssam } 329185377Ssam retVal = minPwr - (minPcdac*2); 330185377Ssam return(retVal); 331185377Ssam} 332185377Ssam#endif 333185377Ssam 334185377Ssamstatic HAL_BOOL 335187831Ssamar2133GetChannelMaxMinPower(struct ath_hal *ah, 336187831Ssam const struct ieee80211_channel *chan, 337187831Ssam int16_t *maxPow, int16_t *minPow) 338185377Ssam{ 339185377Ssam#if 0 340185377Ssam struct ath_hal_5212 *ahp = AH5212(ah); 341185377Ssam int numChannels=0,i,last; 342185377Ssam int totalD, totalF,totalMin; 343185377Ssam EXPN_DATA_PER_CHANNEL_5112 *data=AH_NULL; 344185377Ssam EEPROM_POWER_EXPN_5112 *powerArray=AH_NULL; 345185377Ssam 346185377Ssam *maxPow = 0; 347185377Ssam if (IS_CHAN_A(chan)) { 348185377Ssam powerArray = ahp->ah_modePowerArray5112; 349185377Ssam data = powerArray[headerInfo11A].pDataPerChannel; 350185377Ssam numChannels = powerArray[headerInfo11A].numChannels; 351185377Ssam } else if (IS_CHAN_G(chan) || IS_CHAN_108G(chan)) { 352185377Ssam /* XXX - is this correct? Should we also use the same power for turbo G? */ 353185377Ssam powerArray = ahp->ah_modePowerArray5112; 354185377Ssam data = powerArray[headerInfo11G].pDataPerChannel; 355185377Ssam numChannels = powerArray[headerInfo11G].numChannels; 356185377Ssam } else if (IS_CHAN_B(chan)) { 357185377Ssam powerArray = ahp->ah_modePowerArray5112; 358185377Ssam data = powerArray[headerInfo11B].pDataPerChannel; 359185377Ssam numChannels = powerArray[headerInfo11B].numChannels; 360185377Ssam } else { 361185377Ssam return (AH_TRUE); 362185377Ssam } 363185377Ssam /* Make sure the channel is in the range of the TP values 364185377Ssam * (freq piers) 365185377Ssam */ 366185377Ssam if ((numChannels < 1) || 367185377Ssam (chan->channel < data[0].channelValue) || 368185377Ssam (chan->channel > data[numChannels-1].channelValue)) 369185377Ssam return(AH_FALSE); 370185377Ssam 371185377Ssam /* Linearly interpolate the power value now */ 372185377Ssam for (last=0,i=0; 373185377Ssam (i<numChannels) && (chan->channel > data[i].channelValue); 374185377Ssam last=i++); 375185377Ssam totalD = data[i].channelValue - data[last].channelValue; 376185377Ssam if (totalD > 0) { 377185377Ssam totalF = data[i].maxPower_t4 - data[last].maxPower_t4; 378185377Ssam *maxPow = (int8_t) ((totalF*(chan->channel-data[last].channelValue) + data[last].maxPower_t4*totalD)/totalD); 379185377Ssam 380185377Ssam totalMin = ar2133GetMinPower(ah,&data[i]) - ar2133GetMinPower(ah, &data[last]); 381185377Ssam *minPow = (int8_t) ((totalMin*(chan->channel-data[last].channelValue) + ar2133GetMinPower(ah, &data[last])*totalD)/totalD); 382185377Ssam return (AH_TRUE); 383185377Ssam } else { 384185377Ssam if (chan->channel == data[i].channelValue) { 385185377Ssam *maxPow = data[i].maxPower_t4; 386185377Ssam *minPow = ar2133GetMinPower(ah, &data[i]); 387185377Ssam return(AH_TRUE); 388185377Ssam } else 389185377Ssam return(AH_FALSE); 390185377Ssam } 391185377Ssam#else 392185377Ssam *maxPow = *minPow = 0; 393185377Ssam return AH_FALSE; 394185377Ssam#endif 395185377Ssam} 396185377Ssam 397219605Sadrian/* 398219605Sadrian * The ordering of nfarray is thus: 399219605Sadrian * 400219605Sadrian * nfarray[0]: Chain 0 ctl 401219605Sadrian * nfarray[1]: Chain 1 ctl 402219605Sadrian * nfarray[2]: Chain 2 ctl 403219605Sadrian * nfarray[3]: Chain 0 ext 404219605Sadrian * nfarray[4]: Chain 1 ext 405219605Sadrian * nfarray[5]: Chain 2 ext 406219605Sadrian */ 407185380Ssamstatic void 408185380Ssamar2133GetNoiseFloor(struct ath_hal *ah, int16_t nfarray[]) 409185380Ssam{ 410185380Ssam struct ath_hal_5416 *ahp = AH5416(ah); 411185380Ssam int16_t nf; 412185380Ssam 413219605Sadrian /* 414219605Sadrian * Blank nf array - some chips may only 415219605Sadrian * have one or two RX chainmasks enabled. 416219605Sadrian */ 417219605Sadrian nfarray[0] = nfarray[1] = nfarray[2] = 0; 418219605Sadrian nfarray[3] = nfarray[4] = nfarray[5] = 0; 419219605Sadrian 420185380Ssam switch (ahp->ah_rx_chainmask) { 421185380Ssam case 0x7: 422185380Ssam nf = MS(OS_REG_READ(ah, AR_PHY_CH2_CCA), AR_PHY_CH2_MINCCA_PWR); 423185380Ssam if (nf & 0x100) 424185380Ssam nf = 0 - ((nf ^ 0x1ff) + 1); 425185380Ssam HALDEBUG(ah, HAL_DEBUG_NFCAL, 426185380Ssam "NF calibrated [ctl] [chain 2] is %d\n", nf); 427219605Sadrian nfarray[2] = nf; 428185380Ssam 429185380Ssam nf = MS(OS_REG_READ(ah, AR_PHY_CH2_EXT_CCA), AR_PHY_CH2_EXT_MINCCA_PWR); 430185380Ssam if (nf & 0x100) 431185380Ssam nf = 0 - ((nf ^ 0x1ff) + 1); 432185380Ssam HALDEBUG(ah, HAL_DEBUG_NFCAL, 433185380Ssam "NF calibrated [ext] [chain 2] is %d\n", nf); 434185380Ssam nfarray[5] = nf; 435185380Ssam /* fall thru... */ 436185380Ssam case 0x3: 437185380Ssam case 0x5: 438185380Ssam nf = MS(OS_REG_READ(ah, AR_PHY_CH1_CCA), AR_PHY_CH1_MINCCA_PWR); 439185380Ssam if (nf & 0x100) 440185380Ssam nf = 0 - ((nf ^ 0x1ff) + 1); 441185380Ssam HALDEBUG(ah, HAL_DEBUG_NFCAL, 442185380Ssam "NF calibrated [ctl] [chain 1] is %d\n", nf); 443219605Sadrian nfarray[1] = nf; 444185380Ssam 445185380Ssam 446185380Ssam nf = MS(OS_REG_READ(ah, AR_PHY_CH1_EXT_CCA), AR_PHY_CH1_EXT_MINCCA_PWR); 447185380Ssam if (nf & 0x100) 448185380Ssam nf = 0 - ((nf ^ 0x1ff) + 1); 449185380Ssam HALDEBUG(ah, HAL_DEBUG_NFCAL, 450185380Ssam "NF calibrated [ext] [chain 1] is %d\n", nf); 451219605Sadrian nfarray[4] = nf; 452185380Ssam /* fall thru... */ 453185380Ssam case 0x1: 454185380Ssam nf = MS(OS_REG_READ(ah, AR_PHY_CCA), AR_PHY_MINCCA_PWR); 455185380Ssam if (nf & 0x100) 456185380Ssam nf = 0 - ((nf ^ 0x1ff) + 1); 457185380Ssam HALDEBUG(ah, HAL_DEBUG_NFCAL, 458185380Ssam "NF calibrated [ctl] [chain 0] is %d\n", nf); 459185380Ssam nfarray[0] = nf; 460185380Ssam 461185380Ssam nf = MS(OS_REG_READ(ah, AR_PHY_EXT_CCA), AR_PHY_EXT_MINCCA_PWR); 462185380Ssam if (nf & 0x100) 463185380Ssam nf = 0 - ((nf ^ 0x1ff) + 1); 464185380Ssam HALDEBUG(ah, HAL_DEBUG_NFCAL, 465185380Ssam "NF calibrated [ext] [chain 0] is %d\n", nf); 466219605Sadrian nfarray[3] = nf; 467185380Ssam 468185380Ssam break; 469185380Ssam } 470185380Ssam} 471185380Ssam 472185377Ssam/* 473185377Ssam * Adjust NF based on statistical values for 5GHz frequencies. 474185377Ssam * Stubbed:Not used by Fowl 475185377Ssam */ 476187831Ssamstatic int16_t 477185377Ssamar2133GetNfAdjust(struct ath_hal *ah, const HAL_CHANNEL_INTERNAL *c) 478185377Ssam{ 479185377Ssam return 0; 480185377Ssam} 481185377Ssam 482185377Ssam/* 483185377Ssam * Free memory for analog bank scratch buffers 484185377Ssam */ 485185377Ssamstatic void 486185377Ssamar2133RfDetach(struct ath_hal *ah) 487185377Ssam{ 488185377Ssam struct ath_hal_5212 *ahp = AH5212(ah); 489185377Ssam 490185377Ssam HALASSERT(ahp->ah_rfHal != AH_NULL); 491185377Ssam ath_hal_free(ahp->ah_rfHal); 492185377Ssam ahp->ah_rfHal = AH_NULL; 493185377Ssam} 494185377Ssam 495185377Ssam/* 496185377Ssam * Allocate memory for analog bank scratch buffers 497185377Ssam * Scratch Buffer will be reinitialized every reset so no need to zero now 498185377Ssam */ 499185377SsamHAL_BOOL 500185377Ssamar2133RfAttach(struct ath_hal *ah, HAL_STATUS *status) 501185377Ssam{ 502185377Ssam struct ath_hal_5212 *ahp = AH5212(ah); 503185377Ssam struct ar2133State *priv; 504185377Ssam uint32_t *bankData; 505185377Ssam 506188980Ssam HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: attach AR2133 radio\n", __func__); 507188980Ssam 508185377Ssam HALASSERT(ahp->ah_rfHal == AH_NULL); 509185377Ssam priv = ath_hal_malloc(sizeof(struct ar2133State) 510185377Ssam + AH5416(ah)->ah_ini_bank0.rows * sizeof(uint32_t) 511185377Ssam + AH5416(ah)->ah_ini_bank1.rows * sizeof(uint32_t) 512185377Ssam + AH5416(ah)->ah_ini_bank2.rows * sizeof(uint32_t) 513185377Ssam + AH5416(ah)->ah_ini_bank3.rows * sizeof(uint32_t) 514185377Ssam + AH5416(ah)->ah_ini_bank6.rows * sizeof(uint32_t) 515185377Ssam + AH5416(ah)->ah_ini_bank7.rows * sizeof(uint32_t) 516185377Ssam ); 517185377Ssam if (priv == AH_NULL) { 518185377Ssam HALDEBUG(ah, HAL_DEBUG_ANY, 519185377Ssam "%s: cannot allocate private state\n", __func__); 520185377Ssam *status = HAL_ENOMEM; /* XXX */ 521185377Ssam return AH_FALSE; 522185377Ssam } 523185377Ssam priv->base.rfDetach = ar2133RfDetach; 524185377Ssam priv->base.writeRegs = ar2133WriteRegs; 525185377Ssam priv->base.getRfBank = ar2133GetRfBank; 526185377Ssam priv->base.setChannel = ar2133SetChannel; 527185377Ssam priv->base.setRfRegs = ar2133SetRfRegs; 528185377Ssam priv->base.setPowerTable = ar2133SetPowerTable; 529185377Ssam priv->base.getChannelMaxMinPower = ar2133GetChannelMaxMinPower; 530185377Ssam priv->base.getNfAdjust = ar2133GetNfAdjust; 531185377Ssam 532185377Ssam bankData = (uint32_t *) &priv[1]; 533185377Ssam priv->Bank0Data = bankData, bankData += AH5416(ah)->ah_ini_bank0.rows; 534185377Ssam priv->Bank1Data = bankData, bankData += AH5416(ah)->ah_ini_bank1.rows; 535185377Ssam priv->Bank2Data = bankData, bankData += AH5416(ah)->ah_ini_bank2.rows; 536185377Ssam priv->Bank3Data = bankData, bankData += AH5416(ah)->ah_ini_bank3.rows; 537185377Ssam priv->Bank6Data = bankData, bankData += AH5416(ah)->ah_ini_bank6.rows; 538185377Ssam priv->Bank7Data = bankData, bankData += AH5416(ah)->ah_ini_bank7.rows; 539185377Ssam 540185377Ssam ahp->ah_pcdacTable = priv->pcdacTable; 541185377Ssam ahp->ah_pcdacTableSize = sizeof(priv->pcdacTable); 542185377Ssam ahp->ah_rfHal = &priv->base; 543185377Ssam /* 544185377Ssam * Set noise floor adjust method; we arrange a 545185377Ssam * direct call instead of thunking. 546185377Ssam */ 547185377Ssam AH_PRIVATE(ah)->ah_getNfAdjust = priv->base.getNfAdjust; 548185380Ssam AH_PRIVATE(ah)->ah_getNoiseFloor = ar2133GetNoiseFloor; 549185377Ssam 550185377Ssam return AH_TRUE; 551185377Ssam} 552