1 1.1 alc /* 2 1.1 alc * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting 3 1.1 alc * Copyright (c) 2002-2008 Atheros Communications, Inc. 4 1.1 alc * 5 1.1 alc * Permission to use, copy, modify, and/or distribute this software for any 6 1.1 alc * purpose with or without fee is hereby granted, provided that the above 7 1.1 alc * copyright notice and this permission notice appear in all copies. 8 1.1 alc * 9 1.1 alc * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 1.1 alc * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 1.1 alc * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 1.1 alc * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 1.1 alc * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 1.1 alc * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 1.1 alc * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 1.1 alc * 17 1.3 mrg * $Id: ar5111.c,v 1.3 2009/01/06 06:03:57 mrg Exp $ 18 1.1 alc */ 19 1.1 alc #include "opt_ah.h" 20 1.1 alc 21 1.1 alc #include "ah.h" 22 1.1 alc #include "ah_internal.h" 23 1.1 alc 24 1.1 alc #include "ah_eeprom_v3.h" 25 1.1 alc 26 1.1 alc #include "ar5212/ar5212.h" 27 1.1 alc #include "ar5212/ar5212reg.h" 28 1.1 alc #include "ar5212/ar5212phy.h" 29 1.1 alc 30 1.1 alc #define AH_5212_5111 31 1.1 alc #include "ar5212/ar5212.ini" 32 1.1 alc 33 1.1 alc #define N(a) (sizeof(a)/sizeof(a[0])) 34 1.1 alc 35 1.1 alc struct ar5111State { 36 1.1 alc RF_HAL_FUNCS base; /* public state, must be first */ 37 1.1 alc uint16_t pcdacTable[PWR_TABLE_SIZE]; 38 1.1 alc 39 1.1 alc uint32_t Bank0Data[N(ar5212Bank0_5111)]; 40 1.1 alc uint32_t Bank1Data[N(ar5212Bank1_5111)]; 41 1.1 alc uint32_t Bank2Data[N(ar5212Bank2_5111)]; 42 1.1 alc uint32_t Bank3Data[N(ar5212Bank3_5111)]; 43 1.1 alc uint32_t Bank6Data[N(ar5212Bank6_5111)]; 44 1.1 alc uint32_t Bank7Data[N(ar5212Bank7_5111)]; 45 1.1 alc }; 46 1.1 alc #define AR5111(ah) ((struct ar5111State *) AH5212(ah)->ah_rfHal) 47 1.1 alc 48 1.1 alc static uint16_t ar5212GetScaledPower(uint16_t channel, uint16_t pcdacValue, 49 1.1 alc const PCDACS_EEPROM *pSrcStruct); 50 1.1 alc static HAL_BOOL ar5212FindValueInList(uint16_t channel, uint16_t pcdacValue, 51 1.1 alc const PCDACS_EEPROM *pSrcStruct, uint16_t *powerValue); 52 1.1 alc static void ar5212GetLowerUpperPcdacs(uint16_t pcdac, uint16_t channel, 53 1.1 alc const PCDACS_EEPROM *pSrcStruct, 54 1.1 alc uint16_t *pLowerPcdac, uint16_t *pUpperPcdac); 55 1.1 alc 56 1.1 alc extern void ar5212GetLowerUpperValues(uint16_t value, 57 1.1 alc const uint16_t *pList, uint16_t listSize, 58 1.1 alc uint16_t *pLowerValue, uint16_t *pUpperValue); 59 1.1 alc extern void ar5212ModifyRfBuffer(uint32_t *rfBuf, uint32_t reg32, 60 1.1 alc uint32_t numBits, uint32_t firstBit, uint32_t column); 61 1.1 alc 62 1.1 alc static void 63 1.1 alc ar5111WriteRegs(struct ath_hal *ah, u_int modesIndex, u_int freqIndex, 64 1.1 alc int writes) 65 1.1 alc { 66 1.1 alc HAL_INI_WRITE_ARRAY(ah, ar5212Modes_5111, modesIndex, writes); 67 1.1 alc HAL_INI_WRITE_ARRAY(ah, ar5212Common_5111, 1, writes); 68 1.1 alc HAL_INI_WRITE_ARRAY(ah, ar5212BB_RfGain_5111, freqIndex, writes); 69 1.1 alc } 70 1.1 alc 71 1.1 alc /* 72 1.1 alc * Take the MHz channel value and set the Channel value 73 1.1 alc * 74 1.1 alc * ASSUMES: Writes enabled to analog bus 75 1.1 alc */ 76 1.1 alc static HAL_BOOL 77 1.1 alc ar5111SetChannel(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan) 78 1.1 alc { 79 1.1 alc #define CI_2GHZ_INDEX_CORRECTION 19 80 1.1 alc uint32_t refClk, reg32, data2111; 81 1.1 alc int16_t chan5111, chanIEEE; 82 1.1 alc 83 1.1 alc /* 84 1.1 alc * Structure to hold 11b tuning information for 5111/2111 85 1.1 alc * 16 MHz mode, divider ratio = 198 = NP+S. N=16, S=4 or 6, P=12 86 1.1 alc */ 87 1.1 alc typedef struct { 88 1.1 alc uint32_t refClkSel; /* reference clock, 1 for 16 MHz */ 89 1.1 alc uint32_t channelSelect; /* P[7:4]S[3:0] bits */ 90 1.1 alc uint16_t channel5111; /* 11a channel for 5111 */ 91 1.1 alc } CHAN_INFO_2GHZ; 92 1.1 alc 93 1.2 alc static const CHAN_INFO_2GHZ chan2GHzData[] = { 94 1.1 alc { 1, 0x46, 96 }, /* 2312 -19 */ 95 1.1 alc { 1, 0x46, 97 }, /* 2317 -18 */ 96 1.1 alc { 1, 0x46, 98 }, /* 2322 -17 */ 97 1.1 alc { 1, 0x46, 99 }, /* 2327 -16 */ 98 1.1 alc { 1, 0x46, 100 }, /* 2332 -15 */ 99 1.1 alc { 1, 0x46, 101 }, /* 2337 -14 */ 100 1.1 alc { 1, 0x46, 102 }, /* 2342 -13 */ 101 1.1 alc { 1, 0x46, 103 }, /* 2347 -12 */ 102 1.1 alc { 1, 0x46, 104 }, /* 2352 -11 */ 103 1.1 alc { 1, 0x46, 105 }, /* 2357 -10 */ 104 1.1 alc { 1, 0x46, 106 }, /* 2362 -9 */ 105 1.1 alc { 1, 0x46, 107 }, /* 2367 -8 */ 106 1.1 alc { 1, 0x46, 108 }, /* 2372 -7 */ 107 1.1 alc /* index -6 to 0 are pad to make this a nolookup table */ 108 1.1 alc { 1, 0x46, 116 }, /* -6 */ 109 1.1 alc { 1, 0x46, 116 }, /* -5 */ 110 1.1 alc { 1, 0x46, 116 }, /* -4 */ 111 1.1 alc { 1, 0x46, 116 }, /* -3 */ 112 1.1 alc { 1, 0x46, 116 }, /* -2 */ 113 1.1 alc { 1, 0x46, 116 }, /* -1 */ 114 1.1 alc { 1, 0x46, 116 }, /* 0 */ 115 1.1 alc { 1, 0x46, 116 }, /* 2412 1 */ 116 1.1 alc { 1, 0x46, 117 }, /* 2417 2 */ 117 1.1 alc { 1, 0x46, 118 }, /* 2422 3 */ 118 1.1 alc { 1, 0x46, 119 }, /* 2427 4 */ 119 1.1 alc { 1, 0x46, 120 }, /* 2432 5 */ 120 1.1 alc { 1, 0x46, 121 }, /* 2437 6 */ 121 1.1 alc { 1, 0x46, 122 }, /* 2442 7 */ 122 1.1 alc { 1, 0x46, 123 }, /* 2447 8 */ 123 1.1 alc { 1, 0x46, 124 }, /* 2452 9 */ 124 1.1 alc { 1, 0x46, 125 }, /* 2457 10 */ 125 1.1 alc { 1, 0x46, 126 }, /* 2462 11 */ 126 1.1 alc { 1, 0x46, 127 }, /* 2467 12 */ 127 1.1 alc { 1, 0x46, 128 }, /* 2472 13 */ 128 1.1 alc { 1, 0x44, 124 }, /* 2484 14 */ 129 1.1 alc { 1, 0x46, 136 }, /* 2512 15 */ 130 1.1 alc { 1, 0x46, 140 }, /* 2532 16 */ 131 1.1 alc { 1, 0x46, 144 }, /* 2552 17 */ 132 1.1 alc { 1, 0x46, 148 }, /* 2572 18 */ 133 1.1 alc { 1, 0x46, 152 }, /* 2592 19 */ 134 1.1 alc { 1, 0x46, 156 }, /* 2612 20 */ 135 1.1 alc { 1, 0x46, 160 }, /* 2632 21 */ 136 1.1 alc { 1, 0x46, 164 }, /* 2652 22 */ 137 1.1 alc { 1, 0x46, 168 }, /* 2672 23 */ 138 1.1 alc { 1, 0x46, 172 }, /* 2692 24 */ 139 1.1 alc { 1, 0x46, 176 }, /* 2712 25 */ 140 1.1 alc { 1, 0x46, 180 } /* 2732 26 */ 141 1.1 alc }; 142 1.1 alc 143 1.1 alc OS_MARK(ah, AH_MARK_SETCHANNEL, chan->channel); 144 1.1 alc 145 1.1 alc chanIEEE = ath_hal_mhz2ieee(ah, chan->channel, chan->channelFlags); 146 1.1 alc if (IS_CHAN_2GHZ(chan)) { 147 1.1 alc const CHAN_INFO_2GHZ* ci = 148 1.1 alc &chan2GHzData[chanIEEE + CI_2GHZ_INDEX_CORRECTION]; 149 1.1 alc uint32_t txctl; 150 1.1 alc 151 1.1 alc data2111 = ((ath_hal_reverseBits(ci->channelSelect, 8) & 0xff) 152 1.1 alc << 5) 153 1.1 alc | (ci->refClkSel << 4); 154 1.1 alc chan5111 = ci->channel5111; 155 1.1 alc txctl = OS_REG_READ(ah, AR_PHY_CCK_TX_CTRL); 156 1.1 alc if (chan->channel == 2484) { 157 1.1 alc /* Enable channel spreading for channel 14 */ 158 1.1 alc OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, 159 1.1 alc txctl | AR_PHY_CCK_TX_CTRL_JAPAN); 160 1.1 alc } else { 161 1.1 alc OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, 162 1.1 alc txctl &~ AR_PHY_CCK_TX_CTRL_JAPAN); 163 1.1 alc } 164 1.1 alc } else { 165 1.1 alc chan5111 = chanIEEE; /* no conversion needed */ 166 1.1 alc data2111 = 0; 167 1.1 alc } 168 1.1 alc 169 1.1 alc /* Rest of the code is common for 5 GHz and 2.4 GHz. */ 170 1.1 alc if (chan5111 >= 145 || (chan5111 & 0x1)) { 171 1.1 alc reg32 = ath_hal_reverseBits(chan5111 - 24, 8) & 0xff; 172 1.1 alc refClk = 1; 173 1.1 alc } else { 174 1.1 alc reg32 = ath_hal_reverseBits(((chan5111 - 24)/2), 8) & 0xff; 175 1.1 alc refClk = 0; 176 1.1 alc } 177 1.1 alc 178 1.1 alc reg32 = (reg32 << 2) | (refClk << 1) | (1 << 10) | 0x1; 179 1.1 alc OS_REG_WRITE(ah, AR_PHY(0x27), ((data2111 & 0xff) << 8) | (reg32 & 0xff)); 180 1.1 alc reg32 >>= 8; 181 1.1 alc OS_REG_WRITE(ah, AR_PHY(0x34), (data2111 & 0xff00) | (reg32 & 0xff)); 182 1.1 alc 183 1.1 alc AH_PRIVATE(ah)->ah_curchan = chan; 184 1.1 alc return AH_TRUE; 185 1.1 alc #undef CI_2GHZ_INDEX_CORRECTION 186 1.1 alc } 187 1.1 alc 188 1.1 alc /* 189 1.1 alc * Return a reference to the requested RF Bank. 190 1.1 alc */ 191 1.1 alc static uint32_t * 192 1.1 alc ar5111GetRfBank(struct ath_hal *ah, int bank) 193 1.1 alc { 194 1.1 alc struct ar5111State *priv = AR5111(ah); 195 1.1 alc 196 1.1 alc HALASSERT(priv != AH_NULL); 197 1.1 alc switch (bank) { 198 1.1 alc case 0: return priv->Bank0Data; 199 1.1 alc case 1: return priv->Bank1Data; 200 1.1 alc case 2: return priv->Bank2Data; 201 1.1 alc case 3: return priv->Bank3Data; 202 1.1 alc case 6: return priv->Bank6Data; 203 1.1 alc case 7: return priv->Bank7Data; 204 1.1 alc } 205 1.1 alc HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unknown RF Bank %d requested\n", 206 1.1 alc __func__, bank); 207 1.1 alc return AH_NULL; 208 1.1 alc } 209 1.1 alc 210 1.1 alc /* 211 1.1 alc * Reads EEPROM header info from device structure and programs 212 1.1 alc * all rf registers 213 1.1 alc * 214 1.1 alc * REQUIRES: Access to the analog rf device 215 1.1 alc */ 216 1.1 alc static HAL_BOOL 217 1.1 alc ar5111SetRfRegs(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan, 218 1.1 alc uint16_t modesIndex, uint16_t *rfXpdGain) 219 1.1 alc { 220 1.1 alc struct ath_hal_5212 *ahp = AH5212(ah); 221 1.1 alc const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; 222 1.1 alc uint16_t rfXpdGainFixed, rfPloSel, rfPwdXpd, gainI; 223 1.1 alc uint16_t tempOB, tempDB; 224 1.1 alc uint32_t ob2GHz, db2GHz, rfReg[N(ar5212Bank6_5111)]; 225 1.1 alc int i, regWrites = 0; 226 1.1 alc 227 1.1 alc /* Setup rf parameters */ 228 1.1 alc switch (chan->channelFlags & CHANNEL_ALL) { 229 1.1 alc case CHANNEL_A: 230 1.1 alc case CHANNEL_T: 231 1.1 alc if (4000 < chan->channel && chan->channel < 5260) { 232 1.1 alc tempOB = ee->ee_ob1; 233 1.1 alc tempDB = ee->ee_db1; 234 1.1 alc } else if (5260 <= chan->channel && chan->channel < 5500) { 235 1.1 alc tempOB = ee->ee_ob2; 236 1.1 alc tempDB = ee->ee_db2; 237 1.1 alc } else if (5500 <= chan->channel && chan->channel < 5725) { 238 1.1 alc tempOB = ee->ee_ob3; 239 1.1 alc tempDB = ee->ee_db3; 240 1.1 alc } else if (chan->channel >= 5725) { 241 1.1 alc tempOB = ee->ee_ob4; 242 1.1 alc tempDB = ee->ee_db4; 243 1.1 alc } else { 244 1.1 alc /* XXX when does this happen??? */ 245 1.1 alc tempOB = tempDB = 0; 246 1.1 alc } 247 1.1 alc ob2GHz = db2GHz = 0; 248 1.1 alc 249 1.1 alc rfXpdGainFixed = ee->ee_xgain[headerInfo11A]; 250 1.1 alc rfPloSel = ee->ee_xpd[headerInfo11A]; 251 1.1 alc rfPwdXpd = !ee->ee_xpd[headerInfo11A]; 252 1.1 alc gainI = ee->ee_gainI[headerInfo11A]; 253 1.1 alc break; 254 1.1 alc case CHANNEL_B: 255 1.1 alc tempOB = ee->ee_obFor24; 256 1.1 alc tempDB = ee->ee_dbFor24; 257 1.1 alc ob2GHz = ee->ee_ob2GHz[0]; 258 1.1 alc db2GHz = ee->ee_db2GHz[0]; 259 1.1 alc 260 1.1 alc rfXpdGainFixed = ee->ee_xgain[headerInfo11B]; 261 1.1 alc rfPloSel = ee->ee_xpd[headerInfo11B]; 262 1.1 alc rfPwdXpd = !ee->ee_xpd[headerInfo11B]; 263 1.1 alc gainI = ee->ee_gainI[headerInfo11B]; 264 1.1 alc break; 265 1.1 alc case CHANNEL_G: 266 1.1 alc tempOB = ee->ee_obFor24g; 267 1.1 alc tempDB = ee->ee_dbFor24g; 268 1.1 alc ob2GHz = ee->ee_ob2GHz[1]; 269 1.1 alc db2GHz = ee->ee_db2GHz[1]; 270 1.1 alc 271 1.1 alc rfXpdGainFixed = ee->ee_xgain[headerInfo11G]; 272 1.1 alc rfPloSel = ee->ee_xpd[headerInfo11G]; 273 1.1 alc rfPwdXpd = !ee->ee_xpd[headerInfo11G]; 274 1.1 alc gainI = ee->ee_gainI[headerInfo11G]; 275 1.1 alc break; 276 1.1 alc default: 277 1.1 alc HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n", 278 1.1 alc __func__, chan->channelFlags); 279 1.1 alc return AH_FALSE; 280 1.1 alc } 281 1.1 alc 282 1.1 alc HALASSERT(1 <= tempOB && tempOB <= 5); 283 1.1 alc HALASSERT(1 <= tempDB && tempDB <= 5); 284 1.1 alc 285 1.1 alc /* Bank 0 Write */ 286 1.1 alc for (i = 0; i < N(ar5212Bank0_5111); i++) 287 1.1 alc rfReg[i] = ar5212Bank0_5111[i][modesIndex]; 288 1.1 alc if (IS_CHAN_2GHZ(chan)) { 289 1.1 alc ar5212ModifyRfBuffer(rfReg, ob2GHz, 3, 119, 0); 290 1.1 alc ar5212ModifyRfBuffer(rfReg, db2GHz, 3, 122, 0); 291 1.1 alc } 292 1.1 alc HAL_INI_WRITE_BANK(ah, ar5212Bank0_5111, rfReg, regWrites); 293 1.1 alc 294 1.1 alc /* Bank 1 Write */ 295 1.1 alc HAL_INI_WRITE_ARRAY(ah, ar5212Bank1_5111, 1, regWrites); 296 1.1 alc 297 1.1 alc /* Bank 2 Write */ 298 1.1 alc HAL_INI_WRITE_ARRAY(ah, ar5212Bank2_5111, modesIndex, regWrites); 299 1.1 alc 300 1.1 alc /* Bank 3 Write */ 301 1.1 alc HAL_INI_WRITE_ARRAY(ah, ar5212Bank3_5111, modesIndex, regWrites); 302 1.1 alc 303 1.1 alc /* Bank 6 Write */ 304 1.1 alc for (i = 0; i < N(ar5212Bank6_5111); i++) 305 1.1 alc rfReg[i] = ar5212Bank6_5111[i][modesIndex]; 306 1.1 alc if (IS_CHAN_A(chan)) { /* NB: CHANNEL_A | CHANNEL_T */ 307 1.1 alc ar5212ModifyRfBuffer(rfReg, ee->ee_cornerCal.pd84, 1, 51, 3); 308 1.1 alc ar5212ModifyRfBuffer(rfReg, ee->ee_cornerCal.pd90, 1, 45, 3); 309 1.1 alc } 310 1.1 alc ar5212ModifyRfBuffer(rfReg, rfPwdXpd, 1, 95, 0); 311 1.1 alc ar5212ModifyRfBuffer(rfReg, rfXpdGainFixed, 4, 96, 0); 312 1.1 alc /* Set 5212 OB & DB */ 313 1.1 alc ar5212ModifyRfBuffer(rfReg, tempOB, 3, 104, 0); 314 1.1 alc ar5212ModifyRfBuffer(rfReg, tempDB, 3, 107, 0); 315 1.1 alc HAL_INI_WRITE_BANK(ah, ar5212Bank6_5111, rfReg, regWrites); 316 1.1 alc 317 1.1 alc /* Bank 7 Write */ 318 1.1 alc for (i = 0; i < N(ar5212Bank7_5111); i++) 319 1.1 alc rfReg[i] = ar5212Bank7_5111[i][modesIndex]; 320 1.1 alc ar5212ModifyRfBuffer(rfReg, gainI, 6, 29, 0); 321 1.1 alc ar5212ModifyRfBuffer(rfReg, rfPloSel, 1, 4, 0); 322 1.1 alc 323 1.1 alc if (IS_CHAN_QUARTER_RATE(chan) || IS_CHAN_HALF_RATE(chan)) { 324 1.1 alc uint32_t rfWaitI, rfWaitS, rfMaxTime; 325 1.1 alc 326 1.1 alc rfWaitS = 0x1f; 327 1.1 alc rfWaitI = (IS_CHAN_HALF_RATE(chan)) ? 0x10 : 0x1f; 328 1.1 alc rfMaxTime = 3; 329 1.1 alc ar5212ModifyRfBuffer(rfReg, rfWaitS, 5, 19, 0); 330 1.1 alc ar5212ModifyRfBuffer(rfReg, rfWaitI, 5, 24, 0); 331 1.1 alc ar5212ModifyRfBuffer(rfReg, rfMaxTime, 2, 49, 0); 332 1.1 alc 333 1.1 alc } 334 1.1 alc 335 1.1 alc HAL_INI_WRITE_BANK(ah, ar5212Bank7_5111, rfReg, regWrites); 336 1.1 alc 337 1.1 alc /* Now that we have reprogrammed rfgain value, clear the flag. */ 338 1.1 alc ahp->ah_rfgainState = HAL_RFGAIN_INACTIVE; 339 1.1 alc 340 1.1 alc return AH_TRUE; 341 1.1 alc } 342 1.1 alc 343 1.1 alc /* 344 1.1 alc * Returns interpolated or the scaled up interpolated value 345 1.1 alc */ 346 1.1 alc static uint16_t 347 1.1 alc interpolate(uint16_t target, uint16_t srcLeft, uint16_t srcRight, 348 1.1 alc uint16_t targetLeft, uint16_t targetRight) 349 1.1 alc { 350 1.1 alc uint16_t rv; 351 1.1 alc int16_t lRatio; 352 1.1 alc 353 1.1 alc /* to get an accurate ratio, always scale, if want to scale, then don't scale back down */ 354 1.1 alc if ((targetLeft * targetRight) == 0) 355 1.1 alc return 0; 356 1.1 alc 357 1.1 alc if (srcRight != srcLeft) { 358 1.1 alc /* 359 1.1 alc * Note the ratio always need to be scaled, 360 1.1 alc * since it will be a fraction. 361 1.1 alc */ 362 1.1 alc lRatio = (target - srcLeft) * EEP_SCALE / (srcRight - srcLeft); 363 1.1 alc if (lRatio < 0) { 364 1.1 alc /* Return as Left target if value would be negative */ 365 1.1 alc rv = targetLeft; 366 1.1 alc } else if (lRatio > EEP_SCALE) { 367 1.1 alc /* Return as Right target if Ratio is greater than 100% (SCALE) */ 368 1.1 alc rv = targetRight; 369 1.1 alc } else { 370 1.1 alc rv = (lRatio * targetRight + (EEP_SCALE - lRatio) * 371 1.1 alc targetLeft) / EEP_SCALE; 372 1.1 alc } 373 1.1 alc } else { 374 1.1 alc rv = targetLeft; 375 1.1 alc } 376 1.1 alc return rv; 377 1.1 alc } 378 1.1 alc 379 1.1 alc /* 380 1.1 alc * Read the transmit power levels from the structures taken from EEPROM 381 1.1 alc * Interpolate read transmit power values for this channel 382 1.1 alc * Organize the transmit power values into a table for writing into the hardware 383 1.1 alc */ 384 1.1 alc static HAL_BOOL 385 1.1 alc ar5111SetPowerTable(struct ath_hal *ah, 386 1.1 alc int16_t *pMinPower, int16_t *pMaxPower, HAL_CHANNEL_INTERNAL *chan, 387 1.1 alc uint16_t *rfXpdGain) 388 1.1 alc { 389 1.1 alc struct ath_hal_5212 *ahp = AH5212(ah); 390 1.1 alc const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; 391 1.1 alc FULL_PCDAC_STRUCT pcdacStruct; 392 1.1 alc int i, j; 393 1.1 alc 394 1.1 alc uint16_t *pPcdacValues; 395 1.1 alc int16_t *pScaledUpDbm; 396 1.1 alc int16_t minScaledPwr; 397 1.1 alc int16_t maxScaledPwr; 398 1.1 alc int16_t pwr; 399 1.1 alc uint16_t pcdacMin = 0; 400 1.1 alc uint16_t pcdacMax = PCDAC_STOP; 401 1.1 alc uint16_t pcdacTableIndex; 402 1.1 alc uint16_t scaledPcdac; 403 1.1 alc PCDACS_EEPROM *pSrcStruct; 404 1.1 alc PCDACS_EEPROM eepromPcdacs; 405 1.1 alc 406 1.1 alc /* setup the pcdac struct to point to the correct info, based on mode */ 407 1.1 alc switch (chan->channelFlags & CHANNEL_ALL) { 408 1.1 alc case CHANNEL_A: 409 1.1 alc case CHANNEL_T: 410 1.1 alc eepromPcdacs.numChannels = ee->ee_numChannels11a; 411 1.1 alc eepromPcdacs.pChannelList = ee->ee_channels11a; 412 1.1 alc eepromPcdacs.pDataPerChannel = ee->ee_dataPerChannel11a; 413 1.1 alc break; 414 1.1 alc case CHANNEL_B: 415 1.1 alc eepromPcdacs.numChannels = ee->ee_numChannels2_4; 416 1.1 alc eepromPcdacs.pChannelList = ee->ee_channels11b; 417 1.1 alc eepromPcdacs.pDataPerChannel = ee->ee_dataPerChannel11b; 418 1.1 alc break; 419 1.1 alc case CHANNEL_G: 420 1.1 alc case CHANNEL_108G: 421 1.1 alc eepromPcdacs.numChannels = ee->ee_numChannels2_4; 422 1.1 alc eepromPcdacs.pChannelList = ee->ee_channels11g; 423 1.1 alc eepromPcdacs.pDataPerChannel = ee->ee_dataPerChannel11g; 424 1.1 alc break; 425 1.1 alc default: 426 1.1 alc HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n", 427 1.1 alc __func__, chan->channelFlags); 428 1.1 alc return AH_FALSE; 429 1.1 alc } 430 1.1 alc 431 1.1 alc pSrcStruct = &eepromPcdacs; 432 1.1 alc 433 1.1 alc OS_MEMZERO(&pcdacStruct, sizeof(pcdacStruct)); 434 1.1 alc pPcdacValues = pcdacStruct.PcdacValues; 435 1.1 alc pScaledUpDbm = pcdacStruct.PwrValues; 436 1.1 alc 437 1.1 alc /* Initialize the pcdacs to dBM structs pcdacs to be 1 to 63 */ 438 1.1 alc for (i = PCDAC_START, j = 0; i <= PCDAC_STOP; i+= PCDAC_STEP, j++) 439 1.1 alc pPcdacValues[j] = i; 440 1.1 alc 441 1.1 alc pcdacStruct.numPcdacValues = j; 442 1.1 alc pcdacStruct.pcdacMin = PCDAC_START; 443 1.1 alc pcdacStruct.pcdacMax = PCDAC_STOP; 444 1.1 alc 445 1.1 alc /* Fill out the power values for this channel */ 446 1.1 alc for (j = 0; j < pcdacStruct.numPcdacValues; j++ ) 447 1.1 alc pScaledUpDbm[j] = ar5212GetScaledPower(chan->channel, 448 1.1 alc pPcdacValues[j], pSrcStruct); 449 1.1 alc 450 1.1 alc /* Now scale the pcdac values to fit in the 64 entry power table */ 451 1.1 alc minScaledPwr = pScaledUpDbm[0]; 452 1.1 alc maxScaledPwr = pScaledUpDbm[pcdacStruct.numPcdacValues - 1]; 453 1.1 alc 454 1.1 alc /* find minimum and make monotonic */ 455 1.1 alc for (j = 0; j < pcdacStruct.numPcdacValues; j++) { 456 1.1 alc if (minScaledPwr >= pScaledUpDbm[j]) { 457 1.1 alc minScaledPwr = pScaledUpDbm[j]; 458 1.1 alc pcdacMin = j; 459 1.1 alc } 460 1.1 alc /* 461 1.1 alc * Make the full_hsh monotonically increasing otherwise 462 1.1 alc * interpolation algorithm will get fooled gotta start 463 1.1 alc * working from the top, hence i = 63 - j. 464 1.1 alc */ 465 1.1 alc i = (uint16_t)(pcdacStruct.numPcdacValues - 1 - j); 466 1.1 alc if (i == 0) 467 1.1 alc break; 468 1.1 alc if (pScaledUpDbm[i-1] > pScaledUpDbm[i]) { 469 1.1 alc /* 470 1.1 alc * It could be a glitch, so make the power for 471 1.1 alc * this pcdac the same as the power from the 472 1.1 alc * next highest pcdac. 473 1.1 alc */ 474 1.1 alc pScaledUpDbm[i - 1] = pScaledUpDbm[i]; 475 1.1 alc } 476 1.1 alc } 477 1.1 alc 478 1.1 alc for (j = 0; j < pcdacStruct.numPcdacValues; j++) 479 1.1 alc if (maxScaledPwr < pScaledUpDbm[j]) { 480 1.1 alc maxScaledPwr = pScaledUpDbm[j]; 481 1.1 alc pcdacMax = j; 482 1.1 alc } 483 1.1 alc 484 1.1 alc /* Find the first power level with a pcdac */ 485 1.1 alc pwr = (uint16_t)(PWR_STEP * 486 1.1 alc ((minScaledPwr - PWR_MIN + PWR_STEP / 2) / PWR_STEP) + PWR_MIN); 487 1.1 alc 488 1.1 alc /* Write all the first pcdac entries based off the pcdacMin */ 489 1.1 alc pcdacTableIndex = 0; 490 1.1 alc for (i = 0; i < (2 * (pwr - PWR_MIN) / EEP_SCALE + 1); i++) { 491 1.1 alc HALASSERT(pcdacTableIndex < PWR_TABLE_SIZE); 492 1.1 alc ahp->ah_pcdacTable[pcdacTableIndex++] = pcdacMin; 493 1.1 alc } 494 1.1 alc 495 1.1 alc i = 0; 496 1.1 alc while (pwr < pScaledUpDbm[pcdacStruct.numPcdacValues - 1] && 497 1.1 alc pcdacTableIndex < PWR_TABLE_SIZE) { 498 1.1 alc pwr += PWR_STEP; 499 1.1 alc /* stop if dbM > max_power_possible */ 500 1.1 alc while (pwr < pScaledUpDbm[pcdacStruct.numPcdacValues - 1] && 501 1.1 alc (pwr - pScaledUpDbm[i])*(pwr - pScaledUpDbm[i+1]) > 0) 502 1.1 alc i++; 503 1.1 alc /* scale by 2 and add 1 to enable round up or down as needed */ 504 1.1 alc scaledPcdac = (uint16_t)(interpolate(pwr, 505 1.1 alc pScaledUpDbm[i], pScaledUpDbm[i + 1], 506 1.1 alc (uint16_t)(pPcdacValues[i] * 2), 507 1.1 alc (uint16_t)(pPcdacValues[i + 1] * 2)) + 1); 508 1.1 alc 509 1.1 alc HALASSERT(pcdacTableIndex < PWR_TABLE_SIZE); 510 1.1 alc ahp->ah_pcdacTable[pcdacTableIndex] = scaledPcdac / 2; 511 1.1 alc if (ahp->ah_pcdacTable[pcdacTableIndex] > pcdacMax) 512 1.1 alc ahp->ah_pcdacTable[pcdacTableIndex] = pcdacMax; 513 1.1 alc pcdacTableIndex++; 514 1.1 alc } 515 1.1 alc 516 1.1 alc /* Write all the last pcdac entries based off the last valid pcdac */ 517 1.1 alc while (pcdacTableIndex < PWR_TABLE_SIZE) { 518 1.1 alc ahp->ah_pcdacTable[pcdacTableIndex] = 519 1.1 alc ahp->ah_pcdacTable[pcdacTableIndex - 1]; 520 1.1 alc pcdacTableIndex++; 521 1.1 alc } 522 1.1 alc 523 1.1 alc /* No power table adjustment for 5111 */ 524 1.1 alc ahp->ah_txPowerIndexOffset = 0; 525 1.1 alc 526 1.1 alc return AH_TRUE; 527 1.1 alc } 528 1.1 alc 529 1.1 alc /* 530 1.1 alc * Get or interpolate the pcdac value from the calibrated data. 531 1.1 alc */ 532 1.1 alc static uint16_t 533 1.1 alc ar5212GetScaledPower(uint16_t channel, uint16_t pcdacValue, 534 1.1 alc const PCDACS_EEPROM *pSrcStruct) 535 1.1 alc { 536 1.1 alc uint16_t powerValue; 537 1.1 alc uint16_t lFreq, rFreq; /* left and right frequency values */ 538 1.1 alc uint16_t llPcdac, ulPcdac; /* lower and upper left pcdac values */ 539 1.1 alc uint16_t lrPcdac, urPcdac; /* lower and upper right pcdac values */ 540 1.3 mrg uint16_t lPwr = 0, uPwr = 0; /* lower and upper temp pwr values */ 541 1.1 alc uint16_t lScaledPwr, rScaledPwr; /* left and right scaled power */ 542 1.1 alc 543 1.1 alc if (ar5212FindValueInList(channel, pcdacValue, pSrcStruct, &powerValue)) { 544 1.1 alc /* value was copied from srcStruct */ 545 1.1 alc return powerValue; 546 1.1 alc } 547 1.1 alc 548 1.1 alc ar5212GetLowerUpperValues(channel, 549 1.1 alc pSrcStruct->pChannelList, pSrcStruct->numChannels, 550 1.1 alc &lFreq, &rFreq); 551 1.1 alc ar5212GetLowerUpperPcdacs(pcdacValue, 552 1.1 alc lFreq, pSrcStruct, &llPcdac, &ulPcdac); 553 1.1 alc ar5212GetLowerUpperPcdacs(pcdacValue, 554 1.1 alc rFreq, pSrcStruct, &lrPcdac, &urPcdac); 555 1.1 alc 556 1.1 alc /* get the power index for the pcdac value */ 557 1.1 alc ar5212FindValueInList(lFreq, llPcdac, pSrcStruct, &lPwr); 558 1.1 alc ar5212FindValueInList(lFreq, ulPcdac, pSrcStruct, &uPwr); 559 1.1 alc lScaledPwr = interpolate(pcdacValue, llPcdac, ulPcdac, lPwr, uPwr); 560 1.1 alc 561 1.1 alc ar5212FindValueInList(rFreq, lrPcdac, pSrcStruct, &lPwr); 562 1.1 alc ar5212FindValueInList(rFreq, urPcdac, pSrcStruct, &uPwr); 563 1.1 alc rScaledPwr = interpolate(pcdacValue, lrPcdac, urPcdac, lPwr, uPwr); 564 1.1 alc 565 1.1 alc return interpolate(channel, lFreq, rFreq, lScaledPwr, rScaledPwr); 566 1.1 alc } 567 1.1 alc 568 1.1 alc /* 569 1.1 alc * Find the value from the calibrated source data struct 570 1.1 alc */ 571 1.1 alc static HAL_BOOL 572 1.1 alc ar5212FindValueInList(uint16_t channel, uint16_t pcdacValue, 573 1.1 alc const PCDACS_EEPROM *pSrcStruct, uint16_t *powerValue) 574 1.1 alc { 575 1.1 alc const DATA_PER_CHANNEL *pChannelData = pSrcStruct->pDataPerChannel; 576 1.1 alc int i; 577 1.1 alc 578 1.1 alc for (i = 0; i < pSrcStruct->numChannels; i++ ) { 579 1.1 alc if (pChannelData->channelValue == channel) { 580 1.1 alc const uint16_t* pPcdac = pChannelData->PcdacValues; 581 1.1 alc int j; 582 1.1 alc 583 1.1 alc for (j = 0; j < pChannelData->numPcdacValues; j++ ) { 584 1.1 alc if (*pPcdac == pcdacValue) { 585 1.1 alc *powerValue = pChannelData->PwrValues[j]; 586 1.1 alc return AH_TRUE; 587 1.1 alc } 588 1.1 alc pPcdac++; 589 1.1 alc } 590 1.1 alc } 591 1.1 alc pChannelData++; 592 1.1 alc } 593 1.1 alc return AH_FALSE; 594 1.1 alc } 595 1.1 alc 596 1.1 alc /* 597 1.1 alc * Get the upper and lower pcdac given the channel and the pcdac 598 1.1 alc * used in the search 599 1.1 alc */ 600 1.1 alc static void 601 1.1 alc ar5212GetLowerUpperPcdacs(uint16_t pcdac, uint16_t channel, 602 1.1 alc const PCDACS_EEPROM *pSrcStruct, 603 1.1 alc uint16_t *pLowerPcdac, uint16_t *pUpperPcdac) 604 1.1 alc { 605 1.1 alc const DATA_PER_CHANNEL *pChannelData = pSrcStruct->pDataPerChannel; 606 1.1 alc int i; 607 1.1 alc 608 1.1 alc /* Find the channel information */ 609 1.1 alc for (i = 0; i < pSrcStruct->numChannels; i++) { 610 1.1 alc if (pChannelData->channelValue == channel) 611 1.1 alc break; 612 1.1 alc pChannelData++; 613 1.1 alc } 614 1.1 alc ar5212GetLowerUpperValues(pcdac, pChannelData->PcdacValues, 615 1.1 alc pChannelData->numPcdacValues, 616 1.1 alc pLowerPcdac, pUpperPcdac); 617 1.1 alc } 618 1.1 alc 619 1.1 alc static HAL_BOOL 620 1.1 alc ar5111GetChannelMaxMinPower(struct ath_hal *ah, HAL_CHANNEL *chan, 621 1.1 alc int16_t *maxPow, int16_t *minPow) 622 1.1 alc { 623 1.1 alc /* XXX - Get 5111 power limits! */ 624 1.1 alc /* NB: caller will cope */ 625 1.1 alc return AH_FALSE; 626 1.1 alc } 627 1.1 alc 628 1.1 alc /* 629 1.1 alc * Adjust NF based on statistical values for 5GHz frequencies. 630 1.1 alc */ 631 1.1 alc static int16_t 632 1.1 alc ar5111GetNfAdjust(struct ath_hal *ah, const HAL_CHANNEL_INTERNAL *c) 633 1.1 alc { 634 1.1 alc static const struct { 635 1.1 alc uint16_t freqLow; 636 1.1 alc int16_t adjust; 637 1.1 alc } adjust5111[] = { 638 1.1 alc { 5790, 6 }, /* NB: ordered high -> low */ 639 1.1 alc { 5730, 4 }, 640 1.1 alc { 5690, 3 }, 641 1.1 alc { 5660, 2 }, 642 1.1 alc { 5610, 1 }, 643 1.1 alc { 5530, 0 }, 644 1.1 alc { 5450, 0 }, 645 1.1 alc { 5379, 1 }, 646 1.1 alc { 5209, 3 }, 647 1.1 alc { 3000, 5 }, 648 1.1 alc { 0, 0 }, 649 1.1 alc }; 650 1.1 alc int i; 651 1.1 alc 652 1.1 alc for (i = 0; c->channel <= adjust5111[i].freqLow; i++) 653 1.1 alc ; 654 1.1 alc return adjust5111[i].adjust; 655 1.1 alc } 656 1.1 alc 657 1.1 alc /* 658 1.1 alc * Free memory for analog bank scratch buffers 659 1.1 alc */ 660 1.1 alc static void 661 1.1 alc ar5111RfDetach(struct ath_hal *ah) 662 1.1 alc { 663 1.1 alc struct ath_hal_5212 *ahp = AH5212(ah); 664 1.1 alc 665 1.1 alc HALASSERT(ahp->ah_rfHal != AH_NULL); 666 1.1 alc ath_hal_free(ahp->ah_rfHal); 667 1.1 alc ahp->ah_rfHal = AH_NULL; 668 1.1 alc } 669 1.1 alc 670 1.1 alc /* 671 1.1 alc * Allocate memory for analog bank scratch buffers 672 1.1 alc * Scratch Buffer will be reinitialized every reset so no need to zero now 673 1.1 alc */ 674 1.1 alc static HAL_BOOL 675 1.1 alc ar5111RfAttach(struct ath_hal *ah, HAL_STATUS *status) 676 1.1 alc { 677 1.1 alc struct ath_hal_5212 *ahp = AH5212(ah); 678 1.1 alc struct ar5111State *priv; 679 1.1 alc 680 1.1 alc HALASSERT(ah->ah_magic == AR5212_MAGIC); 681 1.1 alc 682 1.1 alc HALASSERT(ahp->ah_rfHal == AH_NULL); 683 1.1 alc priv = ath_hal_malloc(sizeof(struct ar5111State)); 684 1.1 alc if (priv == AH_NULL) { 685 1.1 alc HALDEBUG(ah, HAL_DEBUG_ANY, 686 1.1 alc "%s: cannot allocate private state\n", __func__); 687 1.1 alc *status = HAL_ENOMEM; /* XXX */ 688 1.1 alc return AH_FALSE; 689 1.1 alc } 690 1.1 alc priv->base.rfDetach = ar5111RfDetach; 691 1.1 alc priv->base.writeRegs = ar5111WriteRegs; 692 1.1 alc priv->base.getRfBank = ar5111GetRfBank; 693 1.1 alc priv->base.setChannel = ar5111SetChannel; 694 1.1 alc priv->base.setRfRegs = ar5111SetRfRegs; 695 1.1 alc priv->base.setPowerTable = ar5111SetPowerTable; 696 1.1 alc priv->base.getChannelMaxMinPower = ar5111GetChannelMaxMinPower; 697 1.1 alc priv->base.getNfAdjust = ar5111GetNfAdjust; 698 1.1 alc 699 1.1 alc ahp->ah_pcdacTable = priv->pcdacTable; 700 1.1 alc ahp->ah_pcdacTableSize = sizeof(priv->pcdacTable); 701 1.1 alc ahp->ah_rfHal = &priv->base; 702 1.1 alc 703 1.1 alc return AH_TRUE; 704 1.1 alc } 705 1.1 alc 706 1.1 alc static HAL_BOOL 707 1.1 alc ar5111Probe(struct ath_hal *ah) 708 1.1 alc { 709 1.1 alc return IS_RAD5111(ah); 710 1.1 alc } 711 1.1 alc AH_RF(RF5111, ar5111Probe, ar5111RfAttach); 712