Check for SYS/GL during library init. Reason is that
[AROS.git] / workbench / devs / networks / atheros5000 / hal / ar5211 / ar5211_reset.c
blob568b4aac5d0660157f13488cb08414ba226b95b2
1 /*
2 * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
3 * Copyright (c) 2002-2006 Atheros Communications, Inc.
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 * $Id$
19 #include "opt_ah.h"
21 #ifdef AH_SUPPORT_AR5211
23 * Chips specific device attachment and device info collection
24 * Connects Init Reg Vectors, EEPROM Data, and device Functions.
26 #include "ah.h"
27 #include "ah_internal.h"
28 #include "ah_devid.h"
30 #include "ar5211/ar5211.h"
31 #include "ar5211/ar5211reg.h"
32 #include "ar5211/ar5211phy.h"
34 #include "ah_eeprom_v3.h"
36 /* Add static register initialization vectors */
37 #include "ar5211/boss.ini"
40 * Structure to hold 11b tuning information for Beanie/Sombrero
41 * 16 MHz mode, divider ratio = 198 = NP+S. N=16, S=4 or 6, P=12
43 typedef struct {
44 uint32_t refClkSel; /* reference clock, 1 for 16 MHz */
45 uint32_t channelSelect; /* P[7:4]S[3:0] bits */
46 uint16_t channel5111; /* 11a channel for 5111 */
47 } CHAN_INFO_2GHZ;
49 #define CI_2GHZ_INDEX_CORRECTION 19
50 const static CHAN_INFO_2GHZ chan2GHzData[] = {
51 { 1, 0x46, 96 }, /* 2312 -19 */
52 { 1, 0x46, 97 }, /* 2317 -18 */
53 { 1, 0x46, 98 }, /* 2322 -17 */
54 { 1, 0x46, 99 }, /* 2327 -16 */
55 { 1, 0x46, 100 }, /* 2332 -15 */
56 { 1, 0x46, 101 }, /* 2337 -14 */
57 { 1, 0x46, 102 }, /* 2342 -13 */
58 { 1, 0x46, 103 }, /* 2347 -12 */
59 { 1, 0x46, 104 }, /* 2352 -11 */
60 { 1, 0x46, 105 }, /* 2357 -10 */
61 { 1, 0x46, 106 }, /* 2362 -9 */
62 { 1, 0x46, 107 }, /* 2367 -8 */
63 { 1, 0x46, 108 }, /* 2372 -7 */
64 /* index -6 to 0 are pad to make this a nolookup table */
65 { 1, 0x46, 116 }, /* -6 */
66 { 1, 0x46, 116 }, /* -5 */
67 { 1, 0x46, 116 }, /* -4 */
68 { 1, 0x46, 116 }, /* -3 */
69 { 1, 0x46, 116 }, /* -2 */
70 { 1, 0x46, 116 }, /* -1 */
71 { 1, 0x46, 116 }, /* 0 */
72 { 1, 0x46, 116 }, /* 2412 1 */
73 { 1, 0x46, 117 }, /* 2417 2 */
74 { 1, 0x46, 118 }, /* 2422 3 */
75 { 1, 0x46, 119 }, /* 2427 4 */
76 { 1, 0x46, 120 }, /* 2432 5 */
77 { 1, 0x46, 121 }, /* 2437 6 */
78 { 1, 0x46, 122 }, /* 2442 7 */
79 { 1, 0x46, 123 }, /* 2447 8 */
80 { 1, 0x46, 124 }, /* 2452 9 */
81 { 1, 0x46, 125 }, /* 2457 10 */
82 { 1, 0x46, 126 }, /* 2462 11 */
83 { 1, 0x46, 127 }, /* 2467 12 */
84 { 1, 0x46, 128 }, /* 2472 13 */
85 { 1, 0x44, 124 }, /* 2484 14 */
86 { 1, 0x46, 136 }, /* 2512 15 */
87 { 1, 0x46, 140 }, /* 2532 16 */
88 { 1, 0x46, 144 }, /* 2552 17 */
89 { 1, 0x46, 148 }, /* 2572 18 */
90 { 1, 0x46, 152 }, /* 2592 19 */
91 { 1, 0x46, 156 }, /* 2612 20 */
92 { 1, 0x46, 160 }, /* 2632 21 */
93 { 1, 0x46, 164 }, /* 2652 22 */
94 { 1, 0x46, 168 }, /* 2672 23 */
95 { 1, 0x46, 172 }, /* 2692 24 */
96 { 1, 0x46, 176 }, /* 2712 25 */
97 { 1, 0x46, 180 } /* 2732 26 */
100 /* Power timeouts in usec to wait for chip to wake-up. */
101 #define POWER_UP_TIME 2000
103 #define DELAY_PLL_SETTLE 300 /* 300 us */
104 #define DELAY_BASE_ACTIVATE 100 /* 100 us */
106 #define NUM_RATES 8
108 static HAL_BOOL ar5211SetResetReg(struct ath_hal *ah, uint32_t resetMask);
109 static HAL_BOOL ar5211SetChannel(struct ath_hal *, HAL_CHANNEL_INTERNAL *);
110 static int16_t ar5211RunNoiseFloor(struct ath_hal *,
111 uint8_t runTime, int16_t startingNF);
112 static HAL_BOOL ar5211IsNfGood(struct ath_hal *, HAL_CHANNEL_INTERNAL *chan);
113 static HAL_BOOL ar5211SetRf6and7(struct ath_hal *, HAL_CHANNEL *chan);
114 static HAL_BOOL ar5211SetBoardValues(struct ath_hal *, HAL_CHANNEL *chan);
115 static void ar5211SetPowerTable(struct ath_hal *,
116 PCDACS_EEPROM *pSrcStruct, uint16_t channel);
117 static void ar5211SetRateTable(struct ath_hal *,
118 RD_EDGES_POWER *pRdEdgesPower, TRGT_POWER_INFO *pPowerInfo,
119 uint16_t numChannels, HAL_CHANNEL *chan);
120 static uint16_t ar5211GetScaledPower(uint16_t channel, uint16_t pcdacValue,
121 const PCDACS_EEPROM *pSrcStruct);
122 static HAL_BOOL ar5211FindValueInList(uint16_t channel, uint16_t pcdacValue,
123 const PCDACS_EEPROM *pSrcStruct, uint16_t *powerValue);
124 static uint16_t ar5211GetInterpolatedValue(uint16_t target,
125 uint16_t srcLeft, uint16_t srcRight,
126 uint16_t targetLeft, uint16_t targetRight, HAL_BOOL scaleUp);
127 static void ar5211GetLowerUpperValues(uint16_t value,
128 const uint16_t *pList, uint16_t listSize,
129 uint16_t *pLowerValue, uint16_t *pUpperValue);
130 static void ar5211GetLowerUpperPcdacs(uint16_t pcdac,
131 uint16_t channel, const PCDACS_EEPROM *pSrcStruct,
132 uint16_t *pLowerPcdac, uint16_t *pUpperPcdac);
134 static void ar5211SetRfgain(struct ath_hal *, const GAIN_VALUES *);;
135 static void ar5211RequestRfgain(struct ath_hal *);
136 static HAL_BOOL ar5211InvalidGainReadback(struct ath_hal *, GAIN_VALUES *);
137 static HAL_BOOL ar5211IsGainAdjustNeeded(struct ath_hal *, const GAIN_VALUES *);
138 static int32_t ar5211AdjustGain(struct ath_hal *, GAIN_VALUES *);
139 static void ar5211SetOperatingMode(struct ath_hal *, int opmode);
142 * Places the device in and out of reset and then places sane
143 * values in the registers based on EEPROM config, initialization
144 * vectors (as determined by the mode), and station configuration
146 * bChannelChange is used to preserve DMA/PCU registers across
147 * a HW Reset during channel change.
149 HAL_BOOL
150 ar5211Reset(struct ath_hal *ah, HAL_OPMODE opmode,
151 HAL_CHANNEL *chan, HAL_BOOL bChannelChange, HAL_STATUS *status)
153 uint32_t softLedCfg, softLedState;
154 #define N(a) (sizeof (a) /sizeof (a[0]))
155 #define FAIL(_code) do { ecode = _code; goto bad; } while (0)
156 struct ath_hal_5211 *ahp = AH5211(ah);
157 HAL_CHANNEL_INTERNAL *ichan;
158 uint32_t i, ledstate;
159 HAL_STATUS ecode;
160 int q;
162 uint32_t data, synthDelay;
163 uint32_t macStaId1;
164 uint16_t modesIndex = 0, freqIndex = 0;
165 uint32_t saveFrameSeqCount[AR_NUM_DCU];
166 uint32_t saveTsfLow = 0, saveTsfHigh = 0;
167 uint32_t saveDefAntenna;
169 HALDEBUG(ah, HAL_DEBUG_RESET,
170 "%s: opmode %u channel %u/0x%x %s channel\n",
171 __func__, opmode, chan->channel, chan->channelFlags,
172 bChannelChange ? "change" : "same");
174 OS_MARK(ah, AH_MARK_RESET, bChannelChange);
175 #define IS(_c,_f) (((_c)->channelFlags & _f) || 0)
176 if ((IS(chan, CHANNEL_2GHZ) ^ IS(chan,CHANNEL_5GHZ)) == 0) {
177 HALDEBUG(ah, HAL_DEBUG_ANY,
178 "%s: invalid channel %u/0x%x; not marked as 2GHz or 5GHz\n",
179 __func__, chan->channel, chan->channelFlags);
180 FAIL(HAL_EINVAL);
182 if ((IS(chan, CHANNEL_OFDM) ^ IS(chan, CHANNEL_CCK)) == 0) {
183 HALDEBUG(ah, HAL_DEBUG_ANY,
184 "%s: invalid channel %u/0x%x; not marked as OFDM or CCK\n",
185 __func__, chan->channel, chan->channelFlags);
186 FAIL(HAL_EINVAL);
188 #undef IS
190 * Map public channel to private.
192 ichan = ath_hal_checkchannel(ah, chan);
193 if (ichan == AH_NULL) {
194 HALDEBUG(ah, HAL_DEBUG_ANY,
195 "%s: invalid channel %u/0x%x; no mapping\n",
196 __func__, chan->channel, chan->channelFlags);
197 FAIL(HAL_EINVAL);
199 switch (opmode) {
200 case HAL_M_STA:
201 case HAL_M_IBSS:
202 case HAL_M_HOSTAP:
203 case HAL_M_MONITOR:
204 break;
205 default:
206 HALDEBUG(ah, HAL_DEBUG_ANY,
207 "%s: invalid operating mode %u\n", __func__, opmode);
208 FAIL(HAL_EINVAL);
209 break;
211 HALASSERT(AH_PRIVATE(ah)->ah_eeversion >= AR_EEPROM_VER3);
213 /* Preserve certain DMA hardware registers on a channel change */
214 if (bChannelChange) {
216 * Need to save/restore the TSF because of an issue
217 * that accelerates the TSF during a chip reset.
219 * We could use system timer routines to more
220 * accurately restore the TSF, but
221 * 1. Timer routines on certain platforms are
222 * not accurate enough (e.g. 1 ms resolution).
223 * 2. It would still not be accurate.
225 * The most important aspect of this solution,
226 * is that, after reset, the TSF is behind
227 * other STAs TSFs. This will allow the STA to
228 * properly resynchronize its TSF in adhoc mode.
230 saveTsfLow = OS_REG_READ(ah, AR_TSF_L32);
231 saveTsfHigh = OS_REG_READ(ah, AR_TSF_U32);
233 /* Read frame sequence count */
234 if (AH_PRIVATE(ah)->ah_macVersion >= AR_SREV_VERSION_OAHU) {
235 saveFrameSeqCount[0] = OS_REG_READ(ah, AR_D0_SEQNUM);
236 } else {
237 for (i = 0; i < AR_NUM_DCU; i++)
238 saveFrameSeqCount[i] = OS_REG_READ(ah, AR_DSEQNUM(i));
240 if (!(ichan->privFlags & CHANNEL_DFS))
241 ichan->privFlags &= ~CHANNEL_INTERFERENCE;
242 chan->channelFlags = ichan->channelFlags;
243 chan->privFlags = ichan->privFlags;
247 * Preserve the antenna on a channel change
249 saveDefAntenna = OS_REG_READ(ah, AR_DEF_ANTENNA);
250 if (saveDefAntenna == 0)
251 saveDefAntenna = 1;
253 /* Save hardware flag before chip reset clears the register */
254 macStaId1 = OS_REG_READ(ah, AR_STA_ID1) & AR_STA_ID1_BASE_RATE_11B;
256 /* Save led state from pci config register */
257 ledstate = OS_REG_READ(ah, AR_PCICFG) &
258 (AR_PCICFG_LEDCTL | AR_PCICFG_LEDMODE | AR_PCICFG_LEDBLINK |
259 AR_PCICFG_LEDSLOW);
260 softLedCfg = OS_REG_READ(ah, AR_GPIOCR);
261 softLedState = OS_REG_READ(ah, AR_GPIODO);
263 if (!ar5211ChipReset(ah, chan->channelFlags)) {
264 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__);
265 FAIL(HAL_EIO);
268 /* Setup the indices for the next set of register array writes */
269 switch (chan->channelFlags & CHANNEL_ALL) {
270 case CHANNEL_A:
271 modesIndex = 1;
272 freqIndex = 1;
273 break;
274 case CHANNEL_T:
275 modesIndex = 2;
276 freqIndex = 1;
277 break;
278 case CHANNEL_B:
279 modesIndex = 3;
280 freqIndex = 2;
281 break;
282 case CHANNEL_PUREG:
283 modesIndex = 4;
284 freqIndex = 2;
285 break;
286 default:
287 /* Ah, a new wireless mode */
288 HALASSERT(0);
289 break;
292 /* Set correct Baseband to analog shift setting to access analog chips. */
293 if (AH_PRIVATE(ah)->ah_macVersion >= AR_SREV_VERSION_OAHU) {
294 OS_REG_WRITE(ah, AR_PHY_BASE, 0x00000007);
295 } else {
296 OS_REG_WRITE(ah, AR_PHY_BASE, 0x00000047);
299 /* Write parameters specific to AR5211 */
300 if (AH_PRIVATE(ah)->ah_macVersion >= AR_SREV_VERSION_OAHU) {
301 if (IS_CHAN_2GHZ(chan) &&
302 AH_PRIVATE(ah)->ah_eeversion >= AR_EEPROM_VER3_1) {
303 HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
304 uint32_t ob2GHz, db2GHz;
306 if (IS_CHAN_CCK(chan)) {
307 ob2GHz = ee->ee_ob2GHz[0];
308 db2GHz = ee->ee_db2GHz[0];
309 } else {
310 ob2GHz = ee->ee_ob2GHz[1];
311 db2GHz = ee->ee_db2GHz[1];
313 ob2GHz = ath_hal_reverseBits(ob2GHz, 3);
314 db2GHz = ath_hal_reverseBits(db2GHz, 3);
315 ar5211Mode2_4[25][freqIndex] =
316 (ar5211Mode2_4[25][freqIndex] & ~0xC0) |
317 ((ob2GHz << 6) & 0xC0);
318 ar5211Mode2_4[26][freqIndex] =
319 (ar5211Mode2_4[26][freqIndex] & ~0x0F) |
320 (((ob2GHz >> 2) & 0x1) |
321 ((db2GHz << 1) & 0x0E));
323 for (i = 0; i < N(ar5211Mode2_4); i++)
324 OS_REG_WRITE(ah, ar5211Mode2_4[i][0],
325 ar5211Mode2_4[i][freqIndex]);
328 /* Write the analog registers 6 and 7 before other config */
329 ar5211SetRf6and7(ah, chan);
331 /* Write registers that vary across all modes */
332 for (i = 0; i < N(ar5211Modes); i++)
333 OS_REG_WRITE(ah, ar5211Modes[i][0], ar5211Modes[i][modesIndex]);
335 /* Write RFGain Parameters that differ between 2.4 and 5 GHz */
336 for (i = 0; i < N(ar5211BB_RfGain); i++)
337 OS_REG_WRITE(ah, ar5211BB_RfGain[i][0], ar5211BB_RfGain[i][freqIndex]);
339 /* Write Common Array Parameters */
340 for (i = 0; i < N(ar5211Common); i++) {
341 uint32_t reg = ar5211Common[i][0];
342 /* On channel change, don't reset the PCU registers */
343 if (!(bChannelChange && (0x8000 <= reg && reg < 0x9000)))
344 OS_REG_WRITE(ah, reg, ar5211Common[i][1]);
347 /* Fix pre-AR5211 register values, this includes AR5311s. */
348 if (AH_PRIVATE(ah)->ah_macVersion < AR_SREV_VERSION_OAHU) {
350 * The TX and RX latency values have changed locations
351 * within the USEC register in AR5211. Since they're
352 * set via the .ini, for both AR5211 and AR5311, they
353 * are written properly here for AR5311.
355 data = OS_REG_READ(ah, AR_USEC);
356 /* Must be 0 for proper write in AR5311 */
357 HALASSERT((data & 0x00700000) == 0);
358 OS_REG_WRITE(ah, AR_USEC,
359 (data & (AR_USEC_M | AR_USEC_32_M | AR5311_USEC_TX_LAT_M)) |
360 ((29 << AR5311_USEC_RX_LAT_S) & AR5311_USEC_RX_LAT_M));
361 /* The following registers exist only on AR5311. */
362 OS_REG_WRITE(ah, AR5311_QDCLKGATE, 0);
364 /* Set proper ADC & DAC delays for AR5311. */
365 OS_REG_WRITE(ah, 0x00009878, 0x00000008);
367 /* Enable the PCU FIFO corruption ECO on AR5311. */
368 OS_REG_WRITE(ah, AR_DIAG_SW,
369 OS_REG_READ(ah, AR_DIAG_SW) | AR5311_DIAG_SW_USE_ECO);
372 /* Restore certain DMA hardware registers on a channel change */
373 if (bChannelChange) {
374 /* Restore TSF */
375 OS_REG_WRITE(ah, AR_TSF_L32, saveTsfLow);
376 OS_REG_WRITE(ah, AR_TSF_U32, saveTsfHigh);
378 if (AH_PRIVATE(ah)->ah_macVersion >= AR_SREV_VERSION_OAHU) {
379 OS_REG_WRITE(ah, AR_D0_SEQNUM, saveFrameSeqCount[0]);
380 } else {
381 for (i = 0; i < AR_NUM_DCU; i++)
382 OS_REG_WRITE(ah, AR_DSEQNUM(i), saveFrameSeqCount[i]);
386 OS_REG_WRITE(ah, AR_STA_ID0, LE_READ_4(ahp->ah_macaddr));
387 OS_REG_WRITE(ah, AR_STA_ID1, LE_READ_2(ahp->ah_macaddr + 4)
388 | macStaId1
390 ar5211SetOperatingMode(ah, opmode);
392 /* Restore previous led state */
393 OS_REG_WRITE(ah, AR_PCICFG, OS_REG_READ(ah, AR_PCICFG) | ledstate);
394 OS_REG_WRITE(ah, AR_GPIOCR, softLedCfg);
395 OS_REG_WRITE(ah, AR_GPIODO, softLedState);
397 /* Restore previous antenna */
398 OS_REG_WRITE(ah, AR_DEF_ANTENNA, saveDefAntenna);
400 OS_REG_WRITE(ah, AR_BSS_ID0, LE_READ_4(ahp->ah_bssid));
401 OS_REG_WRITE(ah, AR_BSS_ID1, LE_READ_2(ahp->ah_bssid + 4));
403 /* Restore bmiss rssi & count thresholds */
404 OS_REG_WRITE(ah, AR_RSSI_THR, ahp->ah_rssiThr);
406 OS_REG_WRITE(ah, AR_ISR, ~0); /* cleared on write */
409 * for pre-Production Oahu only.
410 * Disable clock gating in all DMA blocks. Helps when using
411 * 11B and AES. This will result in higher power consumption.
413 if (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_VERSION_OAHU &&
414 AH_PRIVATE(ah)->ah_macRev < AR_SREV_OAHU_PROD) {
415 OS_REG_WRITE(ah, AR_CFG,
416 OS_REG_READ(ah, AR_CFG) | AR_CFG_CLK_GATE_DIS);
419 /* Setup the transmit power values. */
420 if (!ar5211SetTransmitPower(ah, chan)) {
421 HALDEBUG(ah, HAL_DEBUG_ANY,
422 "%s: error init'ing transmit power\n", __func__);
423 FAIL(HAL_EIO);
427 * Configurable OFDM spoofing for 11n compatibility; used
428 * only when operating in station mode.
430 if (opmode != HAL_M_HOSTAP &&
431 (AH_PRIVATE(ah)->ah_11nCompat & HAL_DIAG_11N_SERVICES) != 0) {
432 /* NB: override the .ini setting */
433 OS_REG_RMW_FIELD(ah, AR_PHY_FRAME_CTL,
434 AR_PHY_FRAME_CTL_ERR_SERV,
435 MS(AH_PRIVATE(ah)->ah_11nCompat, HAL_DIAG_11N_SERVICES)&1);
438 /* Setup board specific options for EEPROM version 3 */
439 ar5211SetBoardValues(ah, chan);
441 if (!ar5211SetChannel(ah, ichan)) {
442 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unable to set channel\n",
443 __func__);
444 FAIL(HAL_EIO);
447 /* Activate the PHY */
448 if (AH_PRIVATE(ah)->ah_devid == AR5211_FPGA11B && IS_CHAN_2GHZ(chan))
449 OS_REG_WRITE(ah, 0xd808, 0x502); /* required for FPGA */
450 OS_REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
453 * Wait for the frequency synth to settle (synth goes on
454 * via AR_PHY_ACTIVE_EN). Read the phy active delay register.
455 * Value is in 100ns increments.
457 data = OS_REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_M;
458 if (IS_CHAN_CCK(chan)) {
459 synthDelay = (4 * data) / 22;
460 } else {
461 synthDelay = data / 10;
464 * There is an issue if the AP starts the calibration before
465 * the baseband timeout completes. This could result in the
466 * rxclear false triggering. Add an extra delay to ensure this
467 * this does not happen.
469 OS_DELAY(synthDelay + DELAY_BASE_ACTIVATE);
471 /* Calibrate the AGC and wait for completion. */
472 OS_REG_WRITE(ah, AR_PHY_AGC_CONTROL,
473 OS_REG_READ(ah, AR_PHY_AGC_CONTROL) | AR_PHY_AGC_CONTROL_CAL);
474 (void) ath_hal_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, 0);
476 /* Perform noise floor and set status */
477 if (!ar5211CalNoiseFloor(ah, ichan)) {
478 if (!IS_CHAN_CCK(chan))
479 chan->channelFlags |= CHANNEL_CW_INT;
480 HALDEBUG(ah, HAL_DEBUG_ANY,
481 "%s: noise floor calibration failed\n", __func__);
482 FAIL(HAL_EIO);
485 /* Start IQ calibration w/ 2^(INIT_IQCAL_LOG_COUNT_MAX+1) samples */
486 if (ahp->ah_calibrationTime != 0) {
487 OS_REG_WRITE(ah, AR_PHY_TIMING_CTRL4,
488 AR_PHY_TIMING_CTRL4_DO_IQCAL | (INIT_IQCAL_LOG_COUNT_MAX << AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX_S));
489 ahp->ah_bIQCalibration = AH_TRUE;
492 /* set 1:1 QCU to DCU mapping for all queues */
493 for (q = 0; q < AR_NUM_DCU; q++)
494 OS_REG_WRITE(ah, AR_DQCUMASK(q), 1<<q);
496 for (q = 0; q < HAL_NUM_TX_QUEUES; q++)
497 ar5211ResetTxQueue(ah, q);
499 /* Setup QCU0 transmit interrupt masks (TX_ERR, TX_OK, TX_DESC, TX_URN) */
500 OS_REG_WRITE(ah, AR_IMR_S0,
501 (AR_IMR_S0_QCU_TXOK & AR_QCU_0) |
502 (AR_IMR_S0_QCU_TXDESC & (AR_QCU_0<<AR_IMR_S0_QCU_TXDESC_S)));
503 OS_REG_WRITE(ah, AR_IMR_S1, (AR_IMR_S1_QCU_TXERR & AR_QCU_0));
504 OS_REG_WRITE(ah, AR_IMR_S2, (AR_IMR_S2_QCU_TXURN & AR_QCU_0));
507 * GBL_EIFS must always be written after writing
508 * to any QCUMASK register.
510 OS_REG_WRITE(ah, AR_D_GBL_IFS_EIFS, OS_REG_READ(ah, AR_D_GBL_IFS_EIFS));
512 /* Now set up the Interrupt Mask Register and save it for future use */
513 OS_REG_WRITE(ah, AR_IMR, INIT_INTERRUPT_MASK);
514 ahp->ah_maskReg = INIT_INTERRUPT_MASK;
516 /* Enable bus error interrupts */
517 OS_REG_WRITE(ah, AR_IMR_S2, OS_REG_READ(ah, AR_IMR_S2) |
518 AR_IMR_S2_MCABT | AR_IMR_S2_SSERR | AR_IMR_S2_DPERR);
520 /* Enable interrupts specific to AP */
521 if (opmode == HAL_M_HOSTAP) {
522 OS_REG_WRITE(ah, AR_IMR, OS_REG_READ(ah, AR_IMR) | AR_IMR_MIB);
523 ahp->ah_maskReg |= AR_IMR_MIB;
526 if (AH_PRIVATE(ah)->ah_rfkillEnabled)
527 ar5211EnableRfKill(ah);
530 * Writing to AR_BEACON will start timers. Hence it should
531 * be the last register to be written. Do not reset tsf, do
532 * not enable beacons at this point, but preserve other values
533 * like beaconInterval.
535 OS_REG_WRITE(ah, AR_BEACON,
536 (OS_REG_READ(ah, AR_BEACON) &~ (AR_BEACON_EN | AR_BEACON_RESET_TSF)));
538 /* Restore user-specified slot time and timeouts */
539 if (ahp->ah_sifstime != (u_int) -1)
540 ar5211SetSifsTime(ah, ahp->ah_sifstime);
541 if (ahp->ah_slottime != (u_int) -1)
542 ar5211SetSlotTime(ah, ahp->ah_slottime);
543 if (ahp->ah_acktimeout != (u_int) -1)
544 ar5211SetAckTimeout(ah, ahp->ah_acktimeout);
545 if (ahp->ah_ctstimeout != (u_int) -1)
546 ar5211SetCTSTimeout(ah, ahp->ah_ctstimeout);
547 if (AH_PRIVATE(ah)->ah_diagreg != 0)
548 OS_REG_WRITE(ah, AR_DIAG_SW, AH_PRIVATE(ah)->ah_diagreg);
550 AH_PRIVATE(ah)->ah_opmode = opmode; /* record operating mode */
552 HALDEBUG(ah, HAL_DEBUG_RESET, "%s: done\n", __func__);
554 return AH_TRUE;
555 bad:
556 if (*status)
557 *status = ecode;
558 return AH_FALSE;
559 #undef FAIL
560 #undef N
564 * Places the PHY and Radio chips into reset. A full reset
565 * must be called to leave this state. The PCI/MAC/PCU are
566 * not placed into reset as we must receive interrupt to
567 * re-enable the hardware.
569 HAL_BOOL
570 ar5211PhyDisable(struct ath_hal *ah)
572 return ar5211SetResetReg(ah, AR_RC_BB);
576 * Places all of hardware into reset
578 HAL_BOOL
579 ar5211Disable(struct ath_hal *ah)
581 if (!ar5211SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE))
582 return AH_FALSE;
584 * Reset the HW - PCI must be reset after the rest of the
585 * device has been reset.
587 if (!ar5211SetResetReg(ah, AR_RC_MAC | AR_RC_BB | AR_RC_PCI))
588 return AH_FALSE;
589 OS_DELAY(2100); /* 8245 @ 96Mhz hangs with 2000us. */
591 return AH_TRUE;
595 * Places the hardware into reset and then pulls it out of reset
597 * Only write the PLL if we're changing to or from CCK mode
599 * Attach calls with channelFlags = 0, as the coldreset should have
600 * us in the correct mode and we cannot check the hwchannel flags.
602 HAL_BOOL
603 ar5211ChipReset(struct ath_hal *ah, uint16_t channelFlags)
605 if (!ar5211SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE))
606 return AH_FALSE;
608 /* Set CCK and Turbo modes correctly */
609 switch (channelFlags & CHANNEL_ALL) {
610 case CHANNEL_2GHZ|CHANNEL_CCK:
611 case CHANNEL_2GHZ|CHANNEL_CCK|CHANNEL_TURBO:
612 OS_REG_WRITE(ah, AR_PHY_TURBO, 0);
613 OS_REG_WRITE(ah, AR5211_PHY_MODE,
614 AR5211_PHY_MODE_CCK | AR5211_PHY_MODE_RF2GHZ);
615 OS_REG_WRITE(ah, AR_PHY_PLL_CTL, AR_PHY_PLL_CTL_44);
616 /* Wait for the PLL to settle */
617 OS_DELAY(DELAY_PLL_SETTLE);
618 break;
619 case CHANNEL_2GHZ|CHANNEL_OFDM:
620 case CHANNEL_2GHZ|CHANNEL_OFDM|CHANNEL_TURBO:
621 OS_REG_WRITE(ah, AR_PHY_TURBO, 0);
622 if (AH_PRIVATE(ah)->ah_devid == AR5211_DEVID) {
623 OS_REG_WRITE(ah, AR_PHY_PLL_CTL, AR_PHY_PLL_CTL_40);
624 OS_DELAY(DELAY_PLL_SETTLE);
625 OS_REG_WRITE(ah, AR5211_PHY_MODE,
626 AR5211_PHY_MODE_OFDM | AR5211_PHY_MODE_RF2GHZ);
628 break;
629 case CHANNEL_A:
630 case CHANNEL_T:
631 if (channelFlags & CHANNEL_TURBO) {
632 OS_REG_WRITE(ah, AR_PHY_TURBO,
633 AR_PHY_FC_TURBO_MODE | AR_PHY_FC_TURBO_SHORT);
634 } else { /* 5 GHZ OFDM Mode */
635 OS_REG_WRITE(ah, AR_PHY_TURBO, 0);
637 if (AH_PRIVATE(ah)->ah_devid == AR5211_DEVID) {
638 OS_REG_WRITE(ah, AR_PHY_PLL_CTL, AR_PHY_PLL_CTL_40);
639 OS_DELAY(DELAY_PLL_SETTLE);
640 OS_REG_WRITE(ah, AR5211_PHY_MODE,
641 AR5211_PHY_MODE_OFDM | AR5211_PHY_MODE_RF5GHZ);
643 break;
645 /* NB: else no flags set - must be attach calling - do nothing */
648 * Reset the HW - PCI must be reset after the rest of the
649 * device has been reset
651 if (!ar5211SetResetReg(ah, AR_RC_MAC | AR_RC_BB | AR_RC_PCI))
652 return AH_FALSE;
653 OS_DELAY(2100); /* 8245 @ 96Mhz hangs with 2000us. */
655 /* Bring out of sleep mode (AGAIN) */
656 if (!ar5211SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE))
657 return AH_FALSE;
659 /* Clear warm reset register */
660 return ar5211SetResetReg(ah, 0);
664 * Recalibrate the lower PHY chips to account for temperature/environment
665 * changes.
667 HAL_BOOL
668 ar5211PerCalibration(struct ath_hal *ah, HAL_CHANNEL *chan, HAL_BOOL *isIQdone)
670 struct ath_hal_5211 *ahp = AH5211(ah);
671 HAL_CHANNEL_INTERNAL *ichan;
672 int32_t qCoff, qCoffDenom;
673 uint32_t data;
674 int32_t iqCorrMeas;
675 int32_t iCoff, iCoffDenom;
676 uint32_t powerMeasQ, powerMeasI;
678 ichan = ath_hal_checkchannel(ah, chan);
679 if (ichan == AH_NULL) {
680 HALDEBUG(ah, HAL_DEBUG_ANY,
681 "%s: invalid channel %u/0x%x; no mapping\n",
682 __func__, chan->channel, chan->channelFlags);
683 return AH_FALSE;
685 /* IQ calibration in progress. Check to see if it has finished. */
686 if (ahp->ah_bIQCalibration &&
687 !(OS_REG_READ(ah, AR_PHY_TIMING_CTRL4) & AR_PHY_TIMING_CTRL4_DO_IQCAL)) {
688 /* IQ Calibration has finished. */
689 ahp->ah_bIQCalibration = AH_FALSE;
691 /* Read calibration results. */
692 powerMeasI = OS_REG_READ(ah, AR_PHY_IQCAL_RES_PWR_MEAS_I);
693 powerMeasQ = OS_REG_READ(ah, AR_PHY_IQCAL_RES_PWR_MEAS_Q);
694 iqCorrMeas = OS_REG_READ(ah, AR_PHY_IQCAL_RES_IQ_CORR_MEAS);
697 * Prescale these values to remove 64-bit operation requirement at the loss
698 * of a little precision.
700 iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 128;
701 qCoffDenom = powerMeasQ / 64;
703 /* Protect against divide-by-0. */
704 if (iCoffDenom != 0 && qCoffDenom != 0) {
705 iCoff = (-iqCorrMeas) / iCoffDenom;
706 /* IQCORR_Q_I_COFF is a signed 6 bit number */
707 iCoff = iCoff & 0x3f;
709 qCoff = ((int32_t)powerMeasI / qCoffDenom) - 64;
710 /* IQCORR_Q_Q_COFF is a signed 5 bit number */
711 qCoff = qCoff & 0x1f;
713 HALDEBUG(ah, HAL_DEBUG_PERCAL, "powerMeasI = 0x%08x\n",
714 powerMeasI);
715 HALDEBUG(ah, HAL_DEBUG_PERCAL, "powerMeasQ = 0x%08x\n",
716 powerMeasQ);
717 HALDEBUG(ah, HAL_DEBUG_PERCAL, "iqCorrMeas = 0x%08x\n",
718 iqCorrMeas);
719 HALDEBUG(ah, HAL_DEBUG_PERCAL, "iCoff = %d\n",
720 iCoff);
721 HALDEBUG(ah, HAL_DEBUG_PERCAL, "qCoff = %d\n",
722 qCoff);
724 /* Write IQ */
725 data = OS_REG_READ(ah, AR_PHY_TIMING_CTRL4) |
726 AR_PHY_TIMING_CTRL4_IQCORR_ENABLE |
727 (((uint32_t)iCoff) << AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF_S) |
728 ((uint32_t)qCoff);
729 OS_REG_WRITE(ah, AR_PHY_TIMING_CTRL4, data);
733 /* Perform noise floor and set status */
734 if (!ar5211IsNfGood(ah, ichan)) {
735 /* report up and clear internal state */
736 chan->channelFlags |= CHANNEL_CW_INT;
737 ichan->channelFlags &= ~CHANNEL_CW_INT;
738 return AH_FALSE;
740 if (!ar5211CalNoiseFloor(ah, ichan)) {
742 * Delay 5ms before retrying the noise floor
743 * just to make sure, as we are in an error
744 * condition here.
746 OS_DELAY(5000);
747 if (!ar5211CalNoiseFloor(ah, ichan)) {
748 if (!IS_CHAN_CCK(chan))
749 chan->channelFlags |= CHANNEL_CW_INT;
750 return AH_FALSE;
754 ar5211RequestRfgain(ah);
755 *isIQdone = !ahp->ah_bIQCalibration;
757 return AH_TRUE;
761 * Writes the given reset bit mask into the reset register
763 static HAL_BOOL
764 ar5211SetResetReg(struct ath_hal *ah, uint32_t resetMask)
766 uint32_t mask = resetMask ? resetMask : ~0;
767 HAL_BOOL rt;
769 (void) OS_REG_READ(ah, AR_RXDP);/* flush any pending MMR writes */
770 OS_REG_WRITE(ah, AR_RC, resetMask);
772 /* need to wait at least 128 clocks when reseting PCI before read */
773 OS_DELAY(15);
775 resetMask &= AR_RC_MAC | AR_RC_BB;
776 mask &= AR_RC_MAC | AR_RC_BB;
777 rt = ath_hal_wait(ah, AR_RC, mask, resetMask);
778 if ((resetMask & AR_RC_MAC) == 0) {
779 if (isBigEndian()) {
781 * Set CFG, little-endian for register
782 * and descriptor accesses.
784 mask = INIT_CONFIG_STATUS |
785 AR_CFG_SWTD | AR_CFG_SWRD | AR_CFG_SWRG;
786 OS_REG_WRITE(ah, AR_CFG, LE_READ_4(&mask));
787 } else
788 OS_REG_WRITE(ah, AR_CFG, INIT_CONFIG_STATUS);
790 return rt;
794 * Takes the MHz channel value and sets the Channel value
796 * ASSUMES: Writes enabled to analog bus before AGC is active
797 * or by disabling the AGC.
799 static HAL_BOOL
800 ar5211SetChannel(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan)
802 uint32_t refClk, reg32, data2111;
803 int16_t chan5111, chanIEEE;
805 chanIEEE = ath_hal_mhz2ieee(ah, chan->channel, chan->channelFlags);
806 if (IS_CHAN_2GHZ(chan)) {
807 const CHAN_INFO_2GHZ* ci =
808 &chan2GHzData[chanIEEE + CI_2GHZ_INDEX_CORRECTION];
810 data2111 = ((ath_hal_reverseBits(ci->channelSelect, 8) & 0xff)
811 << 5)
812 | (ci->refClkSel << 4);
813 chan5111 = ci->channel5111;
814 } else {
815 data2111 = 0;
816 chan5111 = chanIEEE;
819 /* Rest of the code is common for 5 GHz and 2.4 GHz. */
820 if (chan5111 >= 145 || (chan5111 & 0x1)) {
821 reg32 = ath_hal_reverseBits(chan5111 - 24, 8) & 0xFF;
822 refClk = 1;
823 } else {
824 reg32 = ath_hal_reverseBits(((chan5111 - 24) / 2), 8) & 0xFF;
825 refClk = 0;
828 reg32 = (reg32 << 2) | (refClk << 1) | (1 << 10) | 0x1;
829 OS_REG_WRITE(ah, AR_PHY(0x27), ((data2111 & 0xff) << 8) | (reg32 & 0xff));
830 reg32 >>= 8;
831 OS_REG_WRITE(ah, AR_PHY(0x34), (data2111 & 0xff00) | (reg32 & 0xff));
833 AH_PRIVATE(ah)->ah_curchan = chan;
834 return AH_TRUE;
837 static int16_t
838 ar5211GetNoiseFloor(struct ath_hal *ah)
840 int16_t nf;
842 nf = (OS_REG_READ(ah, AR_PHY(25)) >> 19) & 0x1ff;
843 if (nf & 0x100)
844 nf = 0 - ((nf ^ 0x1ff) + 1);
845 return nf;
849 * Peform the noisefloor calibration for the length of time set
850 * in runTime (valid values 1 to 7)
852 * Returns: The NF value at the end of the given time (or 0 for failure)
854 int16_t
855 ar5211RunNoiseFloor(struct ath_hal *ah, uint8_t runTime, int16_t startingNF)
857 int i, searchTime;
859 HALASSERT(runTime <= 7);
861 /* Setup noise floor run time and starting value */
862 OS_REG_WRITE(ah, AR_PHY(25),
863 (OS_REG_READ(ah, AR_PHY(25)) & ~0xFFF) |
864 ((runTime << 9) & 0xE00) | (startingNF & 0x1FF));
865 /* Calibrate the noise floor */
866 OS_REG_WRITE(ah, AR_PHY_AGC_CONTROL,
867 OS_REG_READ(ah, AR_PHY_AGC_CONTROL) | AR_PHY_AGC_CONTROL_NF);
869 /* Compute the required amount of searchTime needed to finish NF */
870 if (runTime == 0) {
871 /* 8 search windows * 6.4us each */
872 searchTime = 8 * 7;
873 } else {
874 /* 512 * runtime search windows * 6.4us each */
875 searchTime = (runTime * 512) * 7;
879 * Do not read noise floor until it has been updated
881 * As a guesstimate - we may only get 1/60th the time on
882 * the air to see search windows in a heavily congested
883 * network (40 us every 2400 us of time)
885 for (i = 0; i < 60; i++) {
886 if ((OS_REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) == 0)
887 break;
888 OS_DELAY(searchTime);
890 if (i >= 60) {
891 HALDEBUG(ah, HAL_DEBUG_NFCAL,
892 "NF with runTime %d failed to end on channel %d\n",
893 runTime, AH_PRIVATE(ah)->ah_curchan->channel);
894 HALDEBUG(ah, HAL_DEBUG_NFCAL,
895 " PHY NF Reg state: 0x%x\n",
896 OS_REG_READ(ah, AR_PHY_AGC_CONTROL));
897 HALDEBUG(ah, HAL_DEBUG_NFCAL,
898 " PHY Active Reg state: 0x%x\n",
899 OS_REG_READ(ah, AR_PHY_ACTIVE));
900 return 0;
903 return ar5211GetNoiseFloor(ah);
906 static HAL_BOOL
907 getNoiseFloorThresh(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan, int16_t *nft)
909 HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
911 switch (chan->channelFlags & CHANNEL_ALL_NOTURBO) {
912 case CHANNEL_A:
913 *nft = ee->ee_noiseFloorThresh[0];
914 break;
915 case CHANNEL_CCK|CHANNEL_2GHZ:
916 *nft = ee->ee_noiseFloorThresh[1];
917 break;
918 case CHANNEL_OFDM|CHANNEL_2GHZ:
919 *nft = ee->ee_noiseFloorThresh[2];
920 break;
921 default:
922 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n",
923 __func__, chan->channelFlags);
924 return AH_FALSE;
926 return AH_TRUE;
930 * Read the NF and check it against the noise floor threshhold
932 * Returns: TRUE if the NF is good
934 static HAL_BOOL
935 ar5211IsNfGood(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan)
937 int16_t nf, nfThresh;
939 if (!getNoiseFloorThresh(ah, chan, &nfThresh))
940 return AH_FALSE;
941 if (OS_REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF)
942 HALDEBUG(ah, HAL_DEBUG_ANY,
943 "%s: NF did not complete in calibration window\n", __func__);
944 nf = ar5211GetNoiseFloor(ah);
945 if (nf > nfThresh) {
946 HALDEBUG(ah, HAL_DEBUG_ANY,
947 "%s: noise floor failed; detected %u, threshold %u\n",
948 __func__, nf, nfThresh);
950 * NB: Don't discriminate 2.4 vs 5Ghz, if this
951 * happens it indicates a problem regardless
952 * of the band.
954 chan->channelFlags |= CHANNEL_CW_INT;
956 chan->rawNoiseFloor = nf;
957 return (nf <= nfThresh);
961 * Peform the noisefloor calibration and check for any constant channel
962 * interference.
964 * NOTE: preAR5211 have a lengthy carrier wave detection process - hence
965 * it is if'ed for MKK regulatory domain only.
967 * Returns: TRUE for a successful noise floor calibration; else FALSE
969 HAL_BOOL
970 ar5211CalNoiseFloor(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan)
972 #define N(a) (sizeof (a) / sizeof (a[0]))
973 /* Check for Carrier Wave interference in MKK regulatory zone */
974 if (AH_PRIVATE(ah)->ah_macVersion < AR_SREV_VERSION_OAHU &&
975 ath_hal_getnfcheckrequired(ah, (HAL_CHANNEL *) chan)) {
976 static const uint8_t runtime[3] = { 0, 2, 7 };
977 int16_t nf, nfThresh;
978 int i;
980 if (!getNoiseFloorThresh(ah, chan, &nfThresh))
981 return AH_FALSE;
983 * Run a quick noise floor that will hopefully
984 * complete (decrease delay time).
986 for (i = 0; i < N(runtime); i++) {
987 nf = ar5211RunNoiseFloor(ah, runtime[i], 0);
988 if (nf > nfThresh) {
989 HALDEBUG(ah, HAL_DEBUG_ANY,
990 "%s: run failed with %u > threshold %u "
991 "(runtime %u)\n", __func__,
992 nf, nfThresh, runtime[i]);
993 chan->rawNoiseFloor = 0;
994 } else
995 chan->rawNoiseFloor = nf;
997 return (i <= N(runtime));
998 } else {
999 /* Calibrate the noise floor */
1000 OS_REG_WRITE(ah, AR_PHY_AGC_CONTROL,
1001 OS_REG_READ(ah, AR_PHY_AGC_CONTROL) |
1002 AR_PHY_AGC_CONTROL_NF);
1004 return AH_TRUE;
1005 #undef N
1009 * Adjust NF based on statistical values for 5GHz frequencies.
1011 int16_t
1012 ar5211GetNfAdjust(struct ath_hal *ah, const HAL_CHANNEL_INTERNAL *c)
1014 static const struct {
1015 uint16_t freqLow;
1016 int16_t adjust;
1017 } adjust5111[] = {
1018 { 5790, 11 }, /* NB: ordered high -> low */
1019 { 5730, 10 },
1020 { 5690, 9 },
1021 { 5660, 8 },
1022 { 5610, 7 },
1023 { 5530, 5 },
1024 { 5450, 4 },
1025 { 5379, 2 },
1026 { 5209, 0 }, /* XXX? bogus but doesn't matter */
1027 { 0, 1 },
1029 int i;
1031 for (i = 0; c->channel <= adjust5111[i].freqLow; i++)
1033 /* NB: placeholder for 5111's less severe requirement */
1034 return adjust5111[i].adjust / 3;
1038 * Reads EEPROM header info from device structure and programs
1039 * analog registers 6 and 7
1041 * REQUIRES: Access to the analog device
1043 static HAL_BOOL
1044 ar5211SetRf6and7(struct ath_hal *ah, HAL_CHANNEL *chan)
1046 #define N(a) (sizeof (a) / sizeof (a[0]))
1047 HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
1048 struct ath_hal_5211 *ahp = AH5211(ah);
1049 uint16_t rfXpdGain, rfPloSel, rfPwdXpd;
1050 uint16_t tempOB, tempDB;
1051 uint16_t freqIndex;
1052 int i;
1054 freqIndex = (chan->channelFlags & CHANNEL_2GHZ) ? 2 : 1;
1057 * TODO: This array mode correspondes with the index used
1058 * during the read.
1059 * For readability, this should be changed to an enum or #define
1061 switch (chan->channelFlags & CHANNEL_ALL_NOTURBO) {
1062 case CHANNEL_A:
1063 if (chan->channel > 4000 && chan->channel < 5260) {
1064 tempOB = ee->ee_ob1;
1065 tempDB = ee->ee_db1;
1066 } else if (chan->channel >= 5260 && chan->channel < 5500) {
1067 tempOB = ee->ee_ob2;
1068 tempDB = ee->ee_db2;
1069 } else if (chan->channel >= 5500 && chan->channel < 5725) {
1070 tempOB = ee->ee_ob3;
1071 tempDB = ee->ee_db3;
1072 } else if (chan->channel >= 5725) {
1073 tempOB = ee->ee_ob4;
1074 tempDB = ee->ee_db4;
1075 } else {
1076 /* XXX panic?? */
1077 tempOB = tempDB = 0;
1080 rfXpdGain = ee->ee_xgain[0];
1081 rfPloSel = ee->ee_xpd[0];
1082 rfPwdXpd = !ee->ee_xpd[0];
1084 ar5211Rf6n7[5][freqIndex] =
1085 (ar5211Rf6n7[5][freqIndex] & ~0x10000000) |
1086 (ee->ee_cornerCal.pd84<< 28);
1087 ar5211Rf6n7[6][freqIndex] =
1088 (ar5211Rf6n7[6][freqIndex] & ~0x04000000) |
1089 (ee->ee_cornerCal.pd90 << 26);
1090 ar5211Rf6n7[21][freqIndex] =
1091 (ar5211Rf6n7[21][freqIndex] & ~0x08) |
1092 (ee->ee_cornerCal.gSel << 3);
1093 break;
1094 case CHANNEL_CCK|CHANNEL_2GHZ:
1095 tempOB = ee->ee_obFor24;
1096 tempDB = ee->ee_dbFor24;
1097 rfXpdGain = ee->ee_xgain[1];
1098 rfPloSel = ee->ee_xpd[1];
1099 rfPwdXpd = !ee->ee_xpd[1];
1100 break;
1101 case CHANNEL_OFDM|CHANNEL_2GHZ:
1102 tempOB = ee->ee_obFor24g;
1103 tempDB = ee->ee_dbFor24g;
1104 rfXpdGain = ee->ee_xgain[2];
1105 rfPloSel = ee->ee_xpd[2];
1106 rfPwdXpd = !ee->ee_xpd[2];
1107 break;
1108 default:
1109 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n",
1110 __func__, chan->channelFlags);
1111 return AH_FALSE;
1114 HALASSERT(1 <= tempOB && tempOB <= 5);
1115 HALASSERT(1 <= tempDB && tempDB <= 5);
1117 /* Set rfXpdGain and rfPwdXpd */
1118 ar5211Rf6n7[11][freqIndex] = (ar5211Rf6n7[11][freqIndex] & ~0xC0) |
1119 (((ath_hal_reverseBits(rfXpdGain, 4) << 7) | (rfPwdXpd << 6)) & 0xC0);
1120 ar5211Rf6n7[12][freqIndex] = (ar5211Rf6n7[12][freqIndex] & ~0x07) |
1121 ((ath_hal_reverseBits(rfXpdGain, 4) >> 1) & 0x07);
1123 /* Set OB */
1124 ar5211Rf6n7[12][freqIndex] = (ar5211Rf6n7[12][freqIndex] & ~0x80) |
1125 ((ath_hal_reverseBits(tempOB, 3) << 7) & 0x80);
1126 ar5211Rf6n7[13][freqIndex] = (ar5211Rf6n7[13][freqIndex] & ~0x03) |
1127 ((ath_hal_reverseBits(tempOB, 3) >> 1) & 0x03);
1129 /* Set DB */
1130 ar5211Rf6n7[13][freqIndex] = (ar5211Rf6n7[13][freqIndex] & ~0x1C) |
1131 ((ath_hal_reverseBits(tempDB, 3) << 2) & 0x1C);
1133 /* Set rfPloSel */
1134 ar5211Rf6n7[17][freqIndex] = (ar5211Rf6n7[17][freqIndex] & ~0x08) |
1135 ((rfPloSel << 3) & 0x08);
1137 /* Write the Rf registers 6 & 7 */
1138 for (i = 0; i < N(ar5211Rf6n7); i++)
1139 OS_REG_WRITE(ah, ar5211Rf6n7[i][0], ar5211Rf6n7[i][freqIndex]);
1141 /* Now that we have reprogrammed rfgain value, clear the flag. */
1142 ahp->ah_rfgainState = RFGAIN_INACTIVE;
1144 return AH_TRUE;
1145 #undef N
1148 HAL_BOOL
1149 ar5211SetAntennaSwitchInternal(struct ath_hal *ah, HAL_ANT_SETTING settings,
1150 const HAL_CHANNEL *chan)
1152 #define ANT_SWITCH_TABLE1 0x9960
1153 #define ANT_SWITCH_TABLE2 0x9964
1154 HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
1155 struct ath_hal_5211 *ahp = AH5211(ah);
1156 uint32_t antSwitchA, antSwitchB;
1157 int ix;
1159 switch (chan->channelFlags & CHANNEL_ALL_NOTURBO) {
1160 case CHANNEL_A: ix = 0; break;
1161 case CHANNEL_B: ix = 1; break;
1162 case CHANNEL_PUREG: ix = 2; break;
1163 default:
1164 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n",
1165 __func__, chan->channelFlags);
1166 return AH_FALSE;
1169 antSwitchA = ee->ee_antennaControl[1][ix]
1170 | (ee->ee_antennaControl[2][ix] << 6)
1171 | (ee->ee_antennaControl[3][ix] << 12)
1172 | (ee->ee_antennaControl[4][ix] << 18)
1173 | (ee->ee_antennaControl[5][ix] << 24)
1175 antSwitchB = ee->ee_antennaControl[6][ix]
1176 | (ee->ee_antennaControl[7][ix] << 6)
1177 | (ee->ee_antennaControl[8][ix] << 12)
1178 | (ee->ee_antennaControl[9][ix] << 18)
1179 | (ee->ee_antennaControl[10][ix] << 24)
1182 * For fixed antenna, give the same setting for both switch banks
1184 switch (settings) {
1185 case HAL_ANT_FIXED_A:
1186 antSwitchB = antSwitchA;
1187 break;
1188 case HAL_ANT_FIXED_B:
1189 antSwitchA = antSwitchB;
1190 break;
1191 case HAL_ANT_VARIABLE:
1192 break;
1193 default:
1194 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad antenna setting %u\n",
1195 __func__, settings);
1196 return AH_FALSE;
1198 ahp->ah_diversityControl = settings;
1200 OS_REG_WRITE(ah, ANT_SWITCH_TABLE1, antSwitchA);
1201 OS_REG_WRITE(ah, ANT_SWITCH_TABLE2, antSwitchB);
1203 return AH_TRUE;
1204 #undef ANT_SWITCH_TABLE1
1205 #undef ANT_SWITCH_TABLE2
1209 * Reads EEPROM header info and programs the device for correct operation
1210 * given the channel value
1212 static HAL_BOOL
1213 ar5211SetBoardValues(struct ath_hal *ah, HAL_CHANNEL *chan)
1215 HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
1216 struct ath_hal_5211 *ahp = AH5211(ah);
1217 int arrayMode, falseDectectBackoff;
1219 switch (chan->channelFlags & CHANNEL_ALL_NOTURBO) {
1220 case CHANNEL_A:
1221 arrayMode = 0;
1222 OS_REG_RMW_FIELD(ah, AR_PHY_FRAME_CTL,
1223 AR_PHY_FRAME_CTL_TX_CLIP, ee->ee_cornerCal.clip);
1224 break;
1225 case CHANNEL_CCK|CHANNEL_2GHZ:
1226 arrayMode = 1;
1227 break;
1228 case CHANNEL_OFDM|CHANNEL_2GHZ:
1229 arrayMode = 2;
1230 break;
1231 default:
1232 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n",
1233 __func__, chan->channelFlags);
1234 return AH_FALSE;
1237 /* Set the antenna register(s) correctly for the chip revision */
1238 if (AH_PRIVATE(ah)->ah_macVersion < AR_SREV_VERSION_OAHU) {
1239 OS_REG_WRITE(ah, AR_PHY(68),
1240 (OS_REG_READ(ah, AR_PHY(68)) & 0xFFFFFFFC) | 0x3);
1241 } else {
1242 OS_REG_WRITE(ah, AR_PHY(68),
1243 (OS_REG_READ(ah, AR_PHY(68)) & 0xFFFFFC06) |
1244 (ee->ee_antennaControl[0][arrayMode] << 4) | 0x1);
1246 ar5211SetAntennaSwitchInternal(ah,
1247 ahp->ah_diversityControl, chan);
1249 /* Set the Noise Floor Thresh on ar5211 devices */
1250 OS_REG_WRITE(ah, AR_PHY_BASE + (90 << 2),
1251 (ee->ee_noiseFloorThresh[arrayMode] & 0x1FF) | (1<<9));
1253 OS_REG_WRITE(ah, AR_PHY_BASE + (17 << 2),
1254 (OS_REG_READ(ah, AR_PHY_BASE + (17 << 2)) & 0xFFFFC07F) |
1255 ((ee->ee_switchSettling[arrayMode] << 7) & 0x3F80));
1256 OS_REG_WRITE(ah, AR_PHY_BASE + (18 << 2),
1257 (OS_REG_READ(ah, AR_PHY_BASE + (18 << 2)) & 0xFFFC0FFF) |
1258 ((ee->ee_txrxAtten[arrayMode] << 12) & 0x3F000));
1259 OS_REG_WRITE(ah, AR_PHY_BASE + (20 << 2),
1260 (OS_REG_READ(ah, AR_PHY_BASE + (20 << 2)) & 0xFFFF0000) |
1261 ((ee->ee_pgaDesiredSize[arrayMode] << 8) & 0xFF00) |
1262 (ee->ee_adcDesiredSize[arrayMode] & 0x00FF));
1263 OS_REG_WRITE(ah, AR_PHY_BASE + (13 << 2),
1264 (ee->ee_txEndToXPAOff[arrayMode] << 24) |
1265 (ee->ee_txEndToXPAOff[arrayMode] << 16) |
1266 (ee->ee_txFrameToXPAOn[arrayMode] << 8) |
1267 ee->ee_txFrameToXPAOn[arrayMode]);
1268 OS_REG_WRITE(ah, AR_PHY_BASE + (10 << 2),
1269 (OS_REG_READ(ah, AR_PHY_BASE + (10 << 2)) & 0xFFFF00FF) |
1270 (ee->ee_txEndToXLNAOn[arrayMode] << 8));
1271 OS_REG_WRITE(ah, AR_PHY_BASE + (25 << 2),
1272 (OS_REG_READ(ah, AR_PHY_BASE + (25 << 2)) & 0xFFF80FFF) |
1273 ((ee->ee_thresh62[arrayMode] << 12) & 0x7F000));
1275 #define NO_FALSE_DETECT_BACKOFF 2
1276 #define CB22_FALSE_DETECT_BACKOFF 6
1278 * False detect backoff - suspected 32 MHz spur causes
1279 * false detects in OFDM, causing Tx Hangs. Decrease
1280 * weak signal sensitivity for this card.
1282 falseDectectBackoff = NO_FALSE_DETECT_BACKOFF;
1283 if (AH_PRIVATE(ah)->ah_eeversion < AR_EEPROM_VER3_3) {
1284 if (AH_PRIVATE(ah)->ah_subvendorid == 0x1022 &&
1285 IS_CHAN_OFDM(chan))
1286 falseDectectBackoff += CB22_FALSE_DETECT_BACKOFF;
1287 } else {
1288 uint32_t remainder = chan->channel % 32;
1290 if (remainder && (remainder < 10 || remainder > 22))
1291 falseDectectBackoff += ee->ee_falseDetectBackoff[arrayMode];
1293 OS_REG_WRITE(ah, 0x9924,
1294 (OS_REG_READ(ah, 0x9924) & 0xFFFFFF01)
1295 | ((falseDectectBackoff << 1) & 0xF7));
1297 return AH_TRUE;
1298 #undef NO_FALSE_DETECT_BACKOFF
1299 #undef CB22_FALSE_DETECT_BACKOFF
1303 * Set the limit on the overall output power. Used for dynamic
1304 * transmit power control and the like.
1306 * NOTE: The power is passed in is in units of 0.5 dBm.
1308 HAL_BOOL
1309 ar5211SetTxPowerLimit(struct ath_hal *ah, uint32_t limit)
1312 AH_PRIVATE(ah)->ah_powerLimit = AH_MIN(limit, MAX_RATE_POWER);
1313 OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE_MAX, limit);
1314 return AH_TRUE;
1318 * Sets the transmit power in the baseband for the given
1319 * operating channel and mode.
1321 HAL_BOOL
1322 ar5211SetTransmitPower(struct ath_hal *ah, HAL_CHANNEL *chan)
1324 HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
1325 TRGT_POWER_INFO *pi;
1326 RD_EDGES_POWER *rep;
1327 PCDACS_EEPROM eepromPcdacs;
1328 u_int nchan, cfgCtl;
1329 int i;
1331 /* setup the pcdac struct to point to the correct info, based on mode */
1332 switch (chan->channelFlags & CHANNEL_ALL_NOTURBO) {
1333 case CHANNEL_A:
1334 eepromPcdacs.numChannels = ee->ee_numChannels11a;
1335 eepromPcdacs.pChannelList= ee->ee_channels11a;
1336 eepromPcdacs.pDataPerChannel = ee->ee_dataPerChannel11a;
1337 nchan = ee->ee_numTargetPwr_11a;
1338 pi = ee->ee_trgtPwr_11a;
1339 break;
1340 case CHANNEL_OFDM|CHANNEL_2GHZ:
1341 eepromPcdacs.numChannels = ee->ee_numChannels2_4;
1342 eepromPcdacs.pChannelList= ee->ee_channels11g;
1343 eepromPcdacs.pDataPerChannel = ee->ee_dataPerChannel11g;
1344 nchan = ee->ee_numTargetPwr_11g;
1345 pi = ee->ee_trgtPwr_11g;
1346 break;
1347 case CHANNEL_CCK|CHANNEL_2GHZ:
1348 eepromPcdacs.numChannels = ee->ee_numChannels2_4;
1349 eepromPcdacs.pChannelList= ee->ee_channels11b;
1350 eepromPcdacs.pDataPerChannel = ee->ee_dataPerChannel11b;
1351 nchan = ee->ee_numTargetPwr_11b;
1352 pi = ee->ee_trgtPwr_11b;
1353 break;
1354 default:
1355 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n",
1356 __func__, chan->channelFlags);
1357 return AH_FALSE;
1360 ar5211SetPowerTable(ah, &eepromPcdacs, chan->channel);
1362 rep = AH_NULL;
1363 /* Match CTL to EEPROM value */
1364 cfgCtl = ath_hal_getctl(ah, chan);
1365 for (i = 0; i < ee->ee_numCtls; i++)
1366 if (ee->ee_ctl[i] != 0 && ee->ee_ctl[i] == cfgCtl) {
1367 rep = &ee->ee_rdEdgesPower[i * NUM_EDGES];
1368 break;
1370 ar5211SetRateTable(ah, rep, pi, nchan, chan);
1372 return AH_TRUE;
1376 * Read the transmit power levels from the structures taken
1377 * from EEPROM. Interpolate read transmit power values for
1378 * this channel. Organize the transmit power values into a
1379 * table for writing into the hardware.
1381 void
1382 ar5211SetPowerTable(struct ath_hal *ah, PCDACS_EEPROM *pSrcStruct, uint16_t channel)
1384 static FULL_PCDAC_STRUCT pcdacStruct;
1385 static uint16_t pcdacTable[PWR_TABLE_SIZE];
1387 uint16_t i, j;
1388 uint16_t *pPcdacValues;
1389 int16_t *pScaledUpDbm;
1390 int16_t minScaledPwr;
1391 int16_t maxScaledPwr;
1392 int16_t pwr;
1393 uint16_t pcdacMin = 0;
1394 uint16_t pcdacMax = 63;
1395 uint16_t pcdacTableIndex;
1396 uint16_t scaledPcdac;
1397 uint32_t addr;
1398 uint32_t temp32;
1400 OS_MEMZERO(&pcdacStruct, sizeof(FULL_PCDAC_STRUCT));
1401 OS_MEMZERO(pcdacTable, sizeof(uint16_t) * PWR_TABLE_SIZE);
1402 pPcdacValues = pcdacStruct.PcdacValues;
1403 pScaledUpDbm = pcdacStruct.PwrValues;
1405 /* Initialize the pcdacs to dBM structs pcdacs to be 1 to 63 */
1406 for (i = PCDAC_START, j = 0; i <= PCDAC_STOP; i+= PCDAC_STEP, j++)
1407 pPcdacValues[j] = i;
1409 pcdacStruct.numPcdacValues = j;
1410 pcdacStruct.pcdacMin = PCDAC_START;
1411 pcdacStruct.pcdacMax = PCDAC_STOP;
1413 /* Fill out the power values for this channel */
1414 for (j = 0; j < pcdacStruct.numPcdacValues; j++ )
1415 pScaledUpDbm[j] = ar5211GetScaledPower(channel, pPcdacValues[j], pSrcStruct);
1417 /* Now scale the pcdac values to fit in the 64 entry power table */
1418 minScaledPwr = pScaledUpDbm[0];
1419 maxScaledPwr = pScaledUpDbm[pcdacStruct.numPcdacValues - 1];
1421 /* find minimum and make monotonic */
1422 for (j = 0; j < pcdacStruct.numPcdacValues; j++) {
1423 if (minScaledPwr >= pScaledUpDbm[j]) {
1424 minScaledPwr = pScaledUpDbm[j];
1425 pcdacMin = j;
1428 * Make the full_hsh monotonically increasing otherwise
1429 * interpolation algorithm will get fooled gotta start
1430 * working from the top, hence i = 63 - j.
1432 i = (uint16_t)(pcdacStruct.numPcdacValues - 1 - j);
1433 if (i == 0)
1434 break;
1435 if (pScaledUpDbm[i-1] > pScaledUpDbm[i]) {
1437 * It could be a glitch, so make the power for
1438 * this pcdac the same as the power from the
1439 * next highest pcdac.
1441 pScaledUpDbm[i - 1] = pScaledUpDbm[i];
1445 for (j = 0; j < pcdacStruct.numPcdacValues; j++)
1446 if (maxScaledPwr < pScaledUpDbm[j]) {
1447 maxScaledPwr = pScaledUpDbm[j];
1448 pcdacMax = j;
1451 /* Find the first power level with a pcdac */
1452 pwr = (uint16_t)(PWR_STEP * ((minScaledPwr - PWR_MIN + PWR_STEP / 2) / PWR_STEP) + PWR_MIN);
1454 /* Write all the first pcdac entries based off the pcdacMin */
1455 pcdacTableIndex = 0;
1456 for (i = 0; i < (2 * (pwr - PWR_MIN) / EEP_SCALE + 1); i++)
1457 pcdacTable[pcdacTableIndex++] = pcdacMin;
1459 i = 0;
1460 while (pwr < pScaledUpDbm[pcdacStruct.numPcdacValues - 1]) {
1461 pwr += PWR_STEP;
1462 /* stop if dbM > max_power_possible */
1463 while (pwr < pScaledUpDbm[pcdacStruct.numPcdacValues - 1] &&
1464 (pwr - pScaledUpDbm[i])*(pwr - pScaledUpDbm[i+1]) > 0)
1465 i++;
1466 /* scale by 2 and add 1 to enable round up or down as needed */
1467 scaledPcdac = (uint16_t)(ar5211GetInterpolatedValue(pwr,
1468 pScaledUpDbm[i], pScaledUpDbm[i+1],
1469 (uint16_t)(pPcdacValues[i] * 2),
1470 (uint16_t)(pPcdacValues[i+1] * 2), 0) + 1);
1472 pcdacTable[pcdacTableIndex] = scaledPcdac / 2;
1473 if (pcdacTable[pcdacTableIndex] > pcdacMax)
1474 pcdacTable[pcdacTableIndex] = pcdacMax;
1475 pcdacTableIndex++;
1478 /* Write all the last pcdac entries based off the last valid pcdac */
1479 while (pcdacTableIndex < PWR_TABLE_SIZE) {
1480 pcdacTable[pcdacTableIndex] = pcdacTable[pcdacTableIndex - 1];
1481 pcdacTableIndex++;
1484 /* Finally, write the power values into the baseband power table */
1485 addr = AR_PHY_BASE + (608 << 2);
1486 for (i = 0; i < 32; i++) {
1487 temp32 = 0xffff & ((pcdacTable[2 * i + 1] << 8) | 0xff);
1488 temp32 = (temp32 << 16) | (0xffff & ((pcdacTable[2 * i] << 8) | 0xff));
1489 OS_REG_WRITE(ah, addr, temp32);
1490 addr += 4;
1496 * Set the transmit power in the baseband for the given
1497 * operating channel and mode.
1499 void
1500 ar5211SetRateTable(struct ath_hal *ah, RD_EDGES_POWER *pRdEdgesPower,
1501 TRGT_POWER_INFO *pPowerInfo, uint16_t numChannels,
1502 HAL_CHANNEL *chan)
1504 HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
1505 struct ath_hal_5211 *ahp = AH5211(ah);
1506 static uint16_t ratesArray[NUM_RATES];
1507 static const uint16_t tpcScaleReductionTable[5] =
1508 { 0, 3, 6, 9, MAX_RATE_POWER };
1510 uint16_t *pRatesPower;
1511 uint16_t lowerChannel, lowerIndex=0, lowerPower=0;
1512 uint16_t upperChannel, upperIndex=0, upperPower=0;
1513 uint16_t twiceMaxEdgePower=63;
1514 uint16_t twicePower = 0;
1515 uint16_t i, numEdges;
1516 uint16_t tempChannelList[NUM_EDGES]; /* temp array for holding edge channels */
1517 uint16_t twiceMaxRDPower;
1518 int16_t scaledPower = 0; /* for gcc -O2 */
1519 uint16_t mask = 0x3f;
1520 HAL_BOOL paPreDEnable = 0;
1521 int8_t twiceAntennaGain, twiceAntennaReduction = 0;
1523 pRatesPower = ratesArray;
1524 twiceMaxRDPower = chan->maxRegTxPower * 2;
1526 if (IS_CHAN_5GHZ(chan)) {
1527 twiceAntennaGain = ee->ee_antennaGainMax[0];
1528 } else {
1529 twiceAntennaGain = ee->ee_antennaGainMax[1];
1532 twiceAntennaReduction = ath_hal_getantennareduction(ah, chan, twiceAntennaGain);
1534 if (pRdEdgesPower) {
1535 /* Get the edge power */
1536 for (i = 0; i < NUM_EDGES; i++) {
1537 if (pRdEdgesPower[i].rdEdge == 0)
1538 break;
1539 tempChannelList[i] = pRdEdgesPower[i].rdEdge;
1541 numEdges = i;
1543 ar5211GetLowerUpperValues(chan->channel, tempChannelList,
1544 numEdges, &lowerChannel, &upperChannel);
1545 /* Get the index for this channel */
1546 for (i = 0; i < numEdges; i++)
1547 if (lowerChannel == tempChannelList[i])
1548 break;
1549 HALASSERT(i != numEdges);
1551 if ((lowerChannel == upperChannel &&
1552 lowerChannel == chan->channel) ||
1553 pRdEdgesPower[i].flag) {
1554 twiceMaxEdgePower = pRdEdgesPower[i].twice_rdEdgePower;
1555 HALASSERT(twiceMaxEdgePower > 0);
1559 /* extrapolate the power values for the test Groups */
1560 for (i = 0; i < numChannels; i++)
1561 tempChannelList[i] = pPowerInfo[i].testChannel;
1563 ar5211GetLowerUpperValues(chan->channel, tempChannelList,
1564 numChannels, &lowerChannel, &upperChannel);
1566 /* get the index for the channel */
1567 for (i = 0; i < numChannels; i++) {
1568 if (lowerChannel == tempChannelList[i])
1569 lowerIndex = i;
1570 if (upperChannel == tempChannelList[i]) {
1571 upperIndex = i;
1572 break;
1576 for (i = 0; i < NUM_RATES; i++) {
1577 if (IS_CHAN_OFDM(chan)) {
1578 /* power for rates 6,9,12,18,24 is all the same */
1579 if (i < 5) {
1580 lowerPower = pPowerInfo[lowerIndex].twicePwr6_24;
1581 upperPower = pPowerInfo[upperIndex].twicePwr6_24;
1582 } else if (i == 5) {
1583 lowerPower = pPowerInfo[lowerIndex].twicePwr36;
1584 upperPower = pPowerInfo[upperIndex].twicePwr36;
1585 } else if (i == 6) {
1586 lowerPower = pPowerInfo[lowerIndex].twicePwr48;
1587 upperPower = pPowerInfo[upperIndex].twicePwr48;
1588 } else if (i == 7) {
1589 lowerPower = pPowerInfo[lowerIndex].twicePwr54;
1590 upperPower = pPowerInfo[upperIndex].twicePwr54;
1592 } else {
1593 switch (i) {
1594 case 0:
1595 case 1:
1596 lowerPower = pPowerInfo[lowerIndex].twicePwr6_24;
1597 upperPower = pPowerInfo[upperIndex].twicePwr6_24;
1598 break;
1599 case 2:
1600 case 3:
1601 lowerPower = pPowerInfo[lowerIndex].twicePwr36;
1602 upperPower = pPowerInfo[upperIndex].twicePwr36;
1603 break;
1604 case 4:
1605 case 5:
1606 lowerPower = pPowerInfo[lowerIndex].twicePwr48;
1607 upperPower = pPowerInfo[upperIndex].twicePwr48;
1608 break;
1609 case 6:
1610 case 7:
1611 lowerPower = pPowerInfo[lowerIndex].twicePwr54;
1612 upperPower = pPowerInfo[upperIndex].twicePwr54;
1613 break;
1617 twicePower = ar5211GetInterpolatedValue(chan->channel,
1618 lowerChannel, upperChannel, lowerPower, upperPower, 0);
1620 /* Reduce power by band edge restrictions */
1621 twicePower = AH_MIN(twicePower, twiceMaxEdgePower);
1624 * If turbo is set, reduce power to keep power
1625 * consumption under 2 Watts. Note that we always do
1626 * this unless specially configured. Then we limit
1627 * power only for non-AP operation.
1629 if (IS_CHAN_TURBO(chan) &&
1630 AH_PRIVATE(ah)->ah_eeversion >= AR_EEPROM_VER3_1
1631 #ifdef AH_ENABLE_AP_SUPPORT
1632 && AH_PRIVATE(ah)->ah_opmode != HAL_M_HOSTAP
1633 #endif
1635 twicePower = AH_MIN(twicePower, ee->ee_turbo2WMaxPower5);
1638 /* Reduce power by max regulatory domain allowed restrictions */
1639 pRatesPower[i] = AH_MIN(twicePower, twiceMaxRDPower - twiceAntennaReduction);
1641 /* Use 6 Mb power level for transmit power scaling reduction */
1642 /* We don't want to reduce higher rates if its not needed */
1643 if (i == 0) {
1644 scaledPower = pRatesPower[0] -
1645 (tpcScaleReductionTable[AH_PRIVATE(ah)->ah_tpScale] * 2);
1646 if (scaledPower < 1)
1647 scaledPower = 1;
1650 pRatesPower[i] = AH_MIN(pRatesPower[i], scaledPower);
1653 /* Record txPower at Rate 6 for info gathering */
1654 ahp->ah_tx6PowerInHalfDbm = pRatesPower[0];
1656 #ifdef AH_DEBUG
1657 HALDEBUG(ah, HAL_DEBUG_RESET,
1658 "%s: final output power setting %d MHz:\n",
1659 __func__, chan->channel);
1660 HALDEBUG(ah, HAL_DEBUG_RESET,
1661 "6 Mb %d dBm, MaxRD: %d dBm, MaxEdge %d dBm\n",
1662 scaledPower / 2, twiceMaxRDPower / 2, twiceMaxEdgePower / 2);
1663 HALDEBUG(ah, HAL_DEBUG_RESET, "TPC Scale %d dBm - Ant Red %d dBm\n",
1664 tpcScaleReductionTable[AH_PRIVATE(ah)->ah_tpScale] * 2,
1665 twiceAntennaReduction / 2);
1666 if (IS_CHAN_TURBO(chan) &&
1667 AH_PRIVATE(ah)->ah_eeversion >= AR_EEPROM_VER3_1)
1668 HALDEBUG(ah, HAL_DEBUG_RESET, "Max Turbo %d dBm\n",
1669 ee->ee_turbo2WMaxPower5);
1670 HALDEBUG(ah, HAL_DEBUG_RESET,
1671 " %2d | %2d | %2d | %2d | %2d | %2d | %2d | %2d dBm\n",
1672 pRatesPower[0] / 2, pRatesPower[1] / 2, pRatesPower[2] / 2,
1673 pRatesPower[3] / 2, pRatesPower[4] / 2, pRatesPower[5] / 2,
1674 pRatesPower[6] / 2, pRatesPower[7] / 2);
1675 #endif /* AH_DEBUG */
1677 /* Write the power table into the hardware */
1678 OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE1,
1679 ((paPreDEnable & 1)<< 30) | ((pRatesPower[3] & mask) << 24) |
1680 ((paPreDEnable & 1)<< 22) | ((pRatesPower[2] & mask) << 16) |
1681 ((paPreDEnable & 1)<< 14) | ((pRatesPower[1] & mask) << 8) |
1682 ((paPreDEnable & 1)<< 6 ) | (pRatesPower[0] & mask));
1683 OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE2,
1684 ((paPreDEnable & 1)<< 30) | ((pRatesPower[7] & mask) << 24) |
1685 ((paPreDEnable & 1)<< 22) | ((pRatesPower[6] & mask) << 16) |
1686 ((paPreDEnable & 1)<< 14) | ((pRatesPower[5] & mask) << 8) |
1687 ((paPreDEnable & 1)<< 6 ) | (pRatesPower[4] & mask));
1689 /* set max power to the power value at rate 6 */
1690 ar5211SetTxPowerLimit(ah, pRatesPower[0]);
1692 AH_PRIVATE(ah)->ah_maxPowerLevel = pRatesPower[0];
1696 * Get or interpolate the pcdac value from the calibrated data
1698 uint16_t
1699 ar5211GetScaledPower(uint16_t channel, uint16_t pcdacValue, const PCDACS_EEPROM *pSrcStruct)
1701 uint16_t powerValue;
1702 uint16_t lFreq, rFreq; /* left and right frequency values */
1703 uint16_t llPcdac, ulPcdac; /* lower and upper left pcdac values */
1704 uint16_t lrPcdac, urPcdac; /* lower and upper right pcdac values */
1705 uint16_t lPwr, uPwr; /* lower and upper temp pwr values */
1706 uint16_t lScaledPwr, rScaledPwr; /* left and right scaled power */
1708 if (ar5211FindValueInList(channel, pcdacValue, pSrcStruct, &powerValue))
1709 /* value was copied from srcStruct */
1710 return powerValue;
1712 ar5211GetLowerUpperValues(channel, pSrcStruct->pChannelList,
1713 pSrcStruct->numChannels, &lFreq, &rFreq);
1714 ar5211GetLowerUpperPcdacs(pcdacValue, lFreq, pSrcStruct,
1715 &llPcdac, &ulPcdac);
1716 ar5211GetLowerUpperPcdacs(pcdacValue, rFreq, pSrcStruct,
1717 &lrPcdac, &urPcdac);
1719 /* get the power index for the pcdac value */
1720 ar5211FindValueInList(lFreq, llPcdac, pSrcStruct, &lPwr);
1721 ar5211FindValueInList(lFreq, ulPcdac, pSrcStruct, &uPwr);
1722 lScaledPwr = ar5211GetInterpolatedValue(pcdacValue,
1723 llPcdac, ulPcdac, lPwr, uPwr, 0);
1725 ar5211FindValueInList(rFreq, lrPcdac, pSrcStruct, &lPwr);
1726 ar5211FindValueInList(rFreq, urPcdac, pSrcStruct, &uPwr);
1727 rScaledPwr = ar5211GetInterpolatedValue(pcdacValue,
1728 lrPcdac, urPcdac, lPwr, uPwr, 0);
1730 return ar5211GetInterpolatedValue(channel, lFreq, rFreq,
1731 lScaledPwr, rScaledPwr, 0);
1735 * Find the value from the calibrated source data struct
1737 HAL_BOOL
1738 ar5211FindValueInList(uint16_t channel, uint16_t pcdacValue,
1739 const PCDACS_EEPROM *pSrcStruct, uint16_t *powerValue)
1741 const DATA_PER_CHANNEL *pChannelData;
1742 const uint16_t *pPcdac;
1743 uint16_t i, j;
1745 pChannelData = pSrcStruct->pDataPerChannel;
1746 for (i = 0; i < pSrcStruct->numChannels; i++ ) {
1747 if (pChannelData->channelValue == channel) {
1748 pPcdac = pChannelData->PcdacValues;
1749 for (j = 0; j < pChannelData->numPcdacValues; j++ ) {
1750 if (*pPcdac == pcdacValue) {
1751 *powerValue = pChannelData->PwrValues[j];
1752 return AH_TRUE;
1754 pPcdac++;
1757 pChannelData++;
1759 return AH_FALSE;
1763 * Returns interpolated or the scaled up interpolated value
1765 uint16_t
1766 ar5211GetInterpolatedValue(uint16_t target,
1767 uint16_t srcLeft, uint16_t srcRight,
1768 uint16_t targetLeft, uint16_t targetRight,
1769 HAL_BOOL scaleUp)
1771 uint16_t rv;
1772 int16_t lRatio;
1773 uint16_t scaleValue = EEP_SCALE;
1775 /* to get an accurate ratio, always scale, if want to scale, then don't scale back down */
1776 if ((targetLeft * targetRight) == 0)
1777 return 0;
1778 if (scaleUp)
1779 scaleValue = 1;
1781 if (srcRight != srcLeft) {
1783 * Note the ratio always need to be scaled,
1784 * since it will be a fraction.
1786 lRatio = (target - srcLeft) * EEP_SCALE / (srcRight - srcLeft);
1787 if (lRatio < 0) {
1788 /* Return as Left target if value would be negative */
1789 rv = targetLeft * (scaleUp ? EEP_SCALE : 1);
1790 } else if (lRatio > EEP_SCALE) {
1791 /* Return as Right target if Ratio is greater than 100% (SCALE) */
1792 rv = targetRight * (scaleUp ? EEP_SCALE : 1);
1793 } else {
1794 rv = (lRatio * targetRight + (EEP_SCALE - lRatio) *
1795 targetLeft) / scaleValue;
1797 } else {
1798 rv = targetLeft;
1799 if (scaleUp)
1800 rv *= EEP_SCALE;
1802 return rv;
1806 * Look for value being within 0.1 of the search values
1807 * however, NDIS can't do float calculations, so multiply everything
1808 * up by EEP_SCALE so can do integer arithmatic
1810 * INPUT value -value to search for
1811 * INPUT pList -ptr to the list to search
1812 * INPUT listSize -number of entries in list
1813 * OUTPUT pLowerValue -return the lower value
1814 * OUTPUT pUpperValue -return the upper value
1816 void
1817 ar5211GetLowerUpperValues(uint16_t value,
1818 const uint16_t *pList, uint16_t listSize,
1819 uint16_t *pLowerValue, uint16_t *pUpperValue)
1821 const uint16_t listEndValue = *(pList + listSize - 1);
1822 uint32_t target = value * EEP_SCALE;
1823 int i;
1826 * See if value is lower than the first value in the list
1827 * if so return first value
1829 if (target < (uint32_t)(*pList * EEP_SCALE - EEP_DELTA)) {
1830 *pLowerValue = *pList;
1831 *pUpperValue = *pList;
1832 return;
1836 * See if value is greater than last value in list
1837 * if so return last value
1839 if (target > (uint32_t)(listEndValue * EEP_SCALE + EEP_DELTA)) {
1840 *pLowerValue = listEndValue;
1841 *pUpperValue = listEndValue;
1842 return;
1845 /* look for value being near or between 2 values in list */
1846 for (i = 0; i < listSize; i++) {
1848 * If value is close to the current value of the list
1849 * then target is not between values, it is one of the values
1851 if (abs(pList[i] * EEP_SCALE - (int32_t) target) < EEP_DELTA) {
1852 *pLowerValue = pList[i];
1853 *pUpperValue = pList[i];
1854 return;
1858 * Look for value being between current value and next value
1859 * if so return these 2 values
1861 if (target < (uint32_t)(pList[i + 1] * EEP_SCALE - EEP_DELTA)) {
1862 *pLowerValue = pList[i];
1863 *pUpperValue = pList[i + 1];
1864 return;
1870 * Get the upper and lower pcdac given the channel and the pcdac
1871 * used in the search
1873 void
1874 ar5211GetLowerUpperPcdacs(uint16_t pcdac, uint16_t channel,
1875 const PCDACS_EEPROM *pSrcStruct,
1876 uint16_t *pLowerPcdac, uint16_t *pUpperPcdac)
1878 const DATA_PER_CHANNEL *pChannelData;
1879 int i;
1881 /* Find the channel information */
1882 pChannelData = pSrcStruct->pDataPerChannel;
1883 for (i = 0; i < pSrcStruct->numChannels; i++) {
1884 if (pChannelData->channelValue == channel)
1885 break;
1886 pChannelData++;
1888 ar5211GetLowerUpperValues(pcdac, pChannelData->PcdacValues,
1889 pChannelData->numPcdacValues, pLowerPcdac, pUpperPcdac);
1892 #define DYN_ADJ_UP_MARGIN 15
1893 #define DYN_ADJ_LO_MARGIN 20
1895 static const GAIN_OPTIMIZATION_LADDER gainLadder = {
1896 9, /* numStepsInLadder */
1897 4, /* defaultStepNum */
1898 { { {4, 1, 1, 1}, 6, "FG8"},
1899 { {4, 0, 1, 1}, 4, "FG7"},
1900 { {3, 1, 1, 1}, 3, "FG6"},
1901 { {4, 0, 0, 1}, 1, "FG5"},
1902 { {4, 1, 1, 0}, 0, "FG4"}, /* noJack */
1903 { {4, 0, 1, 0}, -2, "FG3"}, /* halfJack */
1904 { {3, 1, 1, 0}, -3, "FG2"}, /* clip3 */
1905 { {4, 0, 0, 0}, -4, "FG1"}, /* noJack */
1906 { {2, 1, 1, 0}, -6, "FG0"} /* clip2 */
1911 * Initialize the gain structure to good values
1913 void
1914 ar5211InitializeGainValues(struct ath_hal *ah)
1916 struct ath_hal_5211 *ahp = AH5211(ah);
1917 GAIN_VALUES *gv = &ahp->ah_gainValues;
1919 /* initialize gain optimization values */
1920 gv->currStepNum = gainLadder.defaultStepNum;
1921 gv->currStep = &gainLadder.optStep[gainLadder.defaultStepNum];
1922 gv->active = AH_TRUE;
1923 gv->loTrig = 20;
1924 gv->hiTrig = 35;
1927 static HAL_BOOL
1928 ar5211InvalidGainReadback(struct ath_hal *ah, GAIN_VALUES *gv)
1930 HAL_CHANNEL_INTERNAL *chan = AH_PRIVATE(ah)->ah_curchan;
1931 uint32_t gStep, g;
1932 uint32_t L1, L2, L3, L4;
1934 if (IS_CHAN_CCK(chan)) {
1935 gStep = 0x18;
1936 L1 = 0;
1937 L2 = gStep + 4;
1938 L3 = 0x40;
1939 L4 = L3 + 50;
1941 gv->loTrig = L1;
1942 gv->hiTrig = L4+5;
1943 } else {
1944 gStep = 0x3f;
1945 L1 = 0;
1946 L2 = 50;
1947 L3 = L1;
1948 L4 = L3 + 50;
1950 gv->loTrig = L1 + DYN_ADJ_LO_MARGIN;
1951 gv->hiTrig = L4 - DYN_ADJ_UP_MARGIN;
1953 g = gv->currGain;
1955 return !((g >= L1 && g<= L2) || (g >= L3 && g <= L4));
1959 * Enable the probe gain check on the next packet
1961 static void
1962 ar5211RequestRfgain(struct ath_hal *ah)
1964 struct ath_hal_5211 *ahp = AH5211(ah);
1966 /* Enable the gain readback probe */
1967 OS_REG_WRITE(ah, AR_PHY_PAPD_PROBE,
1968 SM(ahp->ah_tx6PowerInHalfDbm, AR_PHY_PAPD_PROBE_POWERTX)
1969 | AR_PHY_PAPD_PROBE_NEXT_TX);
1971 ahp->ah_rfgainState = HAL_RFGAIN_READ_REQUESTED;
1975 * Exported call to check for a recent gain reading and return
1976 * the current state of the thermal calibration gain engine.
1978 HAL_RFGAIN
1979 ar5211GetRfgain(struct ath_hal *ah)
1981 struct ath_hal_5211 *ahp = AH5211(ah);
1982 GAIN_VALUES *gv = &ahp->ah_gainValues;
1983 uint32_t rddata;
1985 if (!gv->active)
1986 return HAL_RFGAIN_INACTIVE;
1988 if (ahp->ah_rfgainState == HAL_RFGAIN_READ_REQUESTED) {
1989 /* Caller had asked to setup a new reading. Check it. */
1990 rddata = OS_REG_READ(ah, AR_PHY_PAPD_PROBE);
1992 if ((rddata & AR_PHY_PAPD_PROBE_NEXT_TX) == 0) {
1993 /* bit got cleared, we have a new reading. */
1994 gv->currGain = rddata >> AR_PHY_PAPD_PROBE_GAINF_S;
1995 /* inactive by default */
1996 ahp->ah_rfgainState = HAL_RFGAIN_INACTIVE;
1998 if (!ar5211InvalidGainReadback(ah, gv) &&
1999 ar5211IsGainAdjustNeeded(ah, gv) &&
2000 ar5211AdjustGain(ah, gv) > 0) {
2002 * Change needed. Copy ladder info
2003 * into eeprom info.
2005 ar5211SetRfgain(ah, gv);
2006 ahp->ah_rfgainState = HAL_RFGAIN_NEED_CHANGE;
2010 return ahp->ah_rfgainState;
2014 * Check to see if our readback gain level sits within the linear
2015 * region of our current variable attenuation window
2017 static HAL_BOOL
2018 ar5211IsGainAdjustNeeded(struct ath_hal *ah, const GAIN_VALUES *gv)
2020 return (gv->currGain <= gv->loTrig || gv->currGain >= gv->hiTrig);
2024 * Move the rabbit ears in the correct direction.
2026 static int32_t
2027 ar5211AdjustGain(struct ath_hal *ah, GAIN_VALUES *gv)
2029 /* return > 0 for valid adjustments. */
2030 if (!gv->active)
2031 return -1;
2033 gv->currStep = &gainLadder.optStep[gv->currStepNum];
2034 if (gv->currGain >= gv->hiTrig) {
2035 if (gv->currStepNum == 0) {
2036 HALDEBUG(ah, HAL_DEBUG_RFPARAM,
2037 "%s: Max gain limit.\n", __func__);
2038 return -1;
2040 HALDEBUG(ah, HAL_DEBUG_RFPARAM,
2041 "%s: Adding gain: currG=%d [%s] --> ",
2042 __func__, gv->currGain, gv->currStep->stepName);
2043 gv->targetGain = gv->currGain;
2044 while (gv->targetGain >= gv->hiTrig && gv->currStepNum > 0) {
2045 gv->targetGain -= 2 * (gainLadder.optStep[--(gv->currStepNum)].stepGain -
2046 gv->currStep->stepGain);
2047 gv->currStep = &gainLadder.optStep[gv->currStepNum];
2049 HALDEBUG(ah, HAL_DEBUG_RFPARAM, "targG=%d [%s]\n",
2050 gv->targetGain, gv->currStep->stepName);
2051 return 1;
2053 if (gv->currGain <= gv->loTrig) {
2054 if (gv->currStepNum == gainLadder.numStepsInLadder-1) {
2055 HALDEBUG(ah, HAL_DEBUG_RFPARAM,
2056 "%s: Min gain limit.\n", __func__);
2057 return -2;
2059 HALDEBUG(ah, HAL_DEBUG_RFPARAM,
2060 "%s: Deducting gain: currG=%d [%s] --> ",
2061 __func__, gv->currGain, gv->currStep->stepName);
2062 gv->targetGain = gv->currGain;
2063 while (gv->targetGain <= gv->loTrig &&
2064 gv->currStepNum < (gainLadder.numStepsInLadder - 1)) {
2065 gv->targetGain -= 2 *
2066 (gainLadder.optStep[++(gv->currStepNum)].stepGain - gv->currStep->stepGain);
2067 gv->currStep = &gainLadder.optStep[gv->currStepNum];
2069 HALDEBUG(ah, HAL_DEBUG_RFPARAM, "targG=%d [%s]\n",
2070 gv->targetGain, gv->currStep->stepName);
2071 return 2;
2073 return 0; /* caller didn't call needAdjGain first */
2077 * Adjust the 5GHz EEPROM information with the desired calibration values.
2079 static void
2080 ar5211SetRfgain(struct ath_hal *ah, const GAIN_VALUES *gv)
2082 HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
2084 if (!gv->active)
2085 return;
2086 ee->ee_cornerCal.clip = gv->currStep->paramVal[0]; /* bb_tx_clip */
2087 ee->ee_cornerCal.pd90 = gv->currStep->paramVal[1]; /* rf_pwd_90 */
2088 ee->ee_cornerCal.pd84 = gv->currStep->paramVal[2]; /* rf_pwd_84 */
2089 ee->ee_cornerCal.gSel = gv->currStep->paramVal[3]; /* rf_rfgainsel */
2092 static void
2093 ar5211SetOperatingMode(struct ath_hal *ah, int opmode)
2095 struct ath_hal_5211 *ahp = AH5211(ah);
2096 uint32_t val;
2098 val = OS_REG_READ(ah, AR_STA_ID1) & 0xffff;
2099 switch (opmode) {
2100 case HAL_M_HOSTAP:
2101 OS_REG_WRITE(ah, AR_STA_ID1, val
2102 | AR_STA_ID1_STA_AP
2103 | AR_STA_ID1_RTS_USE_DEF
2104 | ahp->ah_staId1Defaults);
2105 break;
2106 case HAL_M_IBSS:
2107 OS_REG_WRITE(ah, AR_STA_ID1, val
2108 | AR_STA_ID1_ADHOC
2109 | AR_STA_ID1_DESC_ANTENNA
2110 | ahp->ah_staId1Defaults);
2111 break;
2112 case HAL_M_STA:
2113 case HAL_M_MONITOR:
2114 OS_REG_WRITE(ah, AR_STA_ID1, val
2115 | AR_STA_ID1_DEFAULT_ANTENNA
2116 | ahp->ah_staId1Defaults);
2117 break;
2121 void
2122 ar5211SetPCUConfig(struct ath_hal *ah)
2124 ar5211SetOperatingMode(ah, AH_PRIVATE(ah)->ah_opmode);
2126 #endif /* AH_SUPPORT_AR5211 */