FreeBSD kernel ATH device code
ar5211_reset.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-2006 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/*
24 * Chips specific device attachment and device info collection
25 * Connects Init Reg Vectors, EEPROM Data, and device Functions.
26 */
27#include "ah.h"
28#include "ah_internal.h"
29#include "ah_devid.h"
30
31#include "ar5211/ar5211.h"
32#include "ar5211/ar5211reg.h"
33#include "ar5211/ar5211phy.h"
34
35#include "ah_eeprom_v3.h"
36
37/* Add static register initialization vectors */
38#include "ar5211/boss.ini"
39
40/*
41 * Structure to hold 11b tuning information for Beanie/Sombrero
42 * 16 MHz mode, divider ratio = 198 = NP+S. N=16, S=4 or 6, P=12
43 */
44typedef struct {
45 uint32_t refClkSel; /* reference clock, 1 for 16 MHz */
46 uint32_t channelSelect; /* P[7:4]S[3:0] bits */
47 uint16_t channel5111; /* 11a channel for 5111 */
49
50#define CI_2GHZ_INDEX_CORRECTION 19
51static const CHAN_INFO_2GHZ chan2GHzData[] = {
52 { 1, 0x46, 96 }, /* 2312 -19 */
53 { 1, 0x46, 97 }, /* 2317 -18 */
54 { 1, 0x46, 98 }, /* 2322 -17 */
55 { 1, 0x46, 99 }, /* 2327 -16 */
56 { 1, 0x46, 100 }, /* 2332 -15 */
57 { 1, 0x46, 101 }, /* 2337 -14 */
58 { 1, 0x46, 102 }, /* 2342 -13 */
59 { 1, 0x46, 103 }, /* 2347 -12 */
60 { 1, 0x46, 104 }, /* 2352 -11 */
61 { 1, 0x46, 105 }, /* 2357 -10 */
62 { 1, 0x46, 106 }, /* 2362 -9 */
63 { 1, 0x46, 107 }, /* 2367 -8 */
64 { 1, 0x46, 108 }, /* 2372 -7 */
65 /* index -6 to 0 are pad to make this a nolookup table */
66 { 1, 0x46, 116 }, /* -6 */
67 { 1, 0x46, 116 }, /* -5 */
68 { 1, 0x46, 116 }, /* -4 */
69 { 1, 0x46, 116 }, /* -3 */
70 { 1, 0x46, 116 }, /* -2 */
71 { 1, 0x46, 116 }, /* -1 */
72 { 1, 0x46, 116 }, /* 0 */
73 { 1, 0x46, 116 }, /* 2412 1 */
74 { 1, 0x46, 117 }, /* 2417 2 */
75 { 1, 0x46, 118 }, /* 2422 3 */
76 { 1, 0x46, 119 }, /* 2427 4 */
77 { 1, 0x46, 120 }, /* 2432 5 */
78 { 1, 0x46, 121 }, /* 2437 6 */
79 { 1, 0x46, 122 }, /* 2442 7 */
80 { 1, 0x46, 123 }, /* 2447 8 */
81 { 1, 0x46, 124 }, /* 2452 9 */
82 { 1, 0x46, 125 }, /* 2457 10 */
83 { 1, 0x46, 126 }, /* 2462 11 */
84 { 1, 0x46, 127 }, /* 2467 12 */
85 { 1, 0x46, 128 }, /* 2472 13 */
86 { 1, 0x44, 124 }, /* 2484 14 */
87 { 1, 0x46, 136 }, /* 2512 15 */
88 { 1, 0x46, 140 }, /* 2532 16 */
89 { 1, 0x46, 144 }, /* 2552 17 */
90 { 1, 0x46, 148 }, /* 2572 18 */
91 { 1, 0x46, 152 }, /* 2592 19 */
92 { 1, 0x46, 156 }, /* 2612 20 */
93 { 1, 0x46, 160 }, /* 2632 21 */
94 { 1, 0x46, 164 }, /* 2652 22 */
95 { 1, 0x46, 168 }, /* 2672 23 */
96 { 1, 0x46, 172 }, /* 2692 24 */
97 { 1, 0x46, 176 }, /* 2712 25 */
98 { 1, 0x46, 180 } /* 2732 26 */
99};
100
101/* Power timeouts in usec to wait for chip to wake-up. */
102#define POWER_UP_TIME 2000
103
104#define DELAY_PLL_SETTLE 300 /* 300 us */
105#define DELAY_BASE_ACTIVATE 100 /* 100 us */
106
107#define NUM_RATES 8
108
109static HAL_BOOL ar5211SetResetReg(struct ath_hal *ah, uint32_t resetMask);
110static HAL_BOOL ar5211SetChannel(struct ath_hal *,
111 const struct ieee80211_channel *);
112static int16_t ar5211RunNoiseFloor(struct ath_hal *,
113 uint8_t runTime, int16_t startingNF);
114static HAL_BOOL ar5211IsNfGood(struct ath_hal *,
115 struct ieee80211_channel *chan);
116static HAL_BOOL ar5211SetRf6and7(struct ath_hal *,
117 const struct ieee80211_channel *chan);
119 const struct ieee80211_channel *chan);
120static void ar5211SetPowerTable(struct ath_hal *,
121 PCDACS_EEPROM *pSrcStruct, uint16_t channel);
123 const struct ieee80211_channel *);
124static void ar5211SetRateTable(struct ath_hal *,
125 RD_EDGES_POWER *pRdEdgesPower, TRGT_POWER_INFO *pPowerInfo,
126 uint16_t numChannels, const struct ieee80211_channel *chan);
127static uint16_t ar5211GetScaledPower(uint16_t channel, uint16_t pcdacValue,
128 const PCDACS_EEPROM *pSrcStruct);
129static HAL_BOOL ar5211FindValueInList(uint16_t channel, uint16_t pcdacValue,
130 const PCDACS_EEPROM *pSrcStruct, uint16_t *powerValue);
131static uint16_t ar5211GetInterpolatedValue(uint16_t target,
132 uint16_t srcLeft, uint16_t srcRight,
133 uint16_t targetLeft, uint16_t targetRight, HAL_BOOL scaleUp);
134static void ar5211GetLowerUpperValues(uint16_t value,
135 const uint16_t *pList, uint16_t listSize,
136 uint16_t *pLowerValue, uint16_t *pUpperValue);
137static void ar5211GetLowerUpperPcdacs(uint16_t pcdac,
138 uint16_t channel, const PCDACS_EEPROM *pSrcStruct,
139 uint16_t *pLowerPcdac, uint16_t *pUpperPcdac);
140
141static void ar5211SetRfgain(struct ath_hal *, const GAIN_VALUES *);
142static void ar5211RequestRfgain(struct ath_hal *);
144static HAL_BOOL ar5211IsGainAdjustNeeded(struct ath_hal *, const GAIN_VALUES *);
145static int32_t ar5211AdjustGain(struct ath_hal *, GAIN_VALUES *);
146static void ar5211SetOperatingMode(struct ath_hal *, int opmode);
147
148/*
149 * Places the device in and out of reset and then places sane
150 * values in the registers based on EEPROM config, initialization
151 * vectors (as determined by the mode), and station configuration
152 *
153 * bChannelChange is used to preserve DMA/PCU registers across
154 * a HW Reset during channel change.
155 */
157ar5211Reset(struct ath_hal *ah, HAL_OPMODE opmode,
158 struct ieee80211_channel *chan, HAL_BOOL bChannelChange,
159 HAL_RESET_TYPE resetType,
160 HAL_STATUS *status)
161{
162uint32_t softLedCfg, softLedState;
163#define N(a) (sizeof (a) /sizeof (a[0]))
164#define FAIL(_code) do { ecode = _code; goto bad; } while (0)
165 struct ath_hal_5211 *ahp = AH5211(ah);
167 uint32_t i, ledstate;
168 HAL_STATUS ecode;
169 int q;
170
171 uint32_t data, synthDelay;
172 uint32_t macStaId1;
173 uint16_t modesIndex = 0, freqIndex = 0;
174 uint32_t saveFrameSeqCount[AR_NUM_DCU];
175 uint32_t saveTsfLow = 0, saveTsfHigh = 0;
176 uint32_t saveDefAntenna;
177
179 "%s: opmode %u channel %u/0x%x %s channel\n",
180 __func__, opmode, chan->ic_freq, chan->ic_flags,
181 bChannelChange ? "change" : "same");
182
183 OS_MARK(ah, AH_MARK_RESET, bChannelChange);
184 /*
185 * Map public channel to private.
186 */
187 ichan = ath_hal_checkchannel(ah, chan);
188 if (ichan == AH_NULL)
190 switch (opmode) {
191 case HAL_M_STA:
192 case HAL_M_IBSS:
193 case HAL_M_HOSTAP:
194 case HAL_M_MONITOR:
195 break;
196 default:
198 "%s: invalid operating mode %u\n", __func__, opmode);
200 break;
201 }
202 HALASSERT(AH_PRIVATE(ah)->ah_eeversion >= AR_EEPROM_VER3);
203
204 /* Preserve certain DMA hardware registers on a channel change */
205 if (bChannelChange) {
206 /*
207 * Need to save/restore the TSF because of an issue
208 * that accelerates the TSF during a chip reset.
209 *
210 * We could use system timer routines to more
211 * accurately restore the TSF, but
212 * 1. Timer routines on certain platforms are
213 * not accurate enough (e.g. 1 ms resolution).
214 * 2. It would still not be accurate.
215 *
216 * The most important aspect of this workaround,
217 * is that, after reset, the TSF is behind
218 * other STAs TSFs. This will allow the STA to
219 * properly resynchronize its TSF in adhoc mode.
220 */
221 saveTsfLow = OS_REG_READ(ah, AR_TSF_L32);
222 saveTsfHigh = OS_REG_READ(ah, AR_TSF_U32);
223
224 /* Read frame sequence count */
225 if (AH_PRIVATE(ah)->ah_macVersion >= AR_SREV_VERSION_OAHU) {
226 saveFrameSeqCount[0] = OS_REG_READ(ah, AR_D0_SEQNUM);
227 } else {
228 for (i = 0; i < AR_NUM_DCU; i++)
229 saveFrameSeqCount[i] = OS_REG_READ(ah, AR_DSEQNUM(i));
230 }
231 if (!IEEE80211_IS_CHAN_DFS(chan))
232 chan->ic_state &= ~IEEE80211_CHANSTATE_CWINT;
233 }
234
235 /*
236 * Preserve the antenna on a channel change
237 */
238 saveDefAntenna = OS_REG_READ(ah, AR_DEF_ANTENNA);
239 if (saveDefAntenna == 0)
240 saveDefAntenna = 1;
241
242 /* Save hardware flag before chip reset clears the register */
244
245 /* Save led state from pci config register */
246 ledstate = OS_REG_READ(ah, AR_PCICFG) &
249 softLedCfg = OS_REG_READ(ah, AR_GPIOCR);
250 softLedState = OS_REG_READ(ah, AR_GPIODO);
251
252 if (!ar5211ChipReset(ah, chan)) {
253 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__);
254 FAIL(HAL_EIO);
255 }
256
257 /* Setup the indices for the next set of register array writes */
258 if (IEEE80211_IS_CHAN_5GHZ(chan)) {
259 freqIndex = 1;
260 if (IEEE80211_IS_CHAN_TURBO(chan))
261 modesIndex = 2;
262 else if (IEEE80211_IS_CHAN_A(chan))
263 modesIndex = 1;
264 else {
266 "%s: invalid channel %u/0x%x\n",
267 __func__, chan->ic_freq, chan->ic_flags);
269 }
270 } else {
271 freqIndex = 2;
272 if (IEEE80211_IS_CHAN_B(chan))
273 modesIndex = 3;
274 else if (IEEE80211_IS_CHAN_PUREG(chan))
275 modesIndex = 4;
276 else {
278 "%s: invalid channel %u/0x%x\n",
279 __func__, chan->ic_freq, chan->ic_flags);
281 }
282 }
283
284 /* Set correct Baseband to analog shift setting to access analog chips. */
285 if (AH_PRIVATE(ah)->ah_macVersion >= AR_SREV_VERSION_OAHU) {
286 OS_REG_WRITE(ah, AR_PHY_BASE, 0x00000007);
287 } else {
288 OS_REG_WRITE(ah, AR_PHY_BASE, 0x00000047);
289 }
290
291 /* Write parameters specific to AR5211 */
292 if (AH_PRIVATE(ah)->ah_macVersion >= AR_SREV_VERSION_OAHU) {
293 if (IEEE80211_IS_CHAN_2GHZ(chan) &&
294 AH_PRIVATE(ah)->ah_eeversion >= AR_EEPROM_VER3_1) {
295 HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
296 uint32_t ob2GHz, db2GHz;
297
298 if (IEEE80211_IS_CHAN_CCK(chan)) {
299 ob2GHz = ee->ee_ob2GHz[0];
300 db2GHz = ee->ee_db2GHz[0];
301 } else {
302 ob2GHz = ee->ee_ob2GHz[1];
303 db2GHz = ee->ee_db2GHz[1];
304 }
305 ob2GHz = ath_hal_reverseBits(ob2GHz, 3);
306 db2GHz = ath_hal_reverseBits(db2GHz, 3);
307 ar5211Mode2_4[25][freqIndex] =
308 (ar5211Mode2_4[25][freqIndex] & ~0xC0) |
309 ((ob2GHz << 6) & 0xC0);
310 ar5211Mode2_4[26][freqIndex] =
311 (ar5211Mode2_4[26][freqIndex] & ~0x0F) |
312 (((ob2GHz >> 2) & 0x1) |
313 ((db2GHz << 1) & 0x0E));
314 }
315 for (i = 0; i < N(ar5211Mode2_4); i++)
316 OS_REG_WRITE(ah, ar5211Mode2_4[i][0],
317 ar5211Mode2_4[i][freqIndex]);
318 }
319
320 /* Write the analog registers 6 and 7 before other config */
321 ar5211SetRf6and7(ah, chan);
322
323 /* Write registers that vary across all modes */
324 for (i = 0; i < N(ar5211Modes); i++)
325 OS_REG_WRITE(ah, ar5211Modes[i][0], ar5211Modes[i][modesIndex]);
326
327 /* Write RFGain Parameters that differ between 2.4 and 5 GHz */
328 for (i = 0; i < N(ar5211BB_RfGain); i++)
329 OS_REG_WRITE(ah, ar5211BB_RfGain[i][0], ar5211BB_RfGain[i][freqIndex]);
330
331 /* Write Common Array Parameters */
332 for (i = 0; i < N(ar5211Common); i++) {
333 uint32_t reg = ar5211Common[i][0];
334 /* On channel change, don't reset the PCU registers */
335 if (!(bChannelChange && (0x8000 <= reg && reg < 0x9000)))
336 OS_REG_WRITE(ah, reg, ar5211Common[i][1]);
337 }
338
339 /* Fix pre-AR5211 register values, this includes AR5311s. */
340 if (AH_PRIVATE(ah)->ah_macVersion < AR_SREV_VERSION_OAHU) {
341 /*
342 * The TX and RX latency values have changed locations
343 * within the USEC register in AR5211. Since they're
344 * set via the .ini, for both AR5211 and AR5311, they
345 * are written properly here for AR5311.
346 */
347 data = OS_REG_READ(ah, AR_USEC);
348 /* Must be 0 for proper write in AR5311 */
349 HALASSERT((data & 0x00700000) == 0);
353 /* The following registers exist only on AR5311. */
355
356 /* Set proper ADC & DAC delays for AR5311. */
357 OS_REG_WRITE(ah, 0x00009878, 0x00000008);
358
359 /* Enable the PCU FIFO corruption ECO on AR5311. */
362 }
363
364 /* Restore certain DMA hardware registers on a channel change */
365 if (bChannelChange) {
366 /* Restore TSF */
367 OS_REG_WRITE(ah, AR_TSF_L32, saveTsfLow);
368 OS_REG_WRITE(ah, AR_TSF_U32, saveTsfHigh);
369
370 if (AH_PRIVATE(ah)->ah_macVersion >= AR_SREV_VERSION_OAHU) {
371 OS_REG_WRITE(ah, AR_D0_SEQNUM, saveFrameSeqCount[0]);
372 } else {
373 for (i = 0; i < AR_NUM_DCU; i++)
374 OS_REG_WRITE(ah, AR_DSEQNUM(i), saveFrameSeqCount[i]);
375 }
376 }
377
380 | macStaId1
381 );
382 ar5211SetOperatingMode(ah, opmode);
383
384 /* Restore previous led state */
385 OS_REG_WRITE(ah, AR_PCICFG, OS_REG_READ(ah, AR_PCICFG) | ledstate);
386 OS_REG_WRITE(ah, AR_GPIOCR, softLedCfg);
387 OS_REG_WRITE(ah, AR_GPIODO, softLedState);
388
389 /* Restore previous antenna */
390 OS_REG_WRITE(ah, AR_DEF_ANTENNA, saveDefAntenna);
391
394
395 /* Restore bmiss rssi & count thresholds */
397
398 OS_REG_WRITE(ah, AR_ISR, ~0); /* cleared on write */
399
400 /*
401 * for pre-Production Oahu only.
402 * Disable clock gating in all DMA blocks. Helps when using
403 * 11B and AES but results in higher power consumption.
404 */
405 if (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_VERSION_OAHU &&
406 AH_PRIVATE(ah)->ah_macRev < AR_SREV_OAHU_PROD) {
409 }
410
411 /* Setup the transmit power values. */
412 if (!ar5211SetTransmitPower(ah, chan)) {
414 "%s: error init'ing transmit power\n", __func__);
415 FAIL(HAL_EIO);
416 }
417
418 /*
419 * Configurable OFDM spoofing for 11n compatibility; used
420 * only when operating in station mode.
421 */
422 if (opmode != HAL_M_HOSTAP &&
423 (AH_PRIVATE(ah)->ah_11nCompat & HAL_DIAG_11N_SERVICES) != 0) {
424 /* NB: override the .ini setting */
427 MS(AH_PRIVATE(ah)->ah_11nCompat, HAL_DIAG_11N_SERVICES)&1);
428 }
429
430 /* Setup board specific options for EEPROM version 3 */
431 ar5211SetBoardValues(ah, chan);
432
433 if (!ar5211SetChannel(ah, chan)) {
434 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unable to set channel\n",
435 __func__);
436 FAIL(HAL_EIO);
437 }
438
439 /* Activate the PHY */
440 if (AH_PRIVATE(ah)->ah_devid == AR5211_FPGA11B &&
441 IEEE80211_IS_CHAN_2GHZ(chan))
442 OS_REG_WRITE(ah, 0xd808, 0x502); /* required for FPGA */
444
445 /*
446 * Wait for the frequency synth to settle (synth goes on
447 * via AR_PHY_ACTIVE_EN). Read the phy active delay register.
448 * Value is in 100ns increments.
449 */
451 if (IEEE80211_IS_CHAN_CCK(chan)) {
452 synthDelay = (4 * data) / 22;
453 } else {
454 synthDelay = data / 10;
455 }
456 /*
457 * There is an issue if the AP starts the calibration before
458 * the baseband timeout completes. This could result in the
459 * rxclear false triggering. Add an extra delay to ensure this
460 * this does not happen.
461 */
462 OS_DELAY(synthDelay + DELAY_BASE_ACTIVATE);
463
464 /* Calibrate the AGC and wait for completion. */
468
469 /* Perform noise floor and set status */
470 if (!ar5211CalNoiseFloor(ah, chan)) {
471 if (!IEEE80211_IS_CHAN_CCK(chan))
472 chan->ic_state |= IEEE80211_CHANSTATE_CWINT;
474 "%s: noise floor calibration failed\n", __func__);
475 FAIL(HAL_EIO);
476 }
477
478 /* Start IQ calibration w/ 2^(INIT_IQCAL_LOG_COUNT_MAX+1) samples */
479 if (ahp->ah_calibrationTime != 0) {
483 }
484
485 /* set 1:1 QCU to DCU mapping for all queues */
486 for (q = 0; q < AR_NUM_DCU; q++)
487 OS_REG_WRITE(ah, AR_DQCUMASK(q), 1<<q);
488
489 for (q = 0; q < HAL_NUM_TX_QUEUES; q++)
490 ar5211ResetTxQueue(ah, q);
491
492 /* Setup QCU0 transmit interrupt masks (TX_ERR, TX_OK, TX_DESC, TX_URN) */
498
499 /*
500 * GBL_EIFS must always be written after writing
501 * to any QCUMASK register.
502 */
504
505 /* Now set up the Interrupt Mask Register and save it for future use */
508
509 /* Enable bus error interrupts */
512
513 /* Enable interrupts specific to AP */
514 if (opmode == HAL_M_HOSTAP) {
516 ahp->ah_maskReg |= AR_IMR_MIB;
517 }
518
519 if (AH_PRIVATE(ah)->ah_rfkillEnabled)
521
522 /*
523 * Writing to AR_BEACON will start timers. Hence it should
524 * be the last register to be written. Do not reset tsf, do
525 * not enable beacons at this point, but preserve other values
526 * like beaconInterval.
527 */
530
531 /* Restore user-specified slot time and timeouts */
532 if (ahp->ah_sifstime != (u_int) -1)
534 if (ahp->ah_slottime != (u_int) -1)
536 if (ahp->ah_acktimeout != (u_int) -1)
538 if (ahp->ah_ctstimeout != (u_int) -1)
540 if (AH_PRIVATE(ah)->ah_diagreg != 0)
541 OS_REG_WRITE(ah, AR_DIAG_SW, AH_PRIVATE(ah)->ah_diagreg);
542
543 AH_PRIVATE(ah)->ah_opmode = opmode; /* record operating mode */
544
545 HALDEBUG(ah, HAL_DEBUG_RESET, "%s: done\n", __func__);
546
547 return AH_TRUE;
548bad:
549 if (status != AH_NULL)
550 *status = ecode;
551 return AH_FALSE;
552#undef FAIL
553#undef N
554}
555
556/*
557 * Places the PHY and Radio chips into reset. A full reset
558 * must be called to leave this state. The PCI/MAC/PCU are
559 * not placed into reset as we must receive interrupt to
560 * re-enable the hardware.
561 */
564{
565 return ar5211SetResetReg(ah, AR_RC_BB);
566}
567
568/*
569 * Places all of hardware into reset
570 */
573{
575 return AH_FALSE;
576 /*
577 * Reset the HW - PCI must be reset after the rest of the
578 * device has been reset.
579 */
581 return AH_FALSE;
582 OS_DELAY(2100); /* 8245 @ 96Mhz hangs with 2000us. */
583
584 return AH_TRUE;
585}
586
587/*
588 * Places the hardware into reset and then pulls it out of reset
589 *
590 * Only write the PLL if we're changing to or from CCK mode
591 *
592 * Attach calls with channelFlags = 0, as the coldreset should have
593 * us in the correct mode and we cannot check the hwchannel flags.
594 */
596ar5211ChipReset(struct ath_hal *ah, const struct ieee80211_channel *chan)
597{
599 return AH_FALSE;
600
601 /* NB: called from attach with chan null */
602 if (chan != AH_NULL) {
603 /* Set CCK and Turbo modes correctly */
604 OS_REG_WRITE(ah, AR_PHY_TURBO, IEEE80211_IS_CHAN_TURBO(chan) ?
606 if (IEEE80211_IS_CHAN_B(chan)) {
610 /* Wait for the PLL to settle */
612 } else if (AH_PRIVATE(ah)->ah_devid == AR5211_DEVID) {
616 AR5211_PHY_MODE_OFDM | (IEEE80211_IS_CHAN_2GHZ(chan) ?
619 }
620 }
621
622 /*
623 * Reset the HW - PCI must be reset after the rest of the
624 * device has been reset
625 */
627 return AH_FALSE;
628 OS_DELAY(2100); /* 8245 @ 96Mhz hangs with 2000us. */
629
630 /* Bring out of sleep mode (AGAIN) */
632 return AH_FALSE;
633
634 /* Clear warm reset register */
635 return ar5211SetResetReg(ah, 0);
636}
637
638/*
639 * Recalibrate the lower PHY chips to account for temperature/environment
640 * changes.
641 */
643ar5211PerCalibrationN(struct ath_hal *ah, struct ieee80211_channel *chan,
644 u_int chainMask, HAL_BOOL longCal, HAL_BOOL *isCalDone)
645{
646 struct ath_hal_5211 *ahp = AH5211(ah);
648 int32_t qCoff, qCoffDenom;
649 uint32_t data;
650 int32_t iqCorrMeas;
651 int32_t iCoff, iCoffDenom;
652 uint32_t powerMeasQ, powerMeasI;
653
654 ichan = ath_hal_checkchannel(ah, chan);
655 if (ichan == AH_NULL) {
657 "%s: invalid channel %u/0x%x; no mapping\n",
658 __func__, chan->ic_freq, chan->ic_flags);
659 return AH_FALSE;
660 }
661 /* IQ calibration in progress. Check to see if it has finished. */
662 if (ahp->ah_bIQCalibration &&
664 /* IQ Calibration has finished. */
666
667 /* Read calibration results. */
671
672 /*
673 * Prescale these values to remove 64-bit operation requirement at the loss
674 * of a little precision.
675 */
676 iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 128;
677 qCoffDenom = powerMeasQ / 64;
678
679 /* Protect against divide-by-0. */
680 if (iCoffDenom != 0 && qCoffDenom != 0) {
681 iCoff = (-iqCorrMeas) / iCoffDenom;
682 /* IQCORR_Q_I_COFF is a signed 6 bit number */
683 iCoff = iCoff & 0x3f;
684
685 qCoff = ((int32_t)powerMeasI / qCoffDenom) - 64;
686 /* IQCORR_Q_Q_COFF is a signed 5 bit number */
687 qCoff = qCoff & 0x1f;
688
689 HALDEBUG(ah, HAL_DEBUG_PERCAL, "powerMeasI = 0x%08x\n",
690 powerMeasI);
691 HALDEBUG(ah, HAL_DEBUG_PERCAL, "powerMeasQ = 0x%08x\n",
692 powerMeasQ);
693 HALDEBUG(ah, HAL_DEBUG_PERCAL, "iqCorrMeas = 0x%08x\n",
694 iqCorrMeas);
695 HALDEBUG(ah, HAL_DEBUG_PERCAL, "iCoff = %d\n",
696 iCoff);
697 HALDEBUG(ah, HAL_DEBUG_PERCAL, "qCoff = %d\n",
698 qCoff);
699
700 /* Write IQ */
701 data = OS_REG_READ(ah, AR_PHY_TIMING_CTRL4) |
703 (((uint32_t)iCoff) << AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF_S) |
704 ((uint32_t)qCoff);
706 }
707 }
708 *isCalDone = !ahp->ah_bIQCalibration;
709
710 if (longCal) {
711 /* Perform noise floor and set status */
712 if (!ar5211IsNfGood(ah, chan)) {
713 /* report up and clear internal state */
714 chan->ic_state |= IEEE80211_CHANSTATE_CWINT;
715 return AH_FALSE;
716 }
717 if (!ar5211CalNoiseFloor(ah, chan)) {
718 /*
719 * Delay 5ms before retrying the noise floor
720 * just to make sure, as we are in an error
721 * condition here.
722 */
723 OS_DELAY(5000);
724 if (!ar5211CalNoiseFloor(ah, chan)) {
725 if (!IEEE80211_IS_CHAN_CCK(chan))
726 chan->ic_state |= IEEE80211_CHANSTATE_CWINT;
727 return AH_FALSE;
728 }
729 }
731 }
732 return AH_TRUE;
733}
734
736ar5211PerCalibration(struct ath_hal *ah, struct ieee80211_channel *chan,
737 HAL_BOOL *isIQdone)
738{
739 return ar5211PerCalibrationN(ah, chan, 0x1, AH_TRUE, isIQdone);
740}
741
743ar5211ResetCalValid(struct ath_hal *ah, const struct ieee80211_channel *chan)
744{
745 /* XXX */
746 return AH_TRUE;
747}
748
749/*
750 * Writes the given reset bit mask into the reset register
751 */
752static HAL_BOOL
753ar5211SetResetReg(struct ath_hal *ah, uint32_t resetMask)
754{
755 uint32_t mask = resetMask ? resetMask : ~0;
756 HAL_BOOL rt;
757
758 (void) OS_REG_READ(ah, AR_RXDP);/* flush any pending MMR writes */
759 OS_REG_WRITE(ah, AR_RC, resetMask);
760
761 /* need to wait at least 128 clocks when reseting PCI before read */
762 OS_DELAY(15);
763
764 resetMask &= AR_RC_MAC | AR_RC_BB;
765 mask &= AR_RC_MAC | AR_RC_BB;
766 rt = ath_hal_wait(ah, AR_RC, mask, resetMask);
767 if ((resetMask & AR_RC_MAC) == 0) {
768 if (isBigEndian()) {
769 /*
770 * Set CFG, little-endian for descriptor accesses.
771 */
773 OS_REG_WRITE(ah, AR_CFG, mask);
774 } else
776 }
777 return rt;
778}
779
780/*
781 * Takes the MHz channel value and sets the Channel value
782 *
783 * ASSUMES: Writes enabled to analog bus before AGC is active
784 * or by disabling the AGC.
785 */
786static HAL_BOOL
787ar5211SetChannel(struct ath_hal *ah, const struct ieee80211_channel *chan)
788{
789 uint32_t refClk, reg32, data2111;
790 int16_t chan5111, chanIEEE;
791
792 chanIEEE = chan->ic_ieee;
793 if (IEEE80211_IS_CHAN_2GHZ(chan)) {
794 const CHAN_INFO_2GHZ* ci =
796
797 data2111 = ((ath_hal_reverseBits(ci->channelSelect, 8) & 0xff)
798 << 5)
799 | (ci->refClkSel << 4);
800 chan5111 = ci->channel5111;
801 } else {
802 data2111 = 0;
803 chan5111 = chanIEEE;
804 }
805
806 /* Rest of the code is common for 5 GHz and 2.4 GHz. */
807 if (chan5111 >= 145 || (chan5111 & 0x1)) {
808 reg32 = ath_hal_reverseBits(chan5111 - 24, 8) & 0xFF;
809 refClk = 1;
810 } else {
811 reg32 = ath_hal_reverseBits(((chan5111 - 24) / 2), 8) & 0xFF;
812 refClk = 0;
813 }
814
815 reg32 = (reg32 << 2) | (refClk << 1) | (1 << 10) | 0x1;
816 OS_REG_WRITE(ah, AR_PHY(0x27), ((data2111 & 0xff) << 8) | (reg32 & 0xff));
817 reg32 >>= 8;
818 OS_REG_WRITE(ah, AR_PHY(0x34), (data2111 & 0xff00) | (reg32 & 0xff));
819
820 AH_PRIVATE(ah)->ah_curchan = chan;
821 return AH_TRUE;
822}
823
824static int16_t
826{
827 int16_t nf;
828
829 nf = (OS_REG_READ(ah, AR_PHY(25)) >> 19) & 0x1ff;
830 if (nf & 0x100)
831 nf = 0 - ((nf ^ 0x1ff) + 1);
832 return nf;
833}
834
835/*
836 * Peform the noisefloor calibration for the length of time set
837 * in runTime (valid values 1 to 7)
838 *
839 * Returns: The NF value at the end of the given time (or 0 for failure)
840 */
841int16_t
842ar5211RunNoiseFloor(struct ath_hal *ah, uint8_t runTime, int16_t startingNF)
843{
844 int i, searchTime;
845
846 HALASSERT(runTime <= 7);
847
848 /* Setup noise floor run time and starting value */
849 OS_REG_WRITE(ah, AR_PHY(25),
850 (OS_REG_READ(ah, AR_PHY(25)) & ~0xFFF) |
851 ((runTime << 9) & 0xE00) | (startingNF & 0x1FF));
852 /* Calibrate the noise floor */
855
856 /* Compute the required amount of searchTime needed to finish NF */
857 if (runTime == 0) {
858 /* 8 search windows * 6.4us each */
859 searchTime = 8 * 7;
860 } else {
861 /* 512 * runtime search windows * 6.4us each */
862 searchTime = (runTime * 512) * 7;
863 }
864
865 /*
866 * Do not read noise floor until it has been updated
867 *
868 * As a guesstimate - we may only get 1/60th the time on
869 * the air to see search windows in a heavily congested
870 * network (40 us every 2400 us of time)
871 */
872 for (i = 0; i < 60; i++) {
874 break;
875 OS_DELAY(searchTime);
876 }
877 if (i >= 60) {
879 "NF with runTime %d failed to end on channel %d\n",
880 runTime, AH_PRIVATE(ah)->ah_curchan->ic_freq);
882 " PHY NF Reg state: 0x%x\n",
885 " PHY Active Reg state: 0x%x\n",
887 return 0;
888 }
889
890 return ar5211GetNoiseFloor(ah);
891}
892
893static HAL_BOOL
894getNoiseFloorThresh(struct ath_hal *ah, const struct ieee80211_channel *chan,
895 int16_t *nft)
896{
897 HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
898
899 switch (chan->ic_flags & IEEE80211_CHAN_ALLFULL) {
900 case IEEE80211_CHAN_A:
901 *nft = ee->ee_noiseFloorThresh[0];
902 break;
903 case IEEE80211_CHAN_B:
904 *nft = ee->ee_noiseFloorThresh[1];
905 break;
906 case IEEE80211_CHAN_PUREG:
907 *nft = ee->ee_noiseFloorThresh[2];
908 break;
909 default:
910 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n",
911 __func__, chan->ic_flags);
912 return AH_FALSE;
913 }
914 return AH_TRUE;
915}
916
917/*
918 * Read the NF and check it against the noise floor threshold
919 *
920 * Returns: TRUE if the NF is good
921 */
922static HAL_BOOL
923ar5211IsNfGood(struct ath_hal *ah, struct ieee80211_channel *chan)
924{
926 int16_t nf, nfThresh;
927
928 if (!getNoiseFloorThresh(ah, chan, &nfThresh))
929 return AH_FALSE;
932 "%s: NF did not complete in calibration window\n", __func__);
933 }
934 nf = ar5211GetNoiseFloor(ah);
935 if (nf > nfThresh) {
937 "%s: noise floor failed; detected %u, threshold %u\n",
938 __func__, nf, nfThresh);
939 /*
940 * NB: Don't discriminate 2.4 vs 5Ghz, if this
941 * happens it indicates a problem regardless
942 * of the band.
943 */
944 chan->ic_state |= IEEE80211_CHANSTATE_CWINT;
945 }
946 ichan->rawNoiseFloor = nf;
947 return (nf <= nfThresh);
948}
949
950/*
951 * Peform the noisefloor calibration and check for any constant channel
952 * interference.
953 *
954 * NOTE: preAR5211 have a lengthy carrier wave detection process - hence
955 * it is if'ed for MKK regulatory domain only.
956 *
957 * Returns: TRUE for a successful noise floor calibration; else FALSE
958 */
960ar5211CalNoiseFloor(struct ath_hal *ah, const struct ieee80211_channel *chan)
961{
962#define N(a) (sizeof (a) / sizeof (a[0]))
963 /* Check for Carrier Wave interference in MKK regulatory zone */
964 if (AH_PRIVATE(ah)->ah_macVersion < AR_SREV_VERSION_OAHU &&
965 (chan->ic_flags & CHANNEL_NFCREQUIRED)) {
966 static const uint8_t runtime[3] = { 0, 2, 7 };
968 int16_t nf, nfThresh;
969 int i;
970
971 if (!getNoiseFloorThresh(ah, chan, &nfThresh))
972 return AH_FALSE;
973 /*
974 * Run a quick noise floor that will hopefully
975 * complete (decrease delay time).
976 */
977 for (i = 0; i < N(runtime); i++) {
978 nf = ar5211RunNoiseFloor(ah, runtime[i], 0);
979 if (nf > nfThresh) {
981 "%s: run failed with %u > threshold %u "
982 "(runtime %u)\n", __func__,
983 nf, nfThresh, runtime[i]);
984 ichan->rawNoiseFloor = 0;
985 } else
986 ichan->rawNoiseFloor = nf;
987 }
988 return (i <= N(runtime));
989 } else {
990 /* Calibrate the noise floor */
994 }
995 return AH_TRUE;
996#undef N
997}
998
999/*
1000 * Adjust NF based on statistical values for 5GHz frequencies.
1001 */
1002int16_t
1004{
1005 static const struct {
1006 uint16_t freqLow;
1007 int16_t adjust;
1008 } adjust5111[] = {
1009 { 5790, 11 }, /* NB: ordered high -> low */
1010 { 5730, 10 },
1011 { 5690, 9 },
1012 { 5660, 8 },
1013 { 5610, 7 },
1014 { 5530, 5 },
1015 { 5450, 4 },
1016 { 5379, 2 },
1017 { 5209, 0 }, /* XXX? bogus but doesn't matter */
1018 { 0, 1 },
1019 };
1020 int i;
1021
1022 for (i = 0; c->channel <= adjust5111[i].freqLow; i++)
1023 ;
1024 /* NB: placeholder for 5111's less severe requirement */
1025 return adjust5111[i].adjust / 3;
1026}
1027
1028/*
1029 * Reads EEPROM header info from device structure and programs
1030 * analog registers 6 and 7
1031 *
1032 * REQUIRES: Access to the analog device
1033 */
1034static HAL_BOOL
1035ar5211SetRf6and7(struct ath_hal *ah, const struct ieee80211_channel *chan)
1036{
1037#define N(a) (sizeof (a) / sizeof (a[0]))
1038 uint16_t freq = ath_hal_gethwchannel(ah, chan);
1039 HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
1040 struct ath_hal_5211 *ahp = AH5211(ah);
1041 uint16_t rfXpdGain, rfPloSel, rfPwdXpd;
1042 uint16_t tempOB, tempDB;
1043 uint16_t freqIndex;
1044 int i;
1045
1046 freqIndex = IEEE80211_IS_CHAN_2GHZ(chan) ? 2 : 1;
1047
1048 /*
1049 * TODO: This array mode correspondes with the index used
1050 * during the read.
1051 * For readability, this should be changed to an enum or #define
1052 */
1053 switch (chan->ic_flags & IEEE80211_CHAN_ALLFULL) {
1054 case IEEE80211_CHAN_A:
1055 if (freq > 4000 && freq < 5260) {
1056 tempOB = ee->ee_ob1;
1057 tempDB = ee->ee_db1;
1058 } else if (freq >= 5260 && freq < 5500) {
1059 tempOB = ee->ee_ob2;
1060 tempDB = ee->ee_db2;
1061 } else if (freq >= 5500 && freq < 5725) {
1062 tempOB = ee->ee_ob3;
1063 tempDB = ee->ee_db3;
1064 } else if (freq >= 5725) {
1065 tempOB = ee->ee_ob4;
1066 tempDB = ee->ee_db4;
1067 } else {
1068 /* XXX panic?? */
1069 tempOB = tempDB = 0;
1070 }
1071
1072 rfXpdGain = ee->ee_xgain[0];
1073 rfPloSel = ee->ee_xpd[0];
1074 rfPwdXpd = !ee->ee_xpd[0];
1075
1076 ar5211Rf6n7[5][freqIndex] =
1077 (ar5211Rf6n7[5][freqIndex] & ~0x10000000) |
1078 (ee->ee_cornerCal.pd84<< 28);
1079 ar5211Rf6n7[6][freqIndex] =
1080 (ar5211Rf6n7[6][freqIndex] & ~0x04000000) |
1081 (ee->ee_cornerCal.pd90 << 26);
1082 ar5211Rf6n7[21][freqIndex] =
1083 (ar5211Rf6n7[21][freqIndex] & ~0x08) |
1084 (ee->ee_cornerCal.gSel << 3);
1085 break;
1086 case IEEE80211_CHAN_B:
1087 tempOB = ee->ee_obFor24;
1088 tempDB = ee->ee_dbFor24;
1089 rfXpdGain = ee->ee_xgain[1];
1090 rfPloSel = ee->ee_xpd[1];
1091 rfPwdXpd = !ee->ee_xpd[1];
1092 break;
1093 case IEEE80211_CHAN_PUREG:
1094 tempOB = ee->ee_obFor24g;
1095 tempDB = ee->ee_dbFor24g;
1096 rfXpdGain = ee->ee_xgain[2];
1097 rfPloSel = ee->ee_xpd[2];
1098 rfPwdXpd = !ee->ee_xpd[2];
1099 break;
1100 default:
1101 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n",
1102 __func__, chan->ic_flags);
1103 return AH_FALSE;
1104 }
1105
1106 HALASSERT(1 <= tempOB && tempOB <= 5);
1107 HALASSERT(1 <= tempDB && tempDB <= 5);
1108
1109 /* Set rfXpdGain and rfPwdXpd */
1110 ar5211Rf6n7[11][freqIndex] = (ar5211Rf6n7[11][freqIndex] & ~0xC0) |
1111 (((ath_hal_reverseBits(rfXpdGain, 4) << 7) | (rfPwdXpd << 6)) & 0xC0);
1112 ar5211Rf6n7[12][freqIndex] = (ar5211Rf6n7[12][freqIndex] & ~0x07) |
1113 ((ath_hal_reverseBits(rfXpdGain, 4) >> 1) & 0x07);
1114
1115 /* Set OB */
1116 ar5211Rf6n7[12][freqIndex] = (ar5211Rf6n7[12][freqIndex] & ~0x80) |
1117 ((ath_hal_reverseBits(tempOB, 3) << 7) & 0x80);
1118 ar5211Rf6n7[13][freqIndex] = (ar5211Rf6n7[13][freqIndex] & ~0x03) |
1119 ((ath_hal_reverseBits(tempOB, 3) >> 1) & 0x03);
1120
1121 /* Set DB */
1122 ar5211Rf6n7[13][freqIndex] = (ar5211Rf6n7[13][freqIndex] & ~0x1C) |
1123 ((ath_hal_reverseBits(tempDB, 3) << 2) & 0x1C);
1124
1125 /* Set rfPloSel */
1126 ar5211Rf6n7[17][freqIndex] = (ar5211Rf6n7[17][freqIndex] & ~0x08) |
1127 ((rfPloSel << 3) & 0x08);
1128
1129 /* Write the Rf registers 6 & 7 */
1130 for (i = 0; i < N(ar5211Rf6n7); i++)
1131 OS_REG_WRITE(ah, ar5211Rf6n7[i][0], ar5211Rf6n7[i][freqIndex]);
1132
1133 /* Now that we have reprogrammed rfgain value, clear the flag. */
1135
1136 return AH_TRUE;
1137#undef N
1138}
1139
1142 const struct ieee80211_channel *chan)
1143{
1144#define ANT_SWITCH_TABLE1 0x9960
1145#define ANT_SWITCH_TABLE2 0x9964
1146 HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
1147 struct ath_hal_5211 *ahp = AH5211(ah);
1148 uint32_t antSwitchA, antSwitchB;
1149 int ix;
1150
1151 switch (chan->ic_flags & IEEE80211_CHAN_ALLFULL) {
1152 case IEEE80211_CHAN_A: ix = 0; break;
1153 case IEEE80211_CHAN_B: ix = 1; break;
1154 case IEEE80211_CHAN_PUREG: ix = 2; break;
1155 default:
1156 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n",
1157 __func__, chan->ic_flags);
1158 return AH_FALSE;
1159 }
1160
1161 antSwitchA = ee->ee_antennaControl[1][ix]
1162 | (ee->ee_antennaControl[2][ix] << 6)
1163 | (ee->ee_antennaControl[3][ix] << 12)
1164 | (ee->ee_antennaControl[4][ix] << 18)
1165 | (ee->ee_antennaControl[5][ix] << 24)
1166 ;
1167 antSwitchB = ee->ee_antennaControl[6][ix]
1168 | (ee->ee_antennaControl[7][ix] << 6)
1169 | (ee->ee_antennaControl[8][ix] << 12)
1170 | (ee->ee_antennaControl[9][ix] << 18)
1171 | (ee->ee_antennaControl[10][ix] << 24)
1172 ;
1173 /*
1174 * For fixed antenna, give the same setting for both switch banks
1175 */
1176 switch (settings) {
1177 case HAL_ANT_FIXED_A:
1178 antSwitchB = antSwitchA;
1179 break;
1180 case HAL_ANT_FIXED_B:
1181 antSwitchA = antSwitchB;
1182 break;
1183 case HAL_ANT_VARIABLE:
1184 break;
1185 default:
1186 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad antenna setting %u\n",
1187 __func__, settings);
1188 return AH_FALSE;
1189 }
1190 ahp->ah_diversityControl = settings;
1191
1192 OS_REG_WRITE(ah, ANT_SWITCH_TABLE1, antSwitchA);
1193 OS_REG_WRITE(ah, ANT_SWITCH_TABLE2, antSwitchB);
1194
1195 return AH_TRUE;
1196#undef ANT_SWITCH_TABLE1
1197#undef ANT_SWITCH_TABLE2
1198}
1199
1200/*
1201 * Reads EEPROM header info and programs the device for correct operation
1202 * given the channel value
1203 */
1204static HAL_BOOL
1205ar5211SetBoardValues(struct ath_hal *ah, const struct ieee80211_channel *chan)
1206{
1207 HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
1208 struct ath_hal_5211 *ahp = AH5211(ah);
1209 int arrayMode, falseDectectBackoff;
1210
1211 switch (chan->ic_flags & IEEE80211_CHAN_ALLFULL) {
1212 case IEEE80211_CHAN_A:
1213 arrayMode = 0;
1216 break;
1217 case IEEE80211_CHAN_B:
1218 arrayMode = 1;
1219 break;
1220 case IEEE80211_CHAN_PUREG:
1221 arrayMode = 2;
1222 break;
1223 default:
1224 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n",
1225 __func__, chan->ic_flags);
1226 return AH_FALSE;
1227 }
1228
1229 /* Set the antenna register(s) correctly for the chip revision */
1230 if (AH_PRIVATE(ah)->ah_macVersion < AR_SREV_VERSION_OAHU) {
1231 OS_REG_WRITE(ah, AR_PHY(68),
1232 (OS_REG_READ(ah, AR_PHY(68)) & 0xFFFFFFFC) | 0x3);
1233 } else {
1234 OS_REG_WRITE(ah, AR_PHY(68),
1235 (OS_REG_READ(ah, AR_PHY(68)) & 0xFFFFFC06) |
1236 (ee->ee_antennaControl[0][arrayMode] << 4) | 0x1);
1237
1239 ahp->ah_diversityControl, chan);
1240
1241 /* Set the Noise Floor Thresh on ar5211 devices */
1242 OS_REG_WRITE(ah, AR_PHY_BASE + (90 << 2),
1243 (ee->ee_noiseFloorThresh[arrayMode] & 0x1FF) | (1<<9));
1244 }
1245 OS_REG_WRITE(ah, AR_PHY_BASE + (17 << 2),
1246 (OS_REG_READ(ah, AR_PHY_BASE + (17 << 2)) & 0xFFFFC07F) |
1247 ((ee->ee_switchSettling[arrayMode] << 7) & 0x3F80));
1248 OS_REG_WRITE(ah, AR_PHY_BASE + (18 << 2),
1249 (OS_REG_READ(ah, AR_PHY_BASE + (18 << 2)) & 0xFFFC0FFF) |
1250 ((ee->ee_txrxAtten[arrayMode] << 12) & 0x3F000));
1251 OS_REG_WRITE(ah, AR_PHY_BASE + (20 << 2),
1252 (OS_REG_READ(ah, AR_PHY_BASE + (20 << 2)) & 0xFFFF0000) |
1253 ((ee->ee_pgaDesiredSize[arrayMode] << 8) & 0xFF00) |
1254 (ee->ee_adcDesiredSize[arrayMode] & 0x00FF));
1255 OS_REG_WRITE(ah, AR_PHY_BASE + (13 << 2),
1256 (ee->ee_txEndToXPAOff[arrayMode] << 24) |
1257 (ee->ee_txEndToXPAOff[arrayMode] << 16) |
1258 (ee->ee_txFrameToXPAOn[arrayMode] << 8) |
1259 ee->ee_txFrameToXPAOn[arrayMode]);
1260 OS_REG_WRITE(ah, AR_PHY_BASE + (10 << 2),
1261 (OS_REG_READ(ah, AR_PHY_BASE + (10 << 2)) & 0xFFFF00FF) |
1262 (ee->ee_txEndToXLNAOn[arrayMode] << 8));
1263 OS_REG_WRITE(ah, AR_PHY_BASE + (25 << 2),
1264 (OS_REG_READ(ah, AR_PHY_BASE + (25 << 2)) & 0xFFF80FFF) |
1265 ((ee->ee_thresh62[arrayMode] << 12) & 0x7F000));
1266
1267#define NO_FALSE_DETECT_BACKOFF 2
1268#define CB22_FALSE_DETECT_BACKOFF 6
1269 /*
1270 * False detect backoff - suspected 32 MHz spur causes
1271 * false detects in OFDM, causing Tx Hangs. Decrease
1272 * weak signal sensitivity for this card.
1273 */
1274 falseDectectBackoff = NO_FALSE_DETECT_BACKOFF;
1275 if (AH_PRIVATE(ah)->ah_eeversion < AR_EEPROM_VER3_3) {
1276 if (AH_PRIVATE(ah)->ah_subvendorid == 0x1022 &&
1277 IEEE80211_IS_CHAN_OFDM(chan))
1278 falseDectectBackoff += CB22_FALSE_DETECT_BACKOFF;
1279 } else {
1280 uint16_t freq = ath_hal_gethwchannel(ah, chan);
1281 uint32_t remainder = freq % 32;
1282
1283 if (remainder && (remainder < 10 || remainder > 22))
1284 falseDectectBackoff += ee->ee_falseDetectBackoff[arrayMode];
1285 }
1286 OS_REG_WRITE(ah, 0x9924,
1287 (OS_REG_READ(ah, 0x9924) & 0xFFFFFF01)
1288 | ((falseDectectBackoff << 1) & 0xF7));
1289
1290 return AH_TRUE;
1291#undef NO_FALSE_DETECT_BACKOFF
1292#undef CB22_FALSE_DETECT_BACKOFF
1293}
1294
1295/*
1296 * Set the limit on the overall output power. Used for dynamic
1297 * transmit power control and the like.
1298 *
1299 * NOTE: The power is passed in is in units of 0.5 dBm.
1300 */
1302ar5211SetTxPowerLimit(struct ath_hal *ah, uint32_t limit)
1303{
1304
1305 AH_PRIVATE(ah)->ah_powerLimit = AH_MIN(limit, MAX_RATE_POWER);
1307 return AH_TRUE;
1308}
1309
1310/*
1311 * Sets the transmit power in the baseband for the given
1312 * operating channel and mode.
1313 */
1314static HAL_BOOL
1315ar5211SetTransmitPower(struct ath_hal *ah, const struct ieee80211_channel *chan)
1316{
1317 uint16_t freq = ath_hal_gethwchannel(ah, chan);
1318 HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
1319 TRGT_POWER_INFO *pi;
1320 RD_EDGES_POWER *rep;
1321 PCDACS_EEPROM eepromPcdacs;
1322 u_int nchan, cfgCtl;
1323 int i;
1324
1325 /* setup the pcdac struct to point to the correct info, based on mode */
1326 switch (chan->ic_flags & IEEE80211_CHAN_ALLFULL) {
1327 case IEEE80211_CHAN_A:
1328 eepromPcdacs.numChannels = ee->ee_numChannels11a;
1329 eepromPcdacs.pChannelList= ee->ee_channels11a;
1330 eepromPcdacs.pDataPerChannel = ee->ee_dataPerChannel11a;
1331 nchan = ee->ee_numTargetPwr_11a;
1332 pi = ee->ee_trgtPwr_11a;
1333 break;
1334 case IEEE80211_CHAN_PUREG:
1335 eepromPcdacs.numChannels = ee->ee_numChannels2_4;
1336 eepromPcdacs.pChannelList= ee->ee_channels11g;
1337 eepromPcdacs.pDataPerChannel = ee->ee_dataPerChannel11g;
1338 nchan = ee->ee_numTargetPwr_11g;
1339 pi = ee->ee_trgtPwr_11g;
1340 break;
1341 case IEEE80211_CHAN_B:
1342 eepromPcdacs.numChannels = ee->ee_numChannels2_4;
1343 eepromPcdacs.pChannelList= ee->ee_channels11b;
1344 eepromPcdacs.pDataPerChannel = ee->ee_dataPerChannel11b;
1345 nchan = ee->ee_numTargetPwr_11b;
1346 pi = ee->ee_trgtPwr_11b;
1347 break;
1348 default:
1349 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n",
1350 __func__, chan->ic_flags);
1351 return AH_FALSE;
1352 }
1353
1354 ar5211SetPowerTable(ah, &eepromPcdacs, freq);
1355
1356 rep = AH_NULL;
1357 /* Match CTL to EEPROM value */
1358 cfgCtl = ath_hal_getctl(ah, chan);
1359 for (i = 0; i < ee->ee_numCtls; i++)
1360 if (ee->ee_ctl[i] != 0 && ee->ee_ctl[i] == cfgCtl) {
1361 rep = &ee->ee_rdEdgesPower[i * NUM_EDGES];
1362 break;
1363 }
1364 ar5211SetRateTable(ah, rep, pi, nchan, chan);
1365
1366 return AH_TRUE;
1367}
1368
1369/*
1370 * Read the transmit power levels from the structures taken
1371 * from EEPROM. Interpolate read transmit power values for
1372 * this channel. Organize the transmit power values into a
1373 * table for writing into the hardware.
1374 */
1375void
1377 uint16_t channel)
1378{
1379 static FULL_PCDAC_STRUCT pcdacStruct;
1380 static uint16_t pcdacTable[PWR_TABLE_SIZE];
1381
1382 uint16_t i, j;
1383 uint16_t *pPcdacValues;
1384 int16_t *pScaledUpDbm;
1385 int16_t minScaledPwr;
1386 int16_t maxScaledPwr;
1387 int16_t pwr;
1388 uint16_t pcdacMin = 0;
1389 uint16_t pcdacMax = 63;
1390 uint16_t pcdacTableIndex;
1391 uint16_t scaledPcdac;
1392 uint32_t addr;
1393 uint32_t temp32;
1394
1395 OS_MEMZERO(&pcdacStruct, sizeof(FULL_PCDAC_STRUCT));
1396 OS_MEMZERO(pcdacTable, sizeof(uint16_t) * PWR_TABLE_SIZE);
1397 pPcdacValues = pcdacStruct.PcdacValues;
1398 pScaledUpDbm = pcdacStruct.PwrValues;
1399
1400 /* Initialize the pcdacs to dBM structs pcdacs to be 1 to 63 */
1401 for (i = PCDAC_START, j = 0; i <= PCDAC_STOP; i+= PCDAC_STEP, j++)
1402 pPcdacValues[j] = i;
1403
1404 pcdacStruct.numPcdacValues = j;
1405 pcdacStruct.pcdacMin = PCDAC_START;
1406 pcdacStruct.pcdacMax = PCDAC_STOP;
1407
1408 /* Fill out the power values for this channel */
1409 for (j = 0; j < pcdacStruct.numPcdacValues; j++ )
1410 pScaledUpDbm[j] = ar5211GetScaledPower(channel, pPcdacValues[j], pSrcStruct);
1411
1412 /* Now scale the pcdac values to fit in the 64 entry power table */
1413 minScaledPwr = pScaledUpDbm[0];
1414 maxScaledPwr = pScaledUpDbm[pcdacStruct.numPcdacValues - 1];
1415
1416 /* find minimum and make monotonic */
1417 for (j = 0; j < pcdacStruct.numPcdacValues; j++) {
1418 if (minScaledPwr >= pScaledUpDbm[j]) {
1419 minScaledPwr = pScaledUpDbm[j];
1420 pcdacMin = j;
1421 }
1422 /*
1423 * Make the full_hsh monotonically increasing otherwise
1424 * interpolation algorithm will get fooled gotta start
1425 * working from the top, hence i = 63 - j.
1426 */
1427 i = (uint16_t)(pcdacStruct.numPcdacValues - 1 - j);
1428 if (i == 0)
1429 break;
1430 if (pScaledUpDbm[i-1] > pScaledUpDbm[i]) {
1431 /*
1432 * It could be a glitch, so make the power for
1433 * this pcdac the same as the power from the
1434 * next highest pcdac.
1435 */
1436 pScaledUpDbm[i - 1] = pScaledUpDbm[i];
1437 }
1438 }
1439
1440 for (j = 0; j < pcdacStruct.numPcdacValues; j++)
1441 if (maxScaledPwr < pScaledUpDbm[j]) {
1442 maxScaledPwr = pScaledUpDbm[j];
1443 pcdacMax = j;
1444 }
1445
1446 /* Find the first power level with a pcdac */
1447 pwr = (uint16_t)(PWR_STEP * ((minScaledPwr - PWR_MIN + PWR_STEP / 2) / PWR_STEP) + PWR_MIN);
1448
1449 /* Write all the first pcdac entries based off the pcdacMin */
1450 pcdacTableIndex = 0;
1451 for (i = 0; i < (2 * (pwr - PWR_MIN) / EEP_SCALE + 1); i++)
1452 pcdacTable[pcdacTableIndex++] = pcdacMin;
1453
1454 i = 0;
1455 while (pwr < pScaledUpDbm[pcdacStruct.numPcdacValues - 1]) {
1456 pwr += PWR_STEP;
1457 /* stop if dbM > max_power_possible */
1458 while (pwr < pScaledUpDbm[pcdacStruct.numPcdacValues - 1] &&
1459 (pwr - pScaledUpDbm[i])*(pwr - pScaledUpDbm[i+1]) > 0)
1460 i++;
1461 /* scale by 2 and add 1 to enable round up or down as needed */
1462 scaledPcdac = (uint16_t)(ar5211GetInterpolatedValue(pwr,
1463 pScaledUpDbm[i], pScaledUpDbm[i+1],
1464 (uint16_t)(pPcdacValues[i] * 2),
1465 (uint16_t)(pPcdacValues[i+1] * 2), 0) + 1);
1466
1467 pcdacTable[pcdacTableIndex] = scaledPcdac / 2;
1468 if (pcdacTable[pcdacTableIndex] > pcdacMax)
1469 pcdacTable[pcdacTableIndex] = pcdacMax;
1470 pcdacTableIndex++;
1471 }
1472
1473 /* Write all the last pcdac entries based off the last valid pcdac */
1474 while (pcdacTableIndex < PWR_TABLE_SIZE) {
1475 pcdacTable[pcdacTableIndex] = pcdacTable[pcdacTableIndex - 1];
1476 pcdacTableIndex++;
1477 }
1478
1479 /* Finally, write the power values into the baseband power table */
1480 addr = AR_PHY_BASE + (608 << 2);
1481 for (i = 0; i < 32; i++) {
1482 temp32 = 0xffff & ((pcdacTable[2 * i + 1] << 8) | 0xff);
1483 temp32 = (temp32 << 16) | (0xffff & ((pcdacTable[2 * i] << 8) | 0xff));
1484 OS_REG_WRITE(ah, addr, temp32);
1485 addr += 4;
1486 }
1487
1488}
1489
1490/*
1491 * Set the transmit power in the baseband for the given
1492 * operating channel and mode.
1493 */
1494static void
1495ar5211SetRateTable(struct ath_hal *ah, RD_EDGES_POWER *pRdEdgesPower,
1496 TRGT_POWER_INFO *pPowerInfo, uint16_t numChannels,
1497 const struct ieee80211_channel *chan)
1498{
1499 uint16_t freq = ath_hal_gethwchannel(ah, chan);
1500 HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
1501 struct ath_hal_5211 *ahp = AH5211(ah);
1502 static uint16_t ratesArray[NUM_RATES];
1503 static const uint16_t tpcScaleReductionTable[5] =
1504 { 0, 3, 6, 9, MAX_RATE_POWER };
1505
1506 uint16_t *pRatesPower;
1507 uint16_t lowerChannel, lowerIndex=0, lowerPower=0;
1508 uint16_t upperChannel, upperIndex=0, upperPower=0;
1509 uint16_t twiceMaxEdgePower=63;
1510 uint16_t twicePower = 0;
1511 uint16_t i, numEdges;
1512 uint16_t tempChannelList[NUM_EDGES]; /* temp array for holding edge channels */
1513 uint16_t twiceMaxRDPower;
1514 int16_t scaledPower = 0; /* for gcc -O2 */
1515 uint16_t mask = 0x3f;
1516 HAL_BOOL paPreDEnable = 0;
1517 int8_t twiceAntennaGain, twiceAntennaReduction = 0;
1518
1519 pRatesPower = ratesArray;
1520 twiceMaxRDPower = chan->ic_maxregpower * 2;
1521
1522 if (IEEE80211_IS_CHAN_5GHZ(chan)) {
1523 twiceAntennaGain = ee->ee_antennaGainMax[0];
1524 } else {
1525 twiceAntennaGain = ee->ee_antennaGainMax[1];
1526 }
1527
1528 twiceAntennaReduction = ath_hal_getantennareduction(ah, chan, twiceAntennaGain);
1529
1530 if (pRdEdgesPower) {
1531 /* Get the edge power */
1532 for (i = 0; i < NUM_EDGES; i++) {
1533 if (pRdEdgesPower[i].rdEdge == 0)
1534 break;
1535 tempChannelList[i] = pRdEdgesPower[i].rdEdge;
1536 }
1537 numEdges = i;
1538
1539 ar5211GetLowerUpperValues(freq, tempChannelList,
1540 numEdges, &lowerChannel, &upperChannel);
1541 /* Get the index for this channel */
1542 for (i = 0; i < numEdges; i++)
1543 if (lowerChannel == tempChannelList[i])
1544 break;
1545 HALASSERT(i != numEdges);
1546
1547 if ((lowerChannel == upperChannel &&
1548 lowerChannel == freq) ||
1549 pRdEdgesPower[i].flag) {
1550 twiceMaxEdgePower = pRdEdgesPower[i].twice_rdEdgePower;
1551 HALASSERT(twiceMaxEdgePower > 0);
1552 }
1553 }
1554
1555 /* extrapolate the power values for the test Groups */
1556 for (i = 0; i < numChannels; i++)
1557 tempChannelList[i] = pPowerInfo[i].testChannel;
1558
1559 ar5211GetLowerUpperValues(freq, tempChannelList,
1560 numChannels, &lowerChannel, &upperChannel);
1561
1562 /* get the index for the channel */
1563 for (i = 0; i < numChannels; i++) {
1564 if (lowerChannel == tempChannelList[i])
1565 lowerIndex = i;
1566 if (upperChannel == tempChannelList[i]) {
1567 upperIndex = i;
1568 break;
1569 }
1570 }
1571
1572 for (i = 0; i < NUM_RATES; i++) {
1573 if (IEEE80211_IS_CHAN_OFDM(chan)) {
1574 /* power for rates 6,9,12,18,24 is all the same */
1575 if (i < 5) {
1576 lowerPower = pPowerInfo[lowerIndex].twicePwr6_24;
1577 upperPower = pPowerInfo[upperIndex].twicePwr6_24;
1578 } else if (i == 5) {
1579 lowerPower = pPowerInfo[lowerIndex].twicePwr36;
1580 upperPower = pPowerInfo[upperIndex].twicePwr36;
1581 } else if (i == 6) {
1582 lowerPower = pPowerInfo[lowerIndex].twicePwr48;
1583 upperPower = pPowerInfo[upperIndex].twicePwr48;
1584 } else if (i == 7) {
1585 lowerPower = pPowerInfo[lowerIndex].twicePwr54;
1586 upperPower = pPowerInfo[upperIndex].twicePwr54;
1587 }
1588 } else {
1589 switch (i) {
1590 case 0:
1591 case 1:
1592 lowerPower = pPowerInfo[lowerIndex].twicePwr6_24;
1593 upperPower = pPowerInfo[upperIndex].twicePwr6_24;
1594 break;
1595 case 2:
1596 case 3:
1597 lowerPower = pPowerInfo[lowerIndex].twicePwr36;
1598 upperPower = pPowerInfo[upperIndex].twicePwr36;
1599 break;
1600 case 4:
1601 case 5:
1602 lowerPower = pPowerInfo[lowerIndex].twicePwr48;
1603 upperPower = pPowerInfo[upperIndex].twicePwr48;
1604 break;
1605 case 6:
1606 case 7:
1607 lowerPower = pPowerInfo[lowerIndex].twicePwr54;
1608 upperPower = pPowerInfo[upperIndex].twicePwr54;
1609 break;
1610 }
1611 }
1612
1613 twicePower = ar5211GetInterpolatedValue(freq,
1614 lowerChannel, upperChannel, lowerPower, upperPower, 0);
1615
1616 /* Reduce power by band edge restrictions */
1617 twicePower = AH_MIN(twicePower, twiceMaxEdgePower);
1618
1619 /*
1620 * If turbo is set, reduce power to keep power
1621 * consumption under 2 Watts. Note that we always do
1622 * this unless specially configured. Then we limit
1623 * power only for non-AP operation.
1624 */
1625 if (IEEE80211_IS_CHAN_TURBO(chan) &&
1626 AH_PRIVATE(ah)->ah_eeversion >= AR_EEPROM_VER3_1
1627#ifdef AH_ENABLE_AP_SUPPORT
1628 && AH_PRIVATE(ah)->ah_opmode != HAL_M_HOSTAP
1629#endif
1630 ) {
1631 twicePower = AH_MIN(twicePower, ee->ee_turbo2WMaxPower5);
1632 }
1633
1634 /* Reduce power by max regulatory domain allowed restrictions */
1635 pRatesPower[i] = AH_MIN(twicePower, twiceMaxRDPower - twiceAntennaReduction);
1636
1637 /* Use 6 Mb power level for transmit power scaling reduction */
1638 /* We don't want to reduce higher rates if its not needed */
1639 if (i == 0) {
1640 scaledPower = pRatesPower[0] -
1641 (tpcScaleReductionTable[AH_PRIVATE(ah)->ah_tpScale] * 2);
1642 if (scaledPower < 1)
1643 scaledPower = 1;
1644 }
1645
1646 pRatesPower[i] = AH_MIN(pRatesPower[i], scaledPower);
1647 }
1648
1649 /* Record txPower at Rate 6 for info gathering */
1650 ahp->ah_tx6PowerInHalfDbm = pRatesPower[0];
1651
1652#ifdef AH_DEBUG
1654 "%s: final output power setting %d MHz:\n",
1655 __func__, chan->ic_freq);
1657 "6 Mb %d dBm, MaxRD: %d dBm, MaxEdge %d dBm\n",
1658 scaledPower / 2, twiceMaxRDPower / 2, twiceMaxEdgePower / 2);
1659 HALDEBUG(ah, HAL_DEBUG_RESET, "TPC Scale %d dBm - Ant Red %d dBm\n",
1660 tpcScaleReductionTable[AH_PRIVATE(ah)->ah_tpScale] * 2,
1661 twiceAntennaReduction / 2);
1662 if (IEEE80211_IS_CHAN_TURBO(chan) &&
1663 AH_PRIVATE(ah)->ah_eeversion >= AR_EEPROM_VER3_1)
1664 HALDEBUG(ah, HAL_DEBUG_RESET, "Max Turbo %d dBm\n",
1667 " %2d | %2d | %2d | %2d | %2d | %2d | %2d | %2d dBm\n",
1668 pRatesPower[0] / 2, pRatesPower[1] / 2, pRatesPower[2] / 2,
1669 pRatesPower[3] / 2, pRatesPower[4] / 2, pRatesPower[5] / 2,
1670 pRatesPower[6] / 2, pRatesPower[7] / 2);
1671#endif /* AH_DEBUG */
1672
1673 /* Write the power table into the hardware */
1675 ((paPreDEnable & 1)<< 30) | ((pRatesPower[3] & mask) << 24) |
1676 ((paPreDEnable & 1)<< 22) | ((pRatesPower[2] & mask) << 16) |
1677 ((paPreDEnable & 1)<< 14) | ((pRatesPower[1] & mask) << 8) |
1678 ((paPreDEnable & 1)<< 6 ) | (pRatesPower[0] & mask));
1680 ((paPreDEnable & 1)<< 30) | ((pRatesPower[7] & mask) << 24) |
1681 ((paPreDEnable & 1)<< 22) | ((pRatesPower[6] & mask) << 16) |
1682 ((paPreDEnable & 1)<< 14) | ((pRatesPower[5] & mask) << 8) |
1683 ((paPreDEnable & 1)<< 6 ) | (pRatesPower[4] & mask));
1684
1685 /* set max power to the power value at rate 6 */
1686 ar5211SetTxPowerLimit(ah, pRatesPower[0]);
1687
1688 AH_PRIVATE(ah)->ah_maxPowerLevel = pRatesPower[0];
1689}
1690
1691/*
1692 * Get or interpolate the pcdac value from the calibrated data
1693 */
1694uint16_t
1695ar5211GetScaledPower(uint16_t channel, uint16_t pcdacValue,
1696 const PCDACS_EEPROM *pSrcStruct)
1697{
1698 uint16_t powerValue;
1699 uint16_t lFreq, rFreq; /* left and right frequency values */
1700 uint16_t llPcdac, ulPcdac; /* lower and upper left pcdac values */
1701 uint16_t lrPcdac, urPcdac; /* lower and upper right pcdac values */
1702 uint16_t lPwr, uPwr; /* lower and upper temp pwr values */
1703 uint16_t lScaledPwr, rScaledPwr; /* left and right scaled power */
1704
1705 if (ar5211FindValueInList(channel, pcdacValue, pSrcStruct, &powerValue))
1706 /* value was copied from srcStruct */
1707 return powerValue;
1708
1709 ar5211GetLowerUpperValues(channel, pSrcStruct->pChannelList,
1710 pSrcStruct->numChannels, &lFreq, &rFreq);
1711 ar5211GetLowerUpperPcdacs(pcdacValue, lFreq, pSrcStruct,
1712 &llPcdac, &ulPcdac);
1713 ar5211GetLowerUpperPcdacs(pcdacValue, rFreq, pSrcStruct,
1714 &lrPcdac, &urPcdac);
1715
1716 /* get the power index for the pcdac value */
1717 ar5211FindValueInList(lFreq, llPcdac, pSrcStruct, &lPwr);
1718 ar5211FindValueInList(lFreq, ulPcdac, pSrcStruct, &uPwr);
1719 lScaledPwr = ar5211GetInterpolatedValue(pcdacValue,
1720 llPcdac, ulPcdac, lPwr, uPwr, 0);
1721
1722 ar5211FindValueInList(rFreq, lrPcdac, pSrcStruct, &lPwr);
1723 ar5211FindValueInList(rFreq, urPcdac, pSrcStruct, &uPwr);
1724 rScaledPwr = ar5211GetInterpolatedValue(pcdacValue,
1725 lrPcdac, urPcdac, lPwr, uPwr, 0);
1726
1727 return ar5211GetInterpolatedValue(channel, lFreq, rFreq,
1728 lScaledPwr, rScaledPwr, 0);
1729}
1730
1731/*
1732 * Find the value from the calibrated source data struct
1733 */
1735ar5211FindValueInList(uint16_t channel, uint16_t pcdacValue,
1736 const PCDACS_EEPROM *pSrcStruct, uint16_t *powerValue)
1737{
1738 const DATA_PER_CHANNEL *pChannelData;
1739 const uint16_t *pPcdac;
1740 uint16_t i, j;
1741
1742 pChannelData = pSrcStruct->pDataPerChannel;
1743 for (i = 0; i < pSrcStruct->numChannels; i++ ) {
1744 if (pChannelData->channelValue == channel) {
1745 pPcdac = pChannelData->PcdacValues;
1746 for (j = 0; j < pChannelData->numPcdacValues; j++ ) {
1747 if (*pPcdac == pcdacValue) {
1748 *powerValue = pChannelData->PwrValues[j];
1749 return AH_TRUE;
1750 }
1751 pPcdac++;
1752 }
1753 }
1754 pChannelData++;
1755 }
1756 return AH_FALSE;
1757}
1758
1759/*
1760 * Returns interpolated or the scaled up interpolated value
1761 */
1762uint16_t
1764 uint16_t srcLeft, uint16_t srcRight,
1765 uint16_t targetLeft, uint16_t targetRight,
1766 HAL_BOOL scaleUp)
1767{
1768 uint16_t rv;
1769 int16_t lRatio;
1770 uint16_t scaleValue = EEP_SCALE;
1771
1772 /* to get an accurate ratio, always scale, if want to scale, then don't scale back down */
1773 if ((targetLeft * targetRight) == 0)
1774 return 0;
1775 if (scaleUp)
1776 scaleValue = 1;
1777
1778 if (srcRight != srcLeft) {
1779 /*
1780 * Note the ratio always need to be scaled,
1781 * since it will be a fraction.
1782 */
1783 lRatio = (target - srcLeft) * EEP_SCALE / (srcRight - srcLeft);
1784 if (lRatio < 0) {
1785 /* Return as Left target if value would be negative */
1786 rv = targetLeft * (scaleUp ? EEP_SCALE : 1);
1787 } else if (lRatio > EEP_SCALE) {
1788 /* Return as Right target if Ratio is greater than 100% (SCALE) */
1789 rv = targetRight * (scaleUp ? EEP_SCALE : 1);
1790 } else {
1791 rv = (lRatio * targetRight + (EEP_SCALE - lRatio) *
1792 targetLeft) / scaleValue;
1793 }
1794 } else {
1795 rv = targetLeft;
1796 if (scaleUp)
1797 rv *= EEP_SCALE;
1798 }
1799 return rv;
1800}
1801
1802/*
1803 * Look for value being within 0.1 of the search values
1804 * however, NDIS can't do float calculations, so multiply everything
1805 * up by EEP_SCALE so can do integer arithmatic
1806 *
1807 * INPUT value -value to search for
1808 * INPUT pList -ptr to the list to search
1809 * INPUT listSize -number of entries in list
1810 * OUTPUT pLowerValue -return the lower value
1811 * OUTPUT pUpperValue -return the upper value
1812 */
1813void
1815 const uint16_t *pList, uint16_t listSize,
1816 uint16_t *pLowerValue, uint16_t *pUpperValue)
1817{
1818 const uint16_t listEndValue = *(pList + listSize - 1);
1819 uint32_t target = value * EEP_SCALE;
1820 int i;
1821
1822 /*
1823 * See if value is lower than the first value in the list
1824 * if so return first value
1825 */
1826 if (target < (uint32_t)(*pList * EEP_SCALE - EEP_DELTA)) {
1827 *pLowerValue = *pList;
1828 *pUpperValue = *pList;
1829 return;
1830 }
1831
1832 /*
1833 * See if value is greater than last value in list
1834 * if so return last value
1835 */
1836 if (target > (uint32_t)(listEndValue * EEP_SCALE + EEP_DELTA)) {
1837 *pLowerValue = listEndValue;
1838 *pUpperValue = listEndValue;
1839 return;
1840 }
1841
1842 /* look for value being near or between 2 values in list */
1843 for (i = 0; i < listSize; i++) {
1844 /*
1845 * If value is close to the current value of the list
1846 * then target is not between values, it is one of the values
1847 */
1848 if (abs(pList[i] * EEP_SCALE - (int32_t) target) < EEP_DELTA) {
1849 *pLowerValue = pList[i];
1850 *pUpperValue = pList[i];
1851 return;
1852 }
1853
1854 /*
1855 * Look for value being between current value and next value
1856 * if so return these 2 values
1857 */
1858 if (target < (uint32_t)(pList[i + 1] * EEP_SCALE - EEP_DELTA)) {
1859 *pLowerValue = pList[i];
1860 *pUpperValue = pList[i + 1];
1861 return;
1862 }
1863 }
1864}
1865
1866/*
1867 * Get the upper and lower pcdac given the channel and the pcdac
1868 * used in the search
1869 */
1870void
1871ar5211GetLowerUpperPcdacs(uint16_t pcdac, uint16_t channel,
1872 const PCDACS_EEPROM *pSrcStruct,
1873 uint16_t *pLowerPcdac, uint16_t *pUpperPcdac)
1874{
1875 const DATA_PER_CHANNEL *pChannelData;
1876 int i;
1877
1878 /* Find the channel information */
1879 pChannelData = pSrcStruct->pDataPerChannel;
1880 for (i = 0; i < pSrcStruct->numChannels; i++) {
1881 if (pChannelData->channelValue == channel)
1882 break;
1883 pChannelData++;
1884 }
1885 ar5211GetLowerUpperValues(pcdac, pChannelData->PcdacValues,
1886 pChannelData->numPcdacValues, pLowerPcdac, pUpperPcdac);
1887}
1888
1889#define DYN_ADJ_UP_MARGIN 15
1890#define DYN_ADJ_LO_MARGIN 20
1891
1893 9, /* numStepsInLadder */
1894 4, /* defaultStepNum */
1895 { { {4, 1, 1, 1}, 6, "FG8"},
1896 { {4, 0, 1, 1}, 4, "FG7"},
1897 { {3, 1, 1, 1}, 3, "FG6"},
1898 { {4, 0, 0, 1}, 1, "FG5"},
1899 { {4, 1, 1, 0}, 0, "FG4"}, /* noJack */
1900 { {4, 0, 1, 0}, -2, "FG3"}, /* halfJack */
1901 { {3, 1, 1, 0}, -3, "FG2"}, /* clip3 */
1902 { {4, 0, 0, 0}, -4, "FG1"}, /* noJack */
1903 { {2, 1, 1, 0}, -6, "FG0"} /* clip2 */
1904 }
1905};
1906
1907/*
1908 * Initialize the gain structure to good values
1909 */
1910void
1912{
1913 struct ath_hal_5211 *ahp = AH5211(ah);
1914 GAIN_VALUES *gv = &ahp->ah_gainValues;
1915
1916 /* initialize gain optimization values */
1919 gv->active = AH_TRUE;
1920 gv->loTrig = 20;
1921 gv->hiTrig = 35;
1922}
1923
1924static HAL_BOOL
1926{
1927 const struct ieee80211_channel *chan = AH_PRIVATE(ah)->ah_curchan;
1928 uint32_t gStep, g;
1929 uint32_t L1, L2, L3, L4;
1930
1931 if (IEEE80211_IS_CHAN_CCK(chan)) {
1932 gStep = 0x18;
1933 L1 = 0;
1934 L2 = gStep + 4;
1935 L3 = 0x40;
1936 L4 = L3 + 50;
1937
1938 gv->loTrig = L1;
1939 gv->hiTrig = L4+5;
1940 } else {
1941 gStep = 0x3f;
1942 L1 = 0;
1943 L2 = 50;
1944 L3 = L1;
1945 L4 = L3 + 50;
1946
1947 gv->loTrig = L1 + DYN_ADJ_LO_MARGIN;
1948 gv->hiTrig = L4 - DYN_ADJ_UP_MARGIN;
1949 }
1950 g = gv->currGain;
1951
1952 return !((g >= L1 && g<= L2) || (g >= L3 && g <= L4));
1953}
1954
1955/*
1956 * Enable the probe gain check on the next packet
1957 */
1958static void
1960{
1961 struct ath_hal_5211 *ahp = AH5211(ah);
1962
1963 /* Enable the gain readback probe */
1967
1969}
1970
1971/*
1972 * Exported call to check for a recent gain reading and return
1973 * the current state of the thermal calibration gain engine.
1974 */
1977{
1978 struct ath_hal_5211 *ahp = AH5211(ah);
1979 GAIN_VALUES *gv = &ahp->ah_gainValues;
1980 uint32_t rddata;
1981
1982 if (!gv->active)
1983 return HAL_RFGAIN_INACTIVE;
1984
1986 /* Caller had asked to setup a new reading. Check it. */
1987 rddata = OS_REG_READ(ah, AR_PHY_PAPD_PROBE);
1988
1989 if ((rddata & AR_PHY_PAPD_PROBE_NEXT_TX) == 0) {
1990 /* bit got cleared, we have a new reading. */
1991 gv->currGain = rddata >> AR_PHY_PAPD_PROBE_GAINF_S;
1992 /* inactive by default */
1994
1995 if (!ar5211InvalidGainReadback(ah, gv) &&
1996 ar5211IsGainAdjustNeeded(ah, gv) &&
1997 ar5211AdjustGain(ah, gv) > 0) {
1998 /*
1999 * Change needed. Copy ladder info
2000 * into eeprom info.
2001 */
2002 ar5211SetRfgain(ah, gv);
2004 }
2005 }
2006 }
2007 return ahp->ah_rfgainState;
2008}
2009
2010/*
2011 * Check to see if our readback gain level sits within the linear
2012 * region of our current variable attenuation window
2013 */
2014static HAL_BOOL
2016{
2017 return (gv->currGain <= gv->loTrig || gv->currGain >= gv->hiTrig);
2018}
2019
2020/*
2021 * Move the rabbit ears in the correct direction.
2022 */
2023static int32_t
2025{
2026 /* return > 0 for valid adjustments. */
2027 if (!gv->active)
2028 return -1;
2029
2031 if (gv->currGain >= gv->hiTrig) {
2032 if (gv->currStepNum == 0) {
2034 "%s: Max gain limit.\n", __func__);
2035 return -1;
2036 }
2038 "%s: Adding gain: currG=%d [%s] --> ",
2039 __func__, gv->currGain, gv->currStep->stepName);
2040 gv->targetGain = gv->currGain;
2041 while (gv->targetGain >= gv->hiTrig && gv->currStepNum > 0) {
2042 gv->targetGain -= 2 * (gainLadder.optStep[--(gv->currStepNum)].stepGain -
2043 gv->currStep->stepGain);
2045 }
2046 HALDEBUG(ah, HAL_DEBUG_RFPARAM, "targG=%d [%s]\n",
2047 gv->targetGain, gv->currStep->stepName);
2048 return 1;
2049 }
2050 if (gv->currGain <= gv->loTrig) {
2053 "%s: Min gain limit.\n", __func__);
2054 return -2;
2055 }
2057 "%s: Deducting gain: currG=%d [%s] --> ",
2058 __func__, gv->currGain, gv->currStep->stepName);
2059 gv->targetGain = gv->currGain;
2060 while (gv->targetGain <= gv->loTrig &&
2062 gv->targetGain -= 2 *
2063 (gainLadder.optStep[++(gv->currStepNum)].stepGain - gv->currStep->stepGain);
2065 }
2066 HALDEBUG(ah, HAL_DEBUG_RFPARAM, "targG=%d [%s]\n",
2067 gv->targetGain, gv->currStep->stepName);
2068 return 2;
2069 }
2070 return 0; /* caller didn't call needAdjGain first */
2071}
2072
2073/*
2074 * Adjust the 5GHz EEPROM information with the desired calibration values.
2075 */
2076static void
2078{
2079 HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
2080
2081 if (!gv->active)
2082 return;
2083 ee->ee_cornerCal.clip = gv->currStep->paramVal[0]; /* bb_tx_clip */
2084 ee->ee_cornerCal.pd90 = gv->currStep->paramVal[1]; /* rf_pwd_90 */
2085 ee->ee_cornerCal.pd84 = gv->currStep->paramVal[2]; /* rf_pwd_84 */
2086 ee->ee_cornerCal.gSel = gv->currStep->paramVal[3]; /* rf_rfgainsel */
2087}
2088
2089static void
2090ar5211SetOperatingMode(struct ath_hal *ah, int opmode)
2091{
2092 struct ath_hal_5211 *ahp = AH5211(ah);
2093 uint32_t val;
2094
2095 val = OS_REG_READ(ah, AR_STA_ID1) & 0xffff;
2096 switch (opmode) {
2097 case HAL_M_HOSTAP:
2098 OS_REG_WRITE(ah, AR_STA_ID1, val
2101 | ahp->ah_staId1Defaults);
2102 break;
2103 case HAL_M_IBSS:
2104 OS_REG_WRITE(ah, AR_STA_ID1, val
2107 | ahp->ah_staId1Defaults);
2108 break;
2109 case HAL_M_STA:
2110 case HAL_M_MONITOR:
2111 OS_REG_WRITE(ah, AR_STA_ID1, val
2113 | ahp->ah_staId1Defaults);
2114 break;
2115 }
2116}
2117
2118void
2120{
2121 ar5211SetOperatingMode(ah, AH_PRIVATE(ah)->ah_opmode);
2122}
uint32_t ath_hal_reverseBits(uint32_t val, uint32_t n)
Definition: ah.c:333
HAL_BOOL ath_hal_wait(struct ath_hal *ah, u_int reg, uint32_t mask, uint32_t val)
Definition: ah.c:305
HAL_STATUS
Definition: ah.h:71
@ HAL_EIO
Definition: ah.h:75
@ HAL_EINVAL
Definition: ah.h:84
#define HAL_NUM_TX_QUEUES
Definition: ah.h:251
HAL_OPMODE
Definition: ah.h:764
@ HAL_M_IBSS
Definition: ah.h:766
@ HAL_M_MONITOR
Definition: ah.h:768
@ HAL_M_STA
Definition: ah.h:765
@ HAL_M_HOSTAP
Definition: ah.h:767
@ HAL_PM_AWAKE
Definition: ah.h:440
HAL_RESET_TYPE
Definition: ah.h:771
HAL_ANT_SETTING
Definition: ah.h:758
@ HAL_ANT_FIXED_B
Definition: ah.h:761
@ HAL_ANT_VARIABLE
Definition: ah.h:759
@ HAL_ANT_FIXED_A
Definition: ah.h:760
HAL_RFGAIN
Definition: ah.h:622
@ HAL_RFGAIN_INACTIVE
Definition: ah.h:623
@ HAL_RFGAIN_NEED_CHANGE
Definition: ah.h:625
@ HAL_RFGAIN_READ_REQUESTED
Definition: ah.h:624
HAL_BOOL
Definition: ah.h:93
@ AH_FALSE
Definition: ah.h:94
@ AH_TRUE
Definition: ah.h:95
@ HAL_DEBUG_NFCAL
Definition: ah_debug.h:32
@ HAL_DEBUG_RESET
Definition: ah_debug.h:31
@ HAL_DEBUG_ANY
Definition: ah_debug.h:62
@ HAL_DEBUG_PERCAL
Definition: ah_debug.h:33
@ HAL_DEBUG_RFPARAM
Definition: ah_debug.h:37
@ AH_MARK_RESET
Definition: ah_decode.h:48
#define AR5211_DEVID
Definition: ah_devid.h:42
#define AR5211_FPGA11B
Definition: ah_devid.h:44
#define AR_EEPROM_VER3_1
Definition: ah_eeprom.h:36
#define MAX_RATE_POWER
Definition: ah_eeprom.h:163
#define AR_EEPROM_VER3
Definition: ah_eeprom.h:35
#define AR_EEPROM_VER3_3
Definition: ah_eeprom.h:38
#define NUM_EDGES
#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 EEP_DELTA
Definition: ah_eeprom_v3.h:132
#define PCDAC_STEP
Definition: ah_eeprom_v3.h:158
#define LE_READ_4(p)
Definition: ah_internal.h:577
u_int ath_hal_getantennareduction(struct ath_hal *ah, const struct ieee80211_channel *chan, u_int twiceGain)
Definition: ah_regdomain.c:991
u_int ath_hal_getctl(struct ath_hal *, const struct ieee80211_channel *)
Definition: ah_regdomain.c:932
#define LE_READ_2(p)
Definition: ah_internal.h:574
#define SM(_v, _f)
Definition: ah_internal.h:587
#define MS(_v, _f)
Definition: ah_internal.h:588
static OS_INLINE HAL_CHANNEL_INTERNAL * ath_hal_checkchannel(struct ath_hal *ah, const struct ieee80211_channel *c)
Definition: ah_internal.h:711
#define AH_PRIVATE(_ah)
Definition: ah_internal.h:442
#define HAL_DIAG_11N_SERVICES
Definition: ah_internal.h:860
static __inline__ int isBigEndian(void)
Definition: ah_internal.h:563
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 OS_REG_RMW_FIELD(_a, _r, _f, _v)
Definition: ah_internal.h:591
#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
#define AH_MIN(a, b)
Definition: ah_internal.h:29
#define CHANNEL_NFCREQUIRED
Definition: ah_internal.h:213
#define abs(_a)
Definition: ah_osdep.h:76
#define OS_DELAY(_n)
Definition: ah_osdep.h:69
#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
#define INIT_CONFIG_STATUS
Definition: ar5210.h:44
#define AR_PHY_BASE
Definition: ar5210phy.h:29
#define AR_PHY(_n)
Definition: ar5210phy.h:30
#define AR_PHY_ACTIVE
Definition: ar5210phy.h:51
#define AR_STA_ID0
Definition: ar5210reg.h:70
#define AR_CFG_SWTD
Definition: ar5210reg.h:120
#define AR_BEACON
Definition: ar5210reg.h:79
#define AR_STA_ID1
Definition: ar5210reg.h:71
#define AR_ISR
Definition: ar5210reg.h:41
#define AR_TSF_U32
Definition: ar5210reg.h:97
#define AR_BSS_ID0
Definition: ar5210reg.h:72
#define AR_PCICFG
Definition: ar5210reg.h:59
#define AR_RXDP
Definition: ar5210reg.h:39
#define AR_GPIODO
Definition: ar5210reg.h:61
#define AR_IMR
Definition: ar5210reg.h:42
#define AR_CFG_SWRD
Definition: ar5210reg.h:122
#define AR_CFG
Definition: ar5210reg.h:40
#define AR_BEACON_EN
Definition: ar5210reg.h:352
#define AR_BEACON_RESET_TSF
Definition: ar5210reg.h:353
#define AR_GPIOCR
Definition: ar5210reg.h:60
#define AR_BSS_ID1
Definition: ar5210reg.h:73
#define AR_TSF_L32
Definition: ar5210reg.h:96
#define AR_STA_ID1_DESC_ANTENNA
Definition: ar5210reg.h:310
#define AR_STA_ID1_ADHOC
Definition: ar5210reg.h:305
#define AR_RSSI_THR
Definition: ar5210reg.h:76
#define AR_RC
Definition: ar5210reg.h:55
#define AR_DIAG_SW
Definition: ar5210reg.h:95
#define AR_USEC
Definition: ar5210reg.h:78
#define AR_STA_ID1_DEFAULT_ANTENNA
Definition: ar5210reg.h:311
HAL_BOOL ar5211ResetTxQueue(struct ath_hal *ah, u_int q)
Definition: ar5211_xmit.c:234
HAL_BOOL ar5211SetSifsTime(struct ath_hal *, u_int)
Definition: ar5211_misc.c:425
#define INIT_IQCAL_LOG_COUNT_MAX
Definition: ar5211.h:54
#define INIT_INTERRUPT_MASK
Definition: ar5211.h:44
HAL_BOOL ar5211SetAckTimeout(struct ath_hal *, u_int)
Definition: ar5211_misc.c:475
HAL_BOOL ar5211SetCTSTimeout(struct ath_hal *, u_int)
Definition: ar5211_misc.c:522
@ RFGAIN_INACTIVE
Definition: ar5211.h:96
void ar5211EnableRfKill(struct ath_hal *)
Definition: ar5211_misc.c:170
#define AH5211(ah)
Definition: ar5211.h:144
HAL_BOOL ar5211SetSlotTime(struct ath_hal *, u_int)
Definition: ar5211_misc.c:450
HAL_BOOL ar5211SetPowerMode(struct ath_hal *, uint32_t powerRequest, int setChip)
static void ar5211GetLowerUpperValues(uint16_t value, const uint16_t *pList, uint16_t listSize, uint16_t *pLowerValue, uint16_t *pUpperValue)
void ar5211SetPCUConfig(struct ath_hal *ah)
static HAL_BOOL ar5211SetResetReg(struct ath_hal *ah, uint32_t resetMask)
Definition: ar5211_reset.c:753
#define DELAY_BASE_ACTIVATE
Definition: ar5211_reset.c:105
static HAL_BOOL ar5211FindValueInList(uint16_t channel, uint16_t pcdacValue, const PCDACS_EEPROM *pSrcStruct, uint16_t *powerValue)
#define DYN_ADJ_UP_MARGIN
int16_t ar5211GetNfAdjust(struct ath_hal *ah, const HAL_CHANNEL_INTERNAL *c)
static void ar5211RequestRfgain(struct ath_hal *)
static void ar5211SetRfgain(struct ath_hal *, const GAIN_VALUES *)
HAL_BOOL ar5211ResetCalValid(struct ath_hal *ah, const struct ieee80211_channel *chan)
Definition: ar5211_reset.c:743
HAL_BOOL ar5211SetTxPowerLimit(struct ath_hal *ah, uint32_t limit)
static int32_t ar5211AdjustGain(struct ath_hal *, GAIN_VALUES *)
void ar5211InitializeGainValues(struct ath_hal *ah)
HAL_BOOL ar5211PerCalibrationN(struct ath_hal *ah, struct ieee80211_channel *chan, u_int chainMask, HAL_BOOL longCal, HAL_BOOL *isCalDone)
Definition: ar5211_reset.c:643
static HAL_BOOL getNoiseFloorThresh(struct ath_hal *ah, const struct ieee80211_channel *chan, int16_t *nft)
Definition: ar5211_reset.c:894
#define CB22_FALSE_DETECT_BACKOFF
#define FAIL(_code)
#define DYN_ADJ_LO_MARGIN
HAL_BOOL ar5211Reset(struct ath_hal *ah, HAL_OPMODE opmode, struct ieee80211_channel *chan, HAL_BOOL bChannelChange, HAL_RESET_TYPE resetType, HAL_STATUS *status)
Definition: ar5211_reset.c:157
#define ANT_SWITCH_TABLE2
#define ANT_SWITCH_TABLE1
#define NUM_RATES
Definition: ar5211_reset.c:107
static void ar5211SetPowerTable(struct ath_hal *, PCDACS_EEPROM *pSrcStruct, uint16_t channel)
static HAL_BOOL ar5211InvalidGainReadback(struct ath_hal *, GAIN_VALUES *)
static void ar5211SetOperatingMode(struct ath_hal *, int opmode)
static HAL_BOOL ar5211SetBoardValues(struct ath_hal *, const struct ieee80211_channel *chan)
HAL_BOOL ar5211CalNoiseFloor(struct ath_hal *ah, const struct ieee80211_channel *chan)
Definition: ar5211_reset.c:960
HAL_BOOL ar5211ChipReset(struct ath_hal *ah, const struct ieee80211_channel *chan)
Definition: ar5211_reset.c:596
static void ar5211GetLowerUpperPcdacs(uint16_t pcdac, uint16_t channel, const PCDACS_EEPROM *pSrcStruct, uint16_t *pLowerPcdac, uint16_t *pUpperPcdac)
HAL_RFGAIN ar5211GetRfgain(struct ath_hal *ah)
HAL_BOOL ar5211SetAntennaSwitchInternal(struct ath_hal *ah, HAL_ANT_SETTING settings, const struct ieee80211_channel *chan)
static HAL_BOOL ar5211IsGainAdjustNeeded(struct ath_hal *, const GAIN_VALUES *)
static int16_t ar5211RunNoiseFloor(struct ath_hal *, uint8_t runTime, int16_t startingNF)
Definition: ar5211_reset.c:842
#define DELAY_PLL_SETTLE
Definition: ar5211_reset.c:104
HAL_BOOL ar5211PhyDisable(struct ath_hal *ah)
Definition: ar5211_reset.c:563
#define NO_FALSE_DETECT_BACKOFF
static const GAIN_OPTIMIZATION_LADDER gainLadder
static void ar5211SetRateTable(struct ath_hal *, RD_EDGES_POWER *pRdEdgesPower, TRGT_POWER_INFO *pPowerInfo, uint16_t numChannels, const struct ieee80211_channel *chan)
HAL_BOOL ar5211PerCalibration(struct ath_hal *ah, struct ieee80211_channel *chan, HAL_BOOL *isIQdone)
Definition: ar5211_reset.c:736
static HAL_BOOL ar5211SetChannel(struct ath_hal *, const struct ieee80211_channel *)
Definition: ar5211_reset.c:787
static int16_t ar5211GetNoiseFloor(struct ath_hal *ah)
Definition: ar5211_reset.c:825
static HAL_BOOL ar5211IsNfGood(struct ath_hal *, struct ieee80211_channel *chan)
Definition: ar5211_reset.c:923
static HAL_BOOL ar5211SetRf6and7(struct ath_hal *, const struct ieee80211_channel *chan)
static uint16_t ar5211GetScaledPower(uint16_t channel, uint16_t pcdacValue, const PCDACS_EEPROM *pSrcStruct)
static const CHAN_INFO_2GHZ chan2GHzData[]
Definition: ar5211_reset.c:51
static HAL_BOOL ar5211SetTransmitPower(struct ath_hal *, const struct ieee80211_channel *)
#define N(a)
HAL_BOOL ar5211Disable(struct ath_hal *ah)
Definition: ar5211_reset.c:572
#define CI_2GHZ_INDEX_CORRECTION
Definition: ar5211_reset.c:50
static uint16_t ar5211GetInterpolatedValue(uint16_t target, uint16_t srcLeft, uint16_t srcRight, uint16_t targetLeft, uint16_t targetRight, HAL_BOOL scaleUp)
#define AR_PHY_ACTIVE_EN
Definition: ar5211phy.h:39
#define AR_PHY_POWER_TX_RATE2
Definition: ar5211phy.h:72
#define AR_PHY_IQCAL_RES_IQ_CORR_MEAS
Definition: ar5211phy.h:86
#define AR_PHY_AGC_CONTROL_CAL
Definition: ar5211phy.h:43
#define AR_PHY_FRAME_CTL_TX_CLIP
Definition: ar5211phy.h:76
#define AR_PHY_TIMING_CTRL4_DO_IQCAL
Definition: ar5211phy.h:62
#define AR5211_PHY_MODE_CCK
Definition: ar5211phy.h:91
#define AR_PHY_RX_DELAY
Definition: ar5211phy.h:51
#define AR_PHY_AGC_CONTROL_NF
Definition: ar5211phy.h:44
#define AR_PHY_PLL_CTL
Definition: ar5211phy.h:46
#define AR_PHY_FRAME_CTL_ERR_SERV
Definition: ar5211phy.h:78
#define AR_PHY_FC_TURBO_SHORT
Definition: ar5211phy.h:34
#define AR_PHY_PLL_CTL_40
Definition: ar5211phy.h:48
#define AR_PHY_POWER_TX_RATE1
Definition: ar5211phy.h:71
#define AR5211_PHY_MODE_OFDM
Definition: ar5211phy.h:90
#define AR_PHY_FC_TURBO_MODE
Definition: ar5211phy.h:33
#define AR_PHY_TURBO
Definition: ar5211phy.h:32
#define AR5211_PHY_MODE_RF2GHZ
Definition: ar5211phy.h:93
#define AR_PHY_IQCAL_RES_PWR_MEAS_I
Definition: ar5211phy.h:84
#define AR_PHY_PAPD_PROBE_POWERTX
Definition: ar5211phy.h:65
#define AR_PHY_POWER_TX_RATE_MAX
Definition: ar5211phy.h:73
#define AR_PHY_PAPD_PROBE_GAINF_S
Definition: ar5211phy.h:69
#define AR_PHY_TIMING_CTRL4
Definition: ar5211phy.h:55
#define AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF_S
Definition: ar5211phy.h:58
#define AR_PHY_PAPD_PROBE
Definition: ar5211phy.h:64
#define AR_PHY_PAPD_PROBE_NEXT_TX
Definition: ar5211phy.h:67
#define AR5211_PHY_MODE
Definition: ar5211phy.h:89
#define AR_PHY_TIMING_CTRL4_IQCORR_ENABLE
Definition: ar5211phy.h:59
#define AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX_S
Definition: ar5211phy.h:61
#define AR_PHY_RX_DELAY_M
Definition: ar5211phy.h:52
#define AR_PHY_PLL_CTL_44
Definition: ar5211phy.h:47
#define AR5211_PHY_MODE_RF5GHZ
Definition: ar5211phy.h:92
#define AR_PHY_AGC_CONTROL
Definition: ar5211phy.h:42
#define AR_PHY_FRAME_CTL
Definition: ar5211phy.h:75
#define AR_PHY_IQCAL_RES_PWR_MEAS_Q
Definition: ar5211phy.h:85
#define AR5311_USEC_TX_LAT_M
Definition: ar5211reg.h:799
#define AR_IMR_MIB
Definition: ar5211reg.h:431
#define AR_CFG_CLK_GATE_DIS
Definition: ar5211reg.h:288
#define AR_RC_PCI
Definition: ar5211reg.h:614
#define AR_USEC_M
Definition: ar5211reg.h:789
#define AR5311_DIAG_SW_USE_ECO
Definition: ar5211reg.h:838
#define AR_QCU_0
Definition: ar5211reg.h:475
#define AR_NUM_DCU
Definition: ar5211reg.h:531
#define AR_STA_ID1_RTS_USE_DEF
Definition: ar5211reg.h:768
#define AR_PCICFG_LEDSLOW
Definition: ar5211reg.h:668
#define AR_IMR_S2
Definition: ar5211reg.h:60
#define AR_PCICFG_LEDMODE
Definition: ar5211reg.h:661
#define AR_IMR_S1
Definition: ar5211reg.h:59
#define AR_IMR_S0_QCU_TXDESC
Definition: ar5211reg.h:449
#define AR_STA_ID1_STA_AP
Definition: ar5211reg.h:761
#define AR_USEC_32_M
Definition: ar5211reg.h:790
#define AR_PCICFG_LEDCTL
Definition: ar5211reg.h:650
#define AR_IMR_S0_QCU_TXOK
Definition: ar5211reg.h:447
#define AR5311_USEC_RX_LAT_S
Definition: ar5211reg.h:802
#define AR_IMR_S0
Definition: ar5211reg.h:58
#define AR_PCICFG_LEDBLINK
Definition: ar5211reg.h:666
#define AR_SREV_VERSION_OAHU
Definition: ar5211reg.h:725
#define AR_DEF_ANTENNA
Definition: ar5211reg.h:262
#define AR_IMR_S2_DPERR
Definition: ar5211reg.h:461
#define AR_SREV_OAHU_PROD
Definition: ar5211reg.h:727
#define AR_IMR_S2_MCABT
Definition: ar5211reg.h:459
#define AR_DQCUMASK(i)
Definition: ar5211reg.h:148
#define AR_RC_BB
Definition: ar5211reg.h:611
#define AR_IMR_S1_QCU_TXERR
Definition: ar5211reg.h:452
#define AR_RC_MAC
Definition: ar5211reg.h:610
#define AR_IMR_S2_SSERR
Definition: ar5211reg.h:460
#define AR5311_QDCLKGATE
Definition: ar5211reg.h:50
#define AR_IMR_S0_QCU_TXDESC_S
Definition: ar5211reg.h:450
#define AR5311_USEC_RX_LAT_M
Definition: ar5211reg.h:801
#define AR_IMR_S2_QCU_TXURN
Definition: ar5211reg.h:457
#define AR_DSEQNUM(i)
Definition: ar5211reg.h:208
#define AR_STA_ID1_BASE_RATE_11B
Definition: ar5211reg.h:770
#define AR_D0_SEQNUM
Definition: ar5211reg.h:198
#define AR_D_GBL_IFS_EIFS
Definition: ar5211reg.h:213
uint32_t refClkSel
Definition: ar5211_reset.c:45
uint32_t channelSelect
Definition: ar5211_reset.c:46
uint16_t channel5111
Definition: ar5211_reset.c:47
uint32_t defaultStepNum
Definition: ar5211.h:81
GAIN_OPTIMIZATION_STEP optStep[10]
Definition: ar5211.h:82
uint32_t numStepsInLadder
Definition: ar5211.h:80
uint32_t active
Definition: ar5211.h:91
uint32_t targetGain
Definition: ar5211.h:88
uint32_t loTrig
Definition: ar5211.h:89
uint32_t hiTrig
Definition: ar5211.h:90
uint32_t currGain
Definition: ar5211.h:87
const GAIN_OPTIMIZATION_STEP * currStep
Definition: ar5211.h:92
uint32_t currStepNum
Definition: ar5211.h:86
uint16_t ee_channels11a[NUM_11A_EEPROM_CHANNELS]
Definition: ah_eeprom_v3.h:429
RD_EDGES_POWER ee_rdEdgesPower[NUM_EDGES *NUM_CTLS_MAX]
Definition: ah_eeprom_v3.h:446
uint16_t ee_ob2
Definition: ah_eeprom_v3.h:402
uint16_t ee_xgain[3]
Definition: ah_eeprom_v3.h:380
int8_t ee_pgaDesiredSize[3]
Definition: ah_eeprom_v3.h:377
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_antennaControl[11][3]
Definition: ah_eeprom_v3.h:382
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_txFrameToXPAOn[3]
Definition: ah_eeprom_v3.h:375
uint16_t ee_dbFor24
Definition: ah_eeprom_v3.h:411
int8_t ee_antennaGainMax[2]
Definition: ah_eeprom_v3.h:357
uint16_t ee_switchSettling[3]
Definition: ah_eeprom_v3.h:370
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
int16_t ee_noiseFloorThresh[3]
Definition: ah_eeprom_v3.h:378
uint16_t ee_db2GHz[2]
Definition: ah_eeprom_v3.h:415
uint16_t ee_ob4
Definition: ah_eeprom_v3.h:406
uint16_t ee_turbo2WMaxPower5
Definition: ah_eeprom_v3.h:349
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
uint16_t ee_txEndToXLNAOn[3]
Definition: ah_eeprom_v3.h:372
uint16_t ee_numCtls
Definition: ah_eeprom_v3.h:416
int8_t ee_adcDesiredSize[3]
Definition: ah_eeprom_v3.h:376
DATA_PER_CHANNEL ee_dataPerChannel11g[NUM_2_4_EEPROM_CHANNELS]
Definition: ah_eeprom_v3.h:439
uint16_t ee_txEndToXPAOff[3]
Definition: ah_eeprom_v3.h:374
uint16_t ee_falseDetectBackoff[3]
Definition: ah_eeprom_v3.h:383
uint16_t ee_thresh62[3]
Definition: ah_eeprom_v3.h:373
uint16_t ee_channels11g[NUM_2_4_EEPROM_CHANNELS]
Definition: ah_eeprom_v3.h:434
uint16_t ee_txrxAtten[3]
Definition: ah_eeprom_v3.h:371
uint16_t ee_ctl[NUM_CTLS_MAX]
Definition: ah_eeprom_v3.h:417
uint16_t twice_rdEdgePower
Definition: ah_eeprom.h:118
uint16_t rdEdge
Definition: ah_eeprom.h:117
int8_t stepName[16]
Definition: ar5211.h:76
int16_t paramVal[4]
Definition: ar5211.h:74
int32_t stepGain
Definition: ar5211.h:75
uint32_t ah_rssiThr
Definition: ar5211.h:131
u_int ah_slottime
Definition: ar5211.h:134
u_int ah_sifstime
Definition: ar5211.h:133
int ah_rfgainState
Definition: ar5211.h:127
uint32_t ah_maskReg
Definition: ar5211.h:117
u_int ah_acktimeout
Definition: ar5211.h:135
GAIN_VALUES ah_gainValues
Definition: ar5211.h:109
u_int ah_ctstimeout
Definition: ar5211.h:136
uint8_t ah_bssid[IEEE80211_ADDR_LEN]
Definition: ar5211.h:112
HAL_BOOL ah_bIQCalibration
Definition: ar5211.h:126
uint8_t ah_macaddr[IEEE80211_ADDR_LEN]
Definition: ar5211.h:111
HAL_ANT_SETTING ah_diversityControl
Definition: ar5211.h:124
uint32_t ah_tx6PowerInHalfDbm
Definition: ar5211.h:128
uint32_t ah_calibrationTime
Definition: ar5211.h:125
uint32_t ah_staId1Defaults
Definition: ar5211.h:129
Definition: ah.h:1219
uint16_t clip
Definition: ah_eeprom_v3.h:215
uint16_t pd90
Definition: ah_eeprom_v3.h:214
uint16_t gSel
Definition: ah_eeprom_v3.h:212
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
uint16_t twicePwr54
Definition: ah_eeprom_v3.h:195
uint16_t twicePwr48
Definition: ah_eeprom_v3.h:196
uint16_t twicePwr6_24
Definition: ah_eeprom_v3.h:198
uint16_t twicePwr36
Definition: ah_eeprom_v3.h:197