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