ar2133.c (185380) | ar2133.c (185406) |
---|---|
1/* 2 * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting 3 * Copyright (c) 2002-2008 Atheros Communications, Inc. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 * 17 * $Id: ar2133.c,v 1.13 2008/11/11 00:11:30 sam Exp $ 18 */ 19#include "opt_ah.h" 20 | 1/* 2 * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting 3 * Copyright (c) 2002-2008 Atheros Communications, Inc. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 * 17 * $Id: ar2133.c,v 1.13 2008/11/11 00:11:30 sam Exp $ 18 */ 19#include "opt_ah.h" 20 |
21#ifdef AH_SUPPORT_2133 22 | |
23#include "ah.h" 24#include "ah_internal.h" 25 26#include "ah_eeprom_v14.h" 27 28#include "ar5416/ar5416.h" 29#include "ar5416/ar5416reg.h" 30#include "ar5416/ar5416phy.h" 31 32#define N(a) (sizeof(a)/sizeof(a[0])) 33 34struct ar2133State { 35 RF_HAL_FUNCS base; /* public state, must be first */ 36 uint16_t pcdacTable[1]; 37 38 uint32_t *Bank0Data; 39 uint32_t *Bank1Data; 40 uint32_t *Bank2Data; 41 uint32_t *Bank3Data; 42 uint32_t *Bank6Data; 43 uint32_t *Bank7Data; 44 45 /* NB: Bank*Data storage follows */ 46}; 47#define AR2133(ah) ((struct ar2133State *) AH5212(ah)->ah_rfHal) 48 49#define ar5416ModifyRfBuffer ar5212ModifyRfBuffer /*XXX*/ 50 51extern void ar5416ModifyRfBuffer(uint32_t *rfBuf, uint32_t reg32, 52 uint32_t numBits, uint32_t firstBit, uint32_t column); 53HAL_BOOL ar2133GetChipPowerLimits(struct ath_hal *ah, HAL_CHANNEL 54 *chans, uint32_t nchans); 55 56static HAL_BOOL ar2133GetChannelMaxMinPower(struct ath_hal *, HAL_CHANNEL *, 57 int16_t *maxPow,int16_t *minPow); 58int16_t ar2133GetNfAdjust(struct ath_hal *ah, const HAL_CHANNEL_INTERNAL *c); 59 60static void 61ar2133WriteRegs(struct ath_hal *ah, u_int modesIndex, u_int freqIndex, 62 int writes) 63{ 64 (void) ath_hal_ini_write(ah, &AH5416(ah)->ah_ini_bb_rfgain, 65 freqIndex, writes); 66} 67 68/* 69 * Take the MHz channel value and set the Channel value 70 * 71 * ASSUMES: Writes enabled to analog bus 72 */ 73static HAL_BOOL 74ar2133SetChannel(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan) 75{ 76 uint32_t channelSel = 0; 77 uint32_t bModeSynth = 0; 78 uint32_t aModeRefSel = 0; 79 uint32_t reg32 = 0; 80 uint16_t freq; 81 CHAN_CENTERS centers; 82 83 OS_MARK(ah, AH_MARK_SETCHANNEL, chan->channel); 84 85 ar5416GetChannelCenters(ah, chan, ¢ers); 86 freq = centers.synth_center; 87 88 if (freq < 4800) { 89 uint32_t txctl; 90 91 if (((freq - 2192) % 5) == 0) { 92 channelSel = ((freq - 672) * 2 - 3040)/10; 93 bModeSynth = 0; 94 } else if (((freq - 2224) % 5) == 0) { 95 channelSel = ((freq - 704) * 2 - 3040) / 10; 96 bModeSynth = 1; 97 } else { 98 HALDEBUG(ah, HAL_DEBUG_ANY, 99 "%s: invalid channel %u MHz\n", __func__, freq); 100 return AH_FALSE; 101 } 102 103 channelSel = (channelSel << 2) & 0xff; 104 channelSel = ath_hal_reverseBits(channelSel, 8); 105 106 txctl = OS_REG_READ(ah, AR_PHY_CCK_TX_CTRL); 107 if (freq == 2484) { 108 /* Enable channel spreading for channel 14 */ 109 OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, 110 txctl | AR_PHY_CCK_TX_CTRL_JAPAN); 111 } else { 112 OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, 113 txctl &~ AR_PHY_CCK_TX_CTRL_JAPAN); 114 } 115 } else if ((freq % 20) == 0 && freq >= 5120) { 116 channelSel = ath_hal_reverseBits(((freq - 4800) / 20 << 2), 8); 117 if (AR_SREV_SOWL_10_OR_LATER(ah)) 118 aModeRefSel = ath_hal_reverseBits(3, 2); 119 else 120 aModeRefSel = ath_hal_reverseBits(1, 2); 121 } else if ((freq % 10) == 0) { 122 channelSel = ath_hal_reverseBits(((freq - 4800) / 10 << 1), 8); 123 if (AR_SREV_SOWL_10_OR_LATER(ah)) 124 aModeRefSel = ath_hal_reverseBits(2, 2); 125 else 126 aModeRefSel = ath_hal_reverseBits(1, 2); 127 } else if ((freq % 5) == 0) { 128 channelSel = ath_hal_reverseBits((freq - 4800) / 5, 8); 129 aModeRefSel = ath_hal_reverseBits(1, 2); 130 } else { 131 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel %u MHz\n", 132 __func__, freq); 133 return AH_FALSE; 134 } 135 136 reg32 = (channelSel << 8) | (aModeRefSel << 2) | (bModeSynth << 1) | 137 (1 << 5) | 0x1; 138 139 OS_REG_WRITE(ah, AR_PHY(0x37), reg32); 140 141 AH_PRIVATE(ah)->ah_curchan = chan; 142 return AH_TRUE; 143 144} 145 146/* 147 * Return a reference to the requested RF Bank. 148 */ 149static uint32_t * 150ar2133GetRfBank(struct ath_hal *ah, int bank) 151{ 152 struct ar2133State *priv = AR2133(ah); 153 154 HALASSERT(priv != AH_NULL); 155 switch (bank) { 156 case 1: return priv->Bank1Data; 157 case 2: return priv->Bank2Data; 158 case 3: return priv->Bank3Data; 159 case 6: return priv->Bank6Data; 160 case 7: return priv->Bank7Data; 161 } 162 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unknown RF Bank %d requested\n", 163 __func__, bank); 164 return AH_NULL; 165} 166 167/* 168 * Reads EEPROM header info from device structure and programs 169 * all rf registers 170 * 171 * REQUIRES: Access to the analog rf device 172 */ 173static HAL_BOOL 174ar2133SetRfRegs(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan, 175 uint16_t modesIndex, uint16_t *rfXpdGain) 176{ 177 struct ar2133State *priv = AR2133(ah); 178 int writes; 179 180 HALASSERT(priv); 181 182 /* Setup Bank 0 Write */ 183 ath_hal_ini_bank_setup(priv->Bank0Data, &AH5416(ah)->ah_ini_bank0, 1); 184 185 /* Setup Bank 1 Write */ 186 ath_hal_ini_bank_setup(priv->Bank1Data, &AH5416(ah)->ah_ini_bank1, 1); 187 188 /* Setup Bank 2 Write */ 189 ath_hal_ini_bank_setup(priv->Bank2Data, &AH5416(ah)->ah_ini_bank2, 1); 190 191 /* Setup Bank 3 Write */ 192 ath_hal_ini_bank_setup(priv->Bank3Data, &AH5416(ah)->ah_ini_bank3, modesIndex); 193 194 /* Setup Bank 6 Write */ 195 ath_hal_ini_bank_setup(priv->Bank6Data, &AH5416(ah)->ah_ini_bank6, modesIndex); 196 197 /* Only the 5 or 2 GHz OB/DB need to be set for a mode */ 198 if (IS_CHAN_2GHZ(chan)) { 199 ar5416ModifyRfBuffer(priv->Bank6Data, 200 ath_hal_eepromGet(ah, AR_EEP_OB_2, AH_NULL), 3, 197, 0); 201 ar5416ModifyRfBuffer(priv->Bank6Data, 202 ath_hal_eepromGet(ah, AR_EEP_DB_2, AH_NULL), 3, 194, 0); 203 } else { 204 ar5416ModifyRfBuffer(priv->Bank6Data, 205 ath_hal_eepromGet(ah, AR_EEP_OB_5, AH_NULL), 3, 203, 0); 206 ar5416ModifyRfBuffer(priv->Bank6Data, 207 ath_hal_eepromGet(ah, AR_EEP_DB_5, AH_NULL), 3, 200, 0); 208 } 209 /* Setup Bank 7 Setup */ 210 ath_hal_ini_bank_setup(priv->Bank7Data, &AH5416(ah)->ah_ini_bank7, 1); 211 212 /* Write Analog registers */ 213 writes = ath_hal_ini_bank_write(ah, &AH5416(ah)->ah_ini_bank0, 214 priv->Bank0Data, 0); 215 writes = ath_hal_ini_bank_write(ah, &AH5416(ah)->ah_ini_bank1, 216 priv->Bank1Data, writes); 217 writes = ath_hal_ini_bank_write(ah, &AH5416(ah)->ah_ini_bank2, 218 priv->Bank2Data, writes); 219 writes = ath_hal_ini_bank_write(ah, &AH5416(ah)->ah_ini_bank3, 220 priv->Bank3Data, writes); 221 writes = ath_hal_ini_bank_write(ah, &AH5416(ah)->ah_ini_bank6, 222 priv->Bank6Data, writes); 223 (void) ath_hal_ini_bank_write(ah, &AH5416(ah)->ah_ini_bank7, 224 priv->Bank7Data, writes); 225 226 return AH_TRUE; 227#undef RF_BANK_SETUP 228} 229 230/* 231 * Read the transmit power levels from the structures taken from EEPROM 232 * Interpolate read transmit power values for this channel 233 * Organize the transmit power values into a table for writing into the hardware 234 */ 235 236static HAL_BOOL 237ar2133SetPowerTable(struct ath_hal *ah, int16_t *pPowerMin, int16_t *pPowerMax, 238 HAL_CHANNEL_INTERNAL *chan, uint16_t *rfXpdGain) 239{ 240 return AH_TRUE; 241} 242 243#if 0 244static int16_t 245ar2133GetMinPower(struct ath_hal *ah, EXPN_DATA_PER_CHANNEL_5112 *data) 246{ 247 int i, minIndex; 248 int16_t minGain,minPwr,minPcdac,retVal; 249 250 /* Assume NUM_POINTS_XPD0 > 0 */ 251 minGain = data->pDataPerXPD[0].xpd_gain; 252 for (minIndex=0,i=1; i<NUM_XPD_PER_CHANNEL; i++) { 253 if (data->pDataPerXPD[i].xpd_gain < minGain) { 254 minIndex = i; 255 minGain = data->pDataPerXPD[i].xpd_gain; 256 } 257 } 258 minPwr = data->pDataPerXPD[minIndex].pwr_t4[0]; 259 minPcdac = data->pDataPerXPD[minIndex].pcdac[0]; 260 for (i=1; i<NUM_POINTS_XPD0; i++) { 261 if (data->pDataPerXPD[minIndex].pwr_t4[i] < minPwr) { 262 minPwr = data->pDataPerXPD[minIndex].pwr_t4[i]; 263 minPcdac = data->pDataPerXPD[minIndex].pcdac[i]; 264 } 265 } 266 retVal = minPwr - (minPcdac*2); 267 return(retVal); 268} 269#endif 270 271static HAL_BOOL 272ar2133GetChannelMaxMinPower(struct ath_hal *ah, HAL_CHANNEL *chan, int16_t *maxPow, 273 int16_t *minPow) 274{ 275#if 0 276 struct ath_hal_5212 *ahp = AH5212(ah); 277 int numChannels=0,i,last; 278 int totalD, totalF,totalMin; 279 EXPN_DATA_PER_CHANNEL_5112 *data=AH_NULL; 280 EEPROM_POWER_EXPN_5112 *powerArray=AH_NULL; 281 282 *maxPow = 0; 283 if (IS_CHAN_A(chan)) { 284 powerArray = ahp->ah_modePowerArray5112; 285 data = powerArray[headerInfo11A].pDataPerChannel; 286 numChannels = powerArray[headerInfo11A].numChannels; 287 } else if (IS_CHAN_G(chan) || IS_CHAN_108G(chan)) { 288 /* XXX - is this correct? Should we also use the same power for turbo G? */ 289 powerArray = ahp->ah_modePowerArray5112; 290 data = powerArray[headerInfo11G].pDataPerChannel; 291 numChannels = powerArray[headerInfo11G].numChannels; 292 } else if (IS_CHAN_B(chan)) { 293 powerArray = ahp->ah_modePowerArray5112; 294 data = powerArray[headerInfo11B].pDataPerChannel; 295 numChannels = powerArray[headerInfo11B].numChannels; 296 } else { 297 return (AH_TRUE); 298 } 299 /* Make sure the channel is in the range of the TP values 300 * (freq piers) 301 */ 302 if ((numChannels < 1) || 303 (chan->channel < data[0].channelValue) || 304 (chan->channel > data[numChannels-1].channelValue)) 305 return(AH_FALSE); 306 307 /* Linearly interpolate the power value now */ 308 for (last=0,i=0; 309 (i<numChannels) && (chan->channel > data[i].channelValue); 310 last=i++); 311 totalD = data[i].channelValue - data[last].channelValue; 312 if (totalD > 0) { 313 totalF = data[i].maxPower_t4 - data[last].maxPower_t4; 314 *maxPow = (int8_t) ((totalF*(chan->channel-data[last].channelValue) + data[last].maxPower_t4*totalD)/totalD); 315 316 totalMin = ar2133GetMinPower(ah,&data[i]) - ar2133GetMinPower(ah, &data[last]); 317 *minPow = (int8_t) ((totalMin*(chan->channel-data[last].channelValue) + ar2133GetMinPower(ah, &data[last])*totalD)/totalD); 318 return (AH_TRUE); 319 } else { 320 if (chan->channel == data[i].channelValue) { 321 *maxPow = data[i].maxPower_t4; 322 *minPow = ar2133GetMinPower(ah, &data[i]); 323 return(AH_TRUE); 324 } else 325 return(AH_FALSE); 326 } 327#else 328 *maxPow = *minPow = 0; 329 return AH_FALSE; 330#endif 331} 332 333static void 334ar2133GetNoiseFloor(struct ath_hal *ah, int16_t nfarray[]) 335{ 336 struct ath_hal_5416 *ahp = AH5416(ah); 337 int16_t nf; 338 339 switch (ahp->ah_rx_chainmask) { 340 case 0x7: 341 nf = MS(OS_REG_READ(ah, AR_PHY_CH2_CCA), AR_PHY_CH2_MINCCA_PWR); 342 if (nf & 0x100) 343 nf = 0 - ((nf ^ 0x1ff) + 1); 344 HALDEBUG(ah, HAL_DEBUG_NFCAL, 345 "NF calibrated [ctl] [chain 2] is %d\n", nf); 346 nfarray[4] = nf; 347 348 nf = MS(OS_REG_READ(ah, AR_PHY_CH2_EXT_CCA), AR_PHY_CH2_EXT_MINCCA_PWR); 349 if (nf & 0x100) 350 nf = 0 - ((nf ^ 0x1ff) + 1); 351 HALDEBUG(ah, HAL_DEBUG_NFCAL, 352 "NF calibrated [ext] [chain 2] is %d\n", nf); 353 nfarray[5] = nf; 354 /* fall thru... */ 355 case 0x3: 356 case 0x5: 357 nf = MS(OS_REG_READ(ah, AR_PHY_CH1_CCA), AR_PHY_CH1_MINCCA_PWR); 358 if (nf & 0x100) 359 nf = 0 - ((nf ^ 0x1ff) + 1); 360 HALDEBUG(ah, HAL_DEBUG_NFCAL, 361 "NF calibrated [ctl] [chain 1] is %d\n", nf); 362 nfarray[2] = nf; 363 364 365 nf = MS(OS_REG_READ(ah, AR_PHY_CH1_EXT_CCA), AR_PHY_CH1_EXT_MINCCA_PWR); 366 if (nf & 0x100) 367 nf = 0 - ((nf ^ 0x1ff) + 1); 368 HALDEBUG(ah, HAL_DEBUG_NFCAL, 369 "NF calibrated [ext] [chain 1] is %d\n", nf); 370 nfarray[3] = nf; 371 /* fall thru... */ 372 case 0x1: 373 nf = MS(OS_REG_READ(ah, AR_PHY_CCA), AR_PHY_MINCCA_PWR); 374 if (nf & 0x100) 375 nf = 0 - ((nf ^ 0x1ff) + 1); 376 HALDEBUG(ah, HAL_DEBUG_NFCAL, 377 "NF calibrated [ctl] [chain 0] is %d\n", nf); 378 nfarray[0] = nf; 379 380 nf = MS(OS_REG_READ(ah, AR_PHY_EXT_CCA), AR_PHY_EXT_MINCCA_PWR); 381 if (nf & 0x100) 382 nf = 0 - ((nf ^ 0x1ff) + 1); 383 HALDEBUG(ah, HAL_DEBUG_NFCAL, 384 "NF calibrated [ext] [chain 0] is %d\n", nf); 385 nfarray[1] = nf; 386 387 break; 388 } 389} 390 391/* 392 * Adjust NF based on statistical values for 5GHz frequencies. 393 * Stubbed:Not used by Fowl 394 */ 395int16_t 396ar2133GetNfAdjust(struct ath_hal *ah, const HAL_CHANNEL_INTERNAL *c) 397{ 398 return 0; 399} 400 401/* 402 * Free memory for analog bank scratch buffers 403 */ 404static void 405ar2133RfDetach(struct ath_hal *ah) 406{ 407 struct ath_hal_5212 *ahp = AH5212(ah); 408 409 HALASSERT(ahp->ah_rfHal != AH_NULL); 410 ath_hal_free(ahp->ah_rfHal); 411 ahp->ah_rfHal = AH_NULL; 412} 413 414/* 415 * Allocate memory for analog bank scratch buffers 416 * Scratch Buffer will be reinitialized every reset so no need to zero now 417 */ 418HAL_BOOL 419ar2133RfAttach(struct ath_hal *ah, HAL_STATUS *status) 420{ 421 struct ath_hal_5212 *ahp = AH5212(ah); 422 struct ar2133State *priv; 423 uint32_t *bankData; 424 425 HALASSERT(ahp->ah_rfHal == AH_NULL); 426 priv = ath_hal_malloc(sizeof(struct ar2133State) 427 + AH5416(ah)->ah_ini_bank0.rows * sizeof(uint32_t) 428 + AH5416(ah)->ah_ini_bank1.rows * sizeof(uint32_t) 429 + AH5416(ah)->ah_ini_bank2.rows * sizeof(uint32_t) 430 + AH5416(ah)->ah_ini_bank3.rows * sizeof(uint32_t) 431 + AH5416(ah)->ah_ini_bank6.rows * sizeof(uint32_t) 432 + AH5416(ah)->ah_ini_bank7.rows * sizeof(uint32_t) 433 ); 434 if (priv == AH_NULL) { 435 HALDEBUG(ah, HAL_DEBUG_ANY, 436 "%s: cannot allocate private state\n", __func__); 437 *status = HAL_ENOMEM; /* XXX */ 438 return AH_FALSE; 439 } 440 priv->base.rfDetach = ar2133RfDetach; 441 priv->base.writeRegs = ar2133WriteRegs; 442 priv->base.getRfBank = ar2133GetRfBank; 443 priv->base.setChannel = ar2133SetChannel; 444 priv->base.setRfRegs = ar2133SetRfRegs; 445 priv->base.setPowerTable = ar2133SetPowerTable; 446 priv->base.getChannelMaxMinPower = ar2133GetChannelMaxMinPower; 447 priv->base.getNfAdjust = ar2133GetNfAdjust; 448 449 bankData = (uint32_t *) &priv[1]; 450 priv->Bank0Data = bankData, bankData += AH5416(ah)->ah_ini_bank0.rows; 451 priv->Bank1Data = bankData, bankData += AH5416(ah)->ah_ini_bank1.rows; 452 priv->Bank2Data = bankData, bankData += AH5416(ah)->ah_ini_bank2.rows; 453 priv->Bank3Data = bankData, bankData += AH5416(ah)->ah_ini_bank3.rows; 454 priv->Bank6Data = bankData, bankData += AH5416(ah)->ah_ini_bank6.rows; 455 priv->Bank7Data = bankData, bankData += AH5416(ah)->ah_ini_bank7.rows; 456 457 ahp->ah_pcdacTable = priv->pcdacTable; 458 ahp->ah_pcdacTableSize = sizeof(priv->pcdacTable); 459 ahp->ah_rfHal = &priv->base; 460 /* 461 * Set noise floor adjust method; we arrange a 462 * direct call instead of thunking. 463 */ 464 AH_PRIVATE(ah)->ah_getNfAdjust = priv->base.getNfAdjust; 465 AH_PRIVATE(ah)->ah_getNoiseFloor = ar2133GetNoiseFloor; 466 467 return AH_TRUE; 468} | 21#include "ah.h" 22#include "ah_internal.h" 23 24#include "ah_eeprom_v14.h" 25 26#include "ar5416/ar5416.h" 27#include "ar5416/ar5416reg.h" 28#include "ar5416/ar5416phy.h" 29 30#define N(a) (sizeof(a)/sizeof(a[0])) 31 32struct ar2133State { 33 RF_HAL_FUNCS base; /* public state, must be first */ 34 uint16_t pcdacTable[1]; 35 36 uint32_t *Bank0Data; 37 uint32_t *Bank1Data; 38 uint32_t *Bank2Data; 39 uint32_t *Bank3Data; 40 uint32_t *Bank6Data; 41 uint32_t *Bank7Data; 42 43 /* NB: Bank*Data storage follows */ 44}; 45#define AR2133(ah) ((struct ar2133State *) AH5212(ah)->ah_rfHal) 46 47#define ar5416ModifyRfBuffer ar5212ModifyRfBuffer /*XXX*/ 48 49extern void ar5416ModifyRfBuffer(uint32_t *rfBuf, uint32_t reg32, 50 uint32_t numBits, uint32_t firstBit, uint32_t column); 51HAL_BOOL ar2133GetChipPowerLimits(struct ath_hal *ah, HAL_CHANNEL 52 *chans, uint32_t nchans); 53 54static HAL_BOOL ar2133GetChannelMaxMinPower(struct ath_hal *, HAL_CHANNEL *, 55 int16_t *maxPow,int16_t *minPow); 56int16_t ar2133GetNfAdjust(struct ath_hal *ah, const HAL_CHANNEL_INTERNAL *c); 57 58static void 59ar2133WriteRegs(struct ath_hal *ah, u_int modesIndex, u_int freqIndex, 60 int writes) 61{ 62 (void) ath_hal_ini_write(ah, &AH5416(ah)->ah_ini_bb_rfgain, 63 freqIndex, writes); 64} 65 66/* 67 * Take the MHz channel value and set the Channel value 68 * 69 * ASSUMES: Writes enabled to analog bus 70 */ 71static HAL_BOOL 72ar2133SetChannel(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan) 73{ 74 uint32_t channelSel = 0; 75 uint32_t bModeSynth = 0; 76 uint32_t aModeRefSel = 0; 77 uint32_t reg32 = 0; 78 uint16_t freq; 79 CHAN_CENTERS centers; 80 81 OS_MARK(ah, AH_MARK_SETCHANNEL, chan->channel); 82 83 ar5416GetChannelCenters(ah, chan, ¢ers); 84 freq = centers.synth_center; 85 86 if (freq < 4800) { 87 uint32_t txctl; 88 89 if (((freq - 2192) % 5) == 0) { 90 channelSel = ((freq - 672) * 2 - 3040)/10; 91 bModeSynth = 0; 92 } else if (((freq - 2224) % 5) == 0) { 93 channelSel = ((freq - 704) * 2 - 3040) / 10; 94 bModeSynth = 1; 95 } else { 96 HALDEBUG(ah, HAL_DEBUG_ANY, 97 "%s: invalid channel %u MHz\n", __func__, freq); 98 return AH_FALSE; 99 } 100 101 channelSel = (channelSel << 2) & 0xff; 102 channelSel = ath_hal_reverseBits(channelSel, 8); 103 104 txctl = OS_REG_READ(ah, AR_PHY_CCK_TX_CTRL); 105 if (freq == 2484) { 106 /* Enable channel spreading for channel 14 */ 107 OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, 108 txctl | AR_PHY_CCK_TX_CTRL_JAPAN); 109 } else { 110 OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, 111 txctl &~ AR_PHY_CCK_TX_CTRL_JAPAN); 112 } 113 } else if ((freq % 20) == 0 && freq >= 5120) { 114 channelSel = ath_hal_reverseBits(((freq - 4800) / 20 << 2), 8); 115 if (AR_SREV_SOWL_10_OR_LATER(ah)) 116 aModeRefSel = ath_hal_reverseBits(3, 2); 117 else 118 aModeRefSel = ath_hal_reverseBits(1, 2); 119 } else if ((freq % 10) == 0) { 120 channelSel = ath_hal_reverseBits(((freq - 4800) / 10 << 1), 8); 121 if (AR_SREV_SOWL_10_OR_LATER(ah)) 122 aModeRefSel = ath_hal_reverseBits(2, 2); 123 else 124 aModeRefSel = ath_hal_reverseBits(1, 2); 125 } else if ((freq % 5) == 0) { 126 channelSel = ath_hal_reverseBits((freq - 4800) / 5, 8); 127 aModeRefSel = ath_hal_reverseBits(1, 2); 128 } else { 129 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel %u MHz\n", 130 __func__, freq); 131 return AH_FALSE; 132 } 133 134 reg32 = (channelSel << 8) | (aModeRefSel << 2) | (bModeSynth << 1) | 135 (1 << 5) | 0x1; 136 137 OS_REG_WRITE(ah, AR_PHY(0x37), reg32); 138 139 AH_PRIVATE(ah)->ah_curchan = chan; 140 return AH_TRUE; 141 142} 143 144/* 145 * Return a reference to the requested RF Bank. 146 */ 147static uint32_t * 148ar2133GetRfBank(struct ath_hal *ah, int bank) 149{ 150 struct ar2133State *priv = AR2133(ah); 151 152 HALASSERT(priv != AH_NULL); 153 switch (bank) { 154 case 1: return priv->Bank1Data; 155 case 2: return priv->Bank2Data; 156 case 3: return priv->Bank3Data; 157 case 6: return priv->Bank6Data; 158 case 7: return priv->Bank7Data; 159 } 160 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unknown RF Bank %d requested\n", 161 __func__, bank); 162 return AH_NULL; 163} 164 165/* 166 * Reads EEPROM header info from device structure and programs 167 * all rf registers 168 * 169 * REQUIRES: Access to the analog rf device 170 */ 171static HAL_BOOL 172ar2133SetRfRegs(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan, 173 uint16_t modesIndex, uint16_t *rfXpdGain) 174{ 175 struct ar2133State *priv = AR2133(ah); 176 int writes; 177 178 HALASSERT(priv); 179 180 /* Setup Bank 0 Write */ 181 ath_hal_ini_bank_setup(priv->Bank0Data, &AH5416(ah)->ah_ini_bank0, 1); 182 183 /* Setup Bank 1 Write */ 184 ath_hal_ini_bank_setup(priv->Bank1Data, &AH5416(ah)->ah_ini_bank1, 1); 185 186 /* Setup Bank 2 Write */ 187 ath_hal_ini_bank_setup(priv->Bank2Data, &AH5416(ah)->ah_ini_bank2, 1); 188 189 /* Setup Bank 3 Write */ 190 ath_hal_ini_bank_setup(priv->Bank3Data, &AH5416(ah)->ah_ini_bank3, modesIndex); 191 192 /* Setup Bank 6 Write */ 193 ath_hal_ini_bank_setup(priv->Bank6Data, &AH5416(ah)->ah_ini_bank6, modesIndex); 194 195 /* Only the 5 or 2 GHz OB/DB need to be set for a mode */ 196 if (IS_CHAN_2GHZ(chan)) { 197 ar5416ModifyRfBuffer(priv->Bank6Data, 198 ath_hal_eepromGet(ah, AR_EEP_OB_2, AH_NULL), 3, 197, 0); 199 ar5416ModifyRfBuffer(priv->Bank6Data, 200 ath_hal_eepromGet(ah, AR_EEP_DB_2, AH_NULL), 3, 194, 0); 201 } else { 202 ar5416ModifyRfBuffer(priv->Bank6Data, 203 ath_hal_eepromGet(ah, AR_EEP_OB_5, AH_NULL), 3, 203, 0); 204 ar5416ModifyRfBuffer(priv->Bank6Data, 205 ath_hal_eepromGet(ah, AR_EEP_DB_5, AH_NULL), 3, 200, 0); 206 } 207 /* Setup Bank 7 Setup */ 208 ath_hal_ini_bank_setup(priv->Bank7Data, &AH5416(ah)->ah_ini_bank7, 1); 209 210 /* Write Analog registers */ 211 writes = ath_hal_ini_bank_write(ah, &AH5416(ah)->ah_ini_bank0, 212 priv->Bank0Data, 0); 213 writes = ath_hal_ini_bank_write(ah, &AH5416(ah)->ah_ini_bank1, 214 priv->Bank1Data, writes); 215 writes = ath_hal_ini_bank_write(ah, &AH5416(ah)->ah_ini_bank2, 216 priv->Bank2Data, writes); 217 writes = ath_hal_ini_bank_write(ah, &AH5416(ah)->ah_ini_bank3, 218 priv->Bank3Data, writes); 219 writes = ath_hal_ini_bank_write(ah, &AH5416(ah)->ah_ini_bank6, 220 priv->Bank6Data, writes); 221 (void) ath_hal_ini_bank_write(ah, &AH5416(ah)->ah_ini_bank7, 222 priv->Bank7Data, writes); 223 224 return AH_TRUE; 225#undef RF_BANK_SETUP 226} 227 228/* 229 * Read the transmit power levels from the structures taken from EEPROM 230 * Interpolate read transmit power values for this channel 231 * Organize the transmit power values into a table for writing into the hardware 232 */ 233 234static HAL_BOOL 235ar2133SetPowerTable(struct ath_hal *ah, int16_t *pPowerMin, int16_t *pPowerMax, 236 HAL_CHANNEL_INTERNAL *chan, uint16_t *rfXpdGain) 237{ 238 return AH_TRUE; 239} 240 241#if 0 242static int16_t 243ar2133GetMinPower(struct ath_hal *ah, EXPN_DATA_PER_CHANNEL_5112 *data) 244{ 245 int i, minIndex; 246 int16_t minGain,minPwr,minPcdac,retVal; 247 248 /* Assume NUM_POINTS_XPD0 > 0 */ 249 minGain = data->pDataPerXPD[0].xpd_gain; 250 for (minIndex=0,i=1; i<NUM_XPD_PER_CHANNEL; i++) { 251 if (data->pDataPerXPD[i].xpd_gain < minGain) { 252 minIndex = i; 253 minGain = data->pDataPerXPD[i].xpd_gain; 254 } 255 } 256 minPwr = data->pDataPerXPD[minIndex].pwr_t4[0]; 257 minPcdac = data->pDataPerXPD[minIndex].pcdac[0]; 258 for (i=1; i<NUM_POINTS_XPD0; i++) { 259 if (data->pDataPerXPD[minIndex].pwr_t4[i] < minPwr) { 260 minPwr = data->pDataPerXPD[minIndex].pwr_t4[i]; 261 minPcdac = data->pDataPerXPD[minIndex].pcdac[i]; 262 } 263 } 264 retVal = minPwr - (minPcdac*2); 265 return(retVal); 266} 267#endif 268 269static HAL_BOOL 270ar2133GetChannelMaxMinPower(struct ath_hal *ah, HAL_CHANNEL *chan, int16_t *maxPow, 271 int16_t *minPow) 272{ 273#if 0 274 struct ath_hal_5212 *ahp = AH5212(ah); 275 int numChannels=0,i,last; 276 int totalD, totalF,totalMin; 277 EXPN_DATA_PER_CHANNEL_5112 *data=AH_NULL; 278 EEPROM_POWER_EXPN_5112 *powerArray=AH_NULL; 279 280 *maxPow = 0; 281 if (IS_CHAN_A(chan)) { 282 powerArray = ahp->ah_modePowerArray5112; 283 data = powerArray[headerInfo11A].pDataPerChannel; 284 numChannels = powerArray[headerInfo11A].numChannels; 285 } else if (IS_CHAN_G(chan) || IS_CHAN_108G(chan)) { 286 /* XXX - is this correct? Should we also use the same power for turbo G? */ 287 powerArray = ahp->ah_modePowerArray5112; 288 data = powerArray[headerInfo11G].pDataPerChannel; 289 numChannels = powerArray[headerInfo11G].numChannels; 290 } else if (IS_CHAN_B(chan)) { 291 powerArray = ahp->ah_modePowerArray5112; 292 data = powerArray[headerInfo11B].pDataPerChannel; 293 numChannels = powerArray[headerInfo11B].numChannels; 294 } else { 295 return (AH_TRUE); 296 } 297 /* Make sure the channel is in the range of the TP values 298 * (freq piers) 299 */ 300 if ((numChannels < 1) || 301 (chan->channel < data[0].channelValue) || 302 (chan->channel > data[numChannels-1].channelValue)) 303 return(AH_FALSE); 304 305 /* Linearly interpolate the power value now */ 306 for (last=0,i=0; 307 (i<numChannels) && (chan->channel > data[i].channelValue); 308 last=i++); 309 totalD = data[i].channelValue - data[last].channelValue; 310 if (totalD > 0) { 311 totalF = data[i].maxPower_t4 - data[last].maxPower_t4; 312 *maxPow = (int8_t) ((totalF*(chan->channel-data[last].channelValue) + data[last].maxPower_t4*totalD)/totalD); 313 314 totalMin = ar2133GetMinPower(ah,&data[i]) - ar2133GetMinPower(ah, &data[last]); 315 *minPow = (int8_t) ((totalMin*(chan->channel-data[last].channelValue) + ar2133GetMinPower(ah, &data[last])*totalD)/totalD); 316 return (AH_TRUE); 317 } else { 318 if (chan->channel == data[i].channelValue) { 319 *maxPow = data[i].maxPower_t4; 320 *minPow = ar2133GetMinPower(ah, &data[i]); 321 return(AH_TRUE); 322 } else 323 return(AH_FALSE); 324 } 325#else 326 *maxPow = *minPow = 0; 327 return AH_FALSE; 328#endif 329} 330 331static void 332ar2133GetNoiseFloor(struct ath_hal *ah, int16_t nfarray[]) 333{ 334 struct ath_hal_5416 *ahp = AH5416(ah); 335 int16_t nf; 336 337 switch (ahp->ah_rx_chainmask) { 338 case 0x7: 339 nf = MS(OS_REG_READ(ah, AR_PHY_CH2_CCA), AR_PHY_CH2_MINCCA_PWR); 340 if (nf & 0x100) 341 nf = 0 - ((nf ^ 0x1ff) + 1); 342 HALDEBUG(ah, HAL_DEBUG_NFCAL, 343 "NF calibrated [ctl] [chain 2] is %d\n", nf); 344 nfarray[4] = nf; 345 346 nf = MS(OS_REG_READ(ah, AR_PHY_CH2_EXT_CCA), AR_PHY_CH2_EXT_MINCCA_PWR); 347 if (nf & 0x100) 348 nf = 0 - ((nf ^ 0x1ff) + 1); 349 HALDEBUG(ah, HAL_DEBUG_NFCAL, 350 "NF calibrated [ext] [chain 2] is %d\n", nf); 351 nfarray[5] = nf; 352 /* fall thru... */ 353 case 0x3: 354 case 0x5: 355 nf = MS(OS_REG_READ(ah, AR_PHY_CH1_CCA), AR_PHY_CH1_MINCCA_PWR); 356 if (nf & 0x100) 357 nf = 0 - ((nf ^ 0x1ff) + 1); 358 HALDEBUG(ah, HAL_DEBUG_NFCAL, 359 "NF calibrated [ctl] [chain 1] is %d\n", nf); 360 nfarray[2] = nf; 361 362 363 nf = MS(OS_REG_READ(ah, AR_PHY_CH1_EXT_CCA), AR_PHY_CH1_EXT_MINCCA_PWR); 364 if (nf & 0x100) 365 nf = 0 - ((nf ^ 0x1ff) + 1); 366 HALDEBUG(ah, HAL_DEBUG_NFCAL, 367 "NF calibrated [ext] [chain 1] is %d\n", nf); 368 nfarray[3] = nf; 369 /* fall thru... */ 370 case 0x1: 371 nf = MS(OS_REG_READ(ah, AR_PHY_CCA), AR_PHY_MINCCA_PWR); 372 if (nf & 0x100) 373 nf = 0 - ((nf ^ 0x1ff) + 1); 374 HALDEBUG(ah, HAL_DEBUG_NFCAL, 375 "NF calibrated [ctl] [chain 0] is %d\n", nf); 376 nfarray[0] = nf; 377 378 nf = MS(OS_REG_READ(ah, AR_PHY_EXT_CCA), AR_PHY_EXT_MINCCA_PWR); 379 if (nf & 0x100) 380 nf = 0 - ((nf ^ 0x1ff) + 1); 381 HALDEBUG(ah, HAL_DEBUG_NFCAL, 382 "NF calibrated [ext] [chain 0] is %d\n", nf); 383 nfarray[1] = nf; 384 385 break; 386 } 387} 388 389/* 390 * Adjust NF based on statistical values for 5GHz frequencies. 391 * Stubbed:Not used by Fowl 392 */ 393int16_t 394ar2133GetNfAdjust(struct ath_hal *ah, const HAL_CHANNEL_INTERNAL *c) 395{ 396 return 0; 397} 398 399/* 400 * Free memory for analog bank scratch buffers 401 */ 402static void 403ar2133RfDetach(struct ath_hal *ah) 404{ 405 struct ath_hal_5212 *ahp = AH5212(ah); 406 407 HALASSERT(ahp->ah_rfHal != AH_NULL); 408 ath_hal_free(ahp->ah_rfHal); 409 ahp->ah_rfHal = AH_NULL; 410} 411 412/* 413 * Allocate memory for analog bank scratch buffers 414 * Scratch Buffer will be reinitialized every reset so no need to zero now 415 */ 416HAL_BOOL 417ar2133RfAttach(struct ath_hal *ah, HAL_STATUS *status) 418{ 419 struct ath_hal_5212 *ahp = AH5212(ah); 420 struct ar2133State *priv; 421 uint32_t *bankData; 422 423 HALASSERT(ahp->ah_rfHal == AH_NULL); 424 priv = ath_hal_malloc(sizeof(struct ar2133State) 425 + AH5416(ah)->ah_ini_bank0.rows * sizeof(uint32_t) 426 + AH5416(ah)->ah_ini_bank1.rows * sizeof(uint32_t) 427 + AH5416(ah)->ah_ini_bank2.rows * sizeof(uint32_t) 428 + AH5416(ah)->ah_ini_bank3.rows * sizeof(uint32_t) 429 + AH5416(ah)->ah_ini_bank6.rows * sizeof(uint32_t) 430 + AH5416(ah)->ah_ini_bank7.rows * sizeof(uint32_t) 431 ); 432 if (priv == AH_NULL) { 433 HALDEBUG(ah, HAL_DEBUG_ANY, 434 "%s: cannot allocate private state\n", __func__); 435 *status = HAL_ENOMEM; /* XXX */ 436 return AH_FALSE; 437 } 438 priv->base.rfDetach = ar2133RfDetach; 439 priv->base.writeRegs = ar2133WriteRegs; 440 priv->base.getRfBank = ar2133GetRfBank; 441 priv->base.setChannel = ar2133SetChannel; 442 priv->base.setRfRegs = ar2133SetRfRegs; 443 priv->base.setPowerTable = ar2133SetPowerTable; 444 priv->base.getChannelMaxMinPower = ar2133GetChannelMaxMinPower; 445 priv->base.getNfAdjust = ar2133GetNfAdjust; 446 447 bankData = (uint32_t *) &priv[1]; 448 priv->Bank0Data = bankData, bankData += AH5416(ah)->ah_ini_bank0.rows; 449 priv->Bank1Data = bankData, bankData += AH5416(ah)->ah_ini_bank1.rows; 450 priv->Bank2Data = bankData, bankData += AH5416(ah)->ah_ini_bank2.rows; 451 priv->Bank3Data = bankData, bankData += AH5416(ah)->ah_ini_bank3.rows; 452 priv->Bank6Data = bankData, bankData += AH5416(ah)->ah_ini_bank6.rows; 453 priv->Bank7Data = bankData, bankData += AH5416(ah)->ah_ini_bank7.rows; 454 455 ahp->ah_pcdacTable = priv->pcdacTable; 456 ahp->ah_pcdacTableSize = sizeof(priv->pcdacTable); 457 ahp->ah_rfHal = &priv->base; 458 /* 459 * Set noise floor adjust method; we arrange a 460 * direct call instead of thunking. 461 */ 462 AH_PRIVATE(ah)->ah_getNfAdjust = priv->base.getNfAdjust; 463 AH_PRIVATE(ah)->ah_getNoiseFloor = ar2133GetNoiseFloor; 464 465 return AH_TRUE; 466} |
469#endif /* AH_SUPPORT_2133 */ | |