revert between 56095 -> 55830 in arch
[AROS.git] / workbench / devs / networks / atheros5000 / hal / ar5416 / ar5416_reset.c
blob585428166c016f5e986a85d59749749aa86db339
1 /*
2 * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
3 * Copyright (c) 2002-2008 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_AR5416
23 #include "ah.h"
24 #include "ah_internal.h"
25 #include "ah_devid.h"
27 #include "ah_eeprom_v14.h"
29 #include "ar5416/ar5416.h"
30 #include "ar5416/ar5416reg.h"
31 #include "ar5416/ar5416phy.h"
32 #ifdef AH_SUPPORT_AR9280
33 #include "ar5416/ar9280.h"
34 #endif
36 /* Eeprom versioning macros. Returns true if the version is equal or newer than the ver specified */
37 #define EEP_MINOR(_ah) \
38 (AH_PRIVATE(_ah)->ah_eeversion & AR5416_EEP_VER_MINOR_MASK)
39 #define IS_EEP_MINOR_V2(_ah) (EEP_MINOR(_ah) >= AR5416_EEP_MINOR_VER_2)
40 #define IS_EEP_MINOR_V3(_ah) (EEP_MINOR(_ah) >= AR5416_EEP_MINOR_VER_3)
42 /* Additional Time delay to wait after activiting the Base band */
43 #define BASE_ACTIVATE_DELAY 100 /* 100 usec */
44 #define PLL_SETTLE_DELAY 300 /* 300 usec */
45 #define RTC_PLL_SETTLE_DELAY 1000 /* 1 ms */
47 static void ar5416InitDMA(struct ath_hal *ah);
48 static void ar5416InitBB(struct ath_hal *ah, HAL_CHANNEL *chan);
49 static void ar5416InitIMR(struct ath_hal *ah, HAL_OPMODE opmode);
50 static void ar5416InitQoS(struct ath_hal *ah);
51 static void ar5416InitUserSettings(struct ath_hal *ah);
53 static HAL_BOOL ar5416InitCal(struct ath_hal *ah, HAL_CHANNEL *chan);
55 static HAL_BOOL ar5416SetTransmitPower(struct ath_hal *ah,
56 HAL_CHANNEL_INTERNAL *chan, uint16_t *rfXpdGain);
58 #if 0
59 static HAL_BOOL ar5416ChannelChange(struct ath_hal *, HAL_CHANNEL *);
60 #endif
61 static void ar5416StartNFCal(struct ath_hal *ah);
62 static void ar5416LoadNF(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *);
63 static int16_t ar5416GetNf(struct ath_hal *, HAL_CHANNEL_INTERNAL *);
64 static void ar5416SetDeltaSlope(struct ath_hal *, HAL_CHANNEL_INTERNAL *);
65 static void ar5416SpurMitigate(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan);
66 #ifdef AH_SUPPORT_AR9280
67 static void ar9280SpurMitigate(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan);
68 #endif
70 /* Owl specific stuff */
71 #define NUM_NOISEFLOOR_READINGS 6 /* 3 chains * (ctl + ext) */
73 static HAL_BOOL ar5416SetResetPowerOn(struct ath_hal *ah);
74 static HAL_BOOL ar5416SetReset(struct ath_hal *ah, int type);
75 static void ar5416InitPLL(struct ath_hal *ah, HAL_CHANNEL *chan);
76 static HAL_BOOL ar5416SetBoardValues(struct ath_hal *, HAL_CHANNEL_INTERNAL *);
77 static HAL_BOOL ar5416SetPowerPerRateTable(struct ath_hal *ah,
78 struct ar5416eeprom *pEepData,
79 HAL_CHANNEL_INTERNAL *chan, int16_t *ratesArray,
80 uint16_t cfgCtl, uint16_t AntennaReduction,
81 uint16_t twiceMaxRegulatoryPower,
82 uint16_t powerLimit);
83 static HAL_BOOL ar5416SetPowerCalTable(struct ath_hal *ah,
84 struct ar5416eeprom *pEepData,
85 HAL_CHANNEL_INTERNAL *chan,
86 int16_t *pTxPowerIndexOffset);
87 static uint16_t ar5416GetMaxEdgePower(uint16_t freq,
88 CAL_CTL_EDGES *pRdEdgesPower, HAL_BOOL is2GHz);
89 static void ar5416GetTargetPowers(struct ath_hal *ah,
90 HAL_CHANNEL_INTERNAL *chan, CAL_TARGET_POWER_HT *powInfo,
91 uint16_t numChannels, CAL_TARGET_POWER_HT *pNewPower,
92 uint16_t numRates, HAL_BOOL isHt40Target);
93 static void ar5416GetTargetPowersLeg(struct ath_hal *ah,
94 HAL_CHANNEL_INTERNAL *chan, CAL_TARGET_POWER_LEG *powInfo,
95 uint16_t numChannels, CAL_TARGET_POWER_LEG *pNewPower,
96 uint16_t numRates, HAL_BOOL isExtTarget);
98 static int16_t interpolate(uint16_t target, uint16_t srcLeft,
99 uint16_t srcRight, int16_t targetLeft, int16_t targetRight);
100 static void ar5416Set11nRegs(struct ath_hal *ah, HAL_CHANNEL *chan);
101 static void ar5416GetGainBoundariesAndPdadcs(struct ath_hal *ah,
102 HAL_CHANNEL_INTERNAL *chan, CAL_DATA_PER_FREQ *pRawDataSet,
103 uint8_t * bChans, uint16_t availPiers,
104 uint16_t tPdGainOverlap, int16_t *pMinCalPower,
105 uint16_t * pPdGainBoundaries, uint8_t * pPDADCValues,
106 uint16_t numXpdGains);
107 static HAL_BOOL getLowerUpperIndex(uint8_t target, uint8_t *pList,
108 uint16_t listSize, uint16_t *indexL, uint16_t *indexR);
109 static HAL_BOOL ar5416FillVpdTable(uint8_t pwrMin, uint8_t pwrMax,
110 uint8_t *pPwrList, uint8_t *pVpdList,
111 uint16_t numIntercepts, uint8_t *pRetVpdList);
113 static void ar5416GetNoiseFloor(struct ath_hal *ah,
114 int16_t nfarray[NUM_NOISEFLOOR_READINGS]);
117 * Places the device in and out of reset and then places sane
118 * values in the registers based on EEPROM config, initialization
119 * vectors (as determined by the mode), and station configuration
121 * bChannelChange is used to preserve DMA/PCU registers across
122 * a HW Reset during channel change.
124 HAL_BOOL
125 ar5416Reset(struct ath_hal *ah, HAL_OPMODE opmode,
126 HAL_CHANNEL *chan, HAL_BOOL bChannelChange, HAL_STATUS *status)
128 #define N(a) (sizeof (a) / sizeof (a[0]))
129 #define FAIL(_code) do { ecode = _code; goto bad; } while (0)
130 struct ath_hal_5212 *ahp = AH5212(ah);
131 HAL_CHANNEL_INTERNAL *ichan;
132 uint32_t softLedCfg;
133 uint32_t saveDefAntenna, saveLedState;
134 uint32_t macStaId1;
135 uint16_t rfXpdGain[2];
136 u_int modesIndex, freqIndex;
137 HAL_STATUS ecode;
138 int i, regWrites = 0;
139 uint32_t powerVal, rssiThrReg;
140 uint32_t ackTpcPow, ctsTpcPow, chirpTpcPow;
142 OS_MARK(ah, AH_MARK_RESET, bChannelChange);
143 #define IS(_c,_f) (((_c)->channelFlags & _f) || 0)
144 if ((IS(chan, CHANNEL_2GHZ) ^ IS(chan, CHANNEL_5GHZ)) == 0) {
145 HALDEBUG(ah, HAL_DEBUG_ANY,
146 "%s: invalid channel %u/0x%x; not marked as 2GHz or 5GHz\n",
147 __func__, chan->channel, chan->channelFlags);
148 FAIL(HAL_EINVAL);
150 if ((IS(chan, CHANNEL_OFDM) ^ IS(chan, CHANNEL_CCK)) == 0) {
151 HALDEBUG(ah, HAL_DEBUG_ANY,
152 "%s: invalid channel %u/0x%x; not marked as OFDM or CCK\n",
153 __func__, chan->channel, chan->channelFlags);
154 FAIL(HAL_EINVAL);
156 #undef IS
158 /* Bring out of sleep mode */
159 if (!ar5416SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) {
160 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip did not wakeup\n",
161 __func__);
162 FAIL(HAL_EIO);
166 * Map public channel to private.
168 ichan = ath_hal_checkchannel(ah, chan);
169 if (ichan == AH_NULL) {
170 HALDEBUG(ah, HAL_DEBUG_ANY,
171 "%s: invalid channel %u/0x%x; no mapping\n",
172 __func__, chan->channel, chan->channelFlags);
173 FAIL(HAL_EINVAL);
174 } else {
175 HALDEBUG(ah, HAL_DEBUG_RESET,
176 "%s: Ch=%u Max=%d Min=%d\n",__func__,
177 ichan->channel, ichan->maxTxPower, ichan->minTxPower);
179 switch (opmode) {
180 case HAL_M_STA:
181 case HAL_M_IBSS:
182 case HAL_M_HOSTAP:
183 case HAL_M_MONITOR:
184 break;
185 default:
186 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid operating mode %u\n",
187 __func__, opmode);
188 FAIL(HAL_EINVAL);
189 break;
191 HALASSERT(AH_PRIVATE(ah)->ah_eeversion >= AR_EEPROM_VER14_1);
193 /* XXX Turn on fast channel change for 5416 */
195 * Preserve the bmiss rssi threshold and count threshold
196 * across resets
198 rssiThrReg = OS_REG_READ(ah, AR_RSSI_THR);
199 /* If reg is zero, first time thru set to default val */
200 if (rssiThrReg == 0)
201 rssiThrReg = INIT_RSSI_THR;
204 * Preserve the antenna on a channel change
206 saveDefAntenna = OS_REG_READ(ah, AR_DEF_ANTENNA);
207 if (saveDefAntenna == 0) /* XXX magic constants */
208 saveDefAntenna = 1;
210 /* Save hardware flag before chip reset clears the register */
211 macStaId1 = OS_REG_READ(ah, AR_STA_ID1) &
212 (AR_STA_ID1_BASE_RATE_11B | AR_STA_ID1_USE_DEFANT);
214 /* Save led state from pci config register */
215 saveLedState = OS_REG_READ(ah, AR_MAC_LED) &
216 (AR_MAC_LED_ASSOC | AR_MAC_LED_MODE |
217 AR_MAC_LED_BLINK_THRESH_SEL | AR_MAC_LED_BLINK_SLOW);
218 softLedCfg = OS_REG_READ(ah, AR_GPIO_INTR_OUT);
221 * Adjust gain parameters before reset if
222 * there's an outstanding gain updated.
224 (void) ar5416GetRfgain(ah);
226 if (!ar5416ChipReset(ah, chan)) {
227 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__);
228 FAIL(HAL_EIO);
231 /* Restore bmiss rssi & count thresholds */
232 OS_REG_WRITE(ah, AR_RSSI_THR, rssiThrReg);
234 /* Setup the indices for the next set of register array writes */
235 /* XXX Ignore 11n dynamic mode on the AR5416 for the moment */
236 switch (chan->channelFlags & CHANNEL_ALL) {
237 case CHANNEL_A:
238 case CHANNEL_A_HT20:
239 modesIndex = 1;
240 freqIndex = 1;
241 break;
242 case CHANNEL_T:
243 case CHANNEL_A_HT40PLUS:
244 case CHANNEL_A_HT40MINUS:
245 modesIndex = 2;
246 freqIndex = 1;
247 break;
248 case CHANNEL_PUREG:
249 case CHANNEL_G_HT20:
250 case CHANNEL_B: /* treat as channel G , no B mode suport in owl */
251 modesIndex = 4;
252 freqIndex = 2;
253 break;
254 case CHANNEL_G_HT40PLUS:
255 case CHANNEL_G_HT40MINUS:
256 modesIndex = 3;
257 freqIndex = 2;
258 break;
259 case CHANNEL_108G:
260 modesIndex = 5;
261 freqIndex = 2;
262 break;
263 default:
264 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n",
265 __func__, chan->channelFlags);
266 FAIL(HAL_EINVAL);
269 OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__);
271 /* Set correct Baseband to analog shift setting to access analog chips. */
272 OS_REG_WRITE(ah, AR_PHY(0), 0x00000007);
275 * Write addac shifts
277 OS_REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_EXTERNAL_RADIO);
278 #if 0
279 /* NB: only required for Sowl */
280 ar5416EepromSetAddac(ah, ichan);
281 #endif
282 regWrites = ath_hal_ini_write(ah, &AH5416(ah)->ah_ini_addac, 1,
283 regWrites);
284 OS_REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_INTERNAL_ADDAC);
286 /* XXX Merlin ini fixups */
287 /* XXX Merlin 100us delay for shift registers */
288 regWrites = ath_hal_ini_write(ah, &ahp->ah_ini_modes, modesIndex,
289 regWrites);
290 #ifdef AH_SUPPORT_AR9280
291 if (AR_SREV_MERLIN_20_OR_LATER(ah)) {
292 regWrites = ath_hal_ini_write(ah, &AH9280(ah)->ah_ini_rxgain,
293 modesIndex, regWrites);
294 regWrites = ath_hal_ini_write(ah, &AH9280(ah)->ah_ini_txgain,
295 modesIndex, regWrites);
297 #endif
298 /* XXX Merlin 100us delay for shift registers */
299 regWrites = ath_hal_ini_write(ah, &ahp->ah_ini_common, 1, regWrites);
300 /* Setup 11n MAC/Phy mode registers */
301 ar5416Set11nRegs(ah,chan);
302 /* XXX updated regWrites? */
303 ahp->ah_rfHal->writeRegs(ah, modesIndex, freqIndex, regWrites);
304 #ifdef AH_SUPPORT_AR9280
305 if (AR_SREV_MERLIN_20(ah) && IS_5GHZ_FAST_CLOCK_EN(ah, chan)) {
306 /* 5GHz channels w/ Fast Clock use different modal values */
307 regWrites = ath_hal_ini_write(ah, &AH9280(ah)->ah_ini_xmodes,
308 modesIndex, regWrites);
310 #endif
312 OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__);
314 HALDEBUG(ah, HAL_DEBUG_RESET, ">>>2 %s: AR_PHY_DAG_CTRLCCK=0x%x\n",
315 __func__, OS_REG_READ(ah,AR_PHY_DAG_CTRLCCK));
316 HALDEBUG(ah, HAL_DEBUG_RESET, ">>>2 %s: AR_PHY_ADC_CTL=0x%x\n",
317 __func__, OS_REG_READ(ah,AR_PHY_ADC_CTL));
319 /* Set the mute mask to the correct default */
320 if (AH_PRIVATE(ah)->ah_phyRev >= AR_PHY_CHIP_ID_REV_2)
321 OS_REG_WRITE(ah, AR_SEQ_MASK, 0x0000000F);
323 if (AH_PRIVATE(ah)->ah_phyRev >= AR_PHY_CHIP_ID_REV_3) {
324 /* Clear reg to alllow RX_CLEAR line debug */
325 OS_REG_WRITE(ah, AR_PHY_BLUETOOTH, 0);
327 if (AH_PRIVATE(ah)->ah_phyRev >= AR_PHY_CHIP_ID_REV_4) {
328 #ifdef notyet
329 /* Enable burst prefetch for the data queues */
330 OS_REG_RMW_FIELD(ah, AR_D_FPCTL, ... );
331 /* Enable double-buffering */
332 OS_REG_CLR_BIT(ah, AR_TXCFG, AR_TXCFG_DBL_BUF_DIS);
333 #endif
336 /* Set ADC/DAC select values */
337 OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0e);
339 if (AH5416(ah)->ah_rx_chainmask == 0x5 ||
340 AH5416(ah)->ah_tx_chainmask == 0x5)
341 OS_REG_WRITE(ah, AR_PHY_ANALOG_SWAP, AR_PHY_SWAP_ALT_CHAIN);
342 /* Setup Chain Masks */
343 OS_REG_WRITE(ah, AR_PHY_RX_CHAINMASK, AH5416(ah)->ah_rx_chainmask);
344 OS_REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, AH5416(ah)->ah_rx_chainmask);
345 OS_REG_WRITE(ah, AR_SELFGEN_MASK, AH5416(ah)->ah_tx_chainmask);
347 /* Setup the transmit power values. */
348 if (!ar5416SetTransmitPower(ah, ichan, rfXpdGain)) {
349 HALDEBUG(ah, HAL_DEBUG_ANY,
350 "%s: error init'ing transmit power\n", __func__);
351 FAIL(HAL_EIO);
354 /* Write the analog registers */
355 if (!ahp->ah_rfHal->setRfRegs(ah, ichan, freqIndex, rfXpdGain)) {
356 HALDEBUG(ah, HAL_DEBUG_ANY,
357 "%s: ar5212SetRfRegs failed\n", __func__);
358 FAIL(HAL_EIO);
361 /* Write delta slope for OFDM enabled modes (A, G, Turbo) */
362 if (IS_CHAN_OFDM(chan)|| IS_CHAN_HT(chan))
363 ar5416SetDeltaSlope(ah, ichan);
365 #ifdef AH_SUPPORT_AR9280
366 if (AR_SREV_MERLIN_10_OR_LATER(ah))
367 ar9280SpurMitigate(ah, ichan);
368 else
369 #endif
370 ar5416SpurMitigate(ah, ichan);
372 /* Setup board specific options for EEPROM version 3 */
373 if (!ar5416SetBoardValues(ah, ichan)) {
374 HALDEBUG(ah, HAL_DEBUG_ANY,
375 "%s: error setting board options\n", __func__);
376 FAIL(HAL_EIO);
379 OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__);
381 OS_REG_WRITE(ah, AR_STA_ID0, LE_READ_4(ahp->ah_macaddr));
382 OS_REG_WRITE(ah, AR_STA_ID1, LE_READ_2(ahp->ah_macaddr + 4)
383 | macStaId1
384 | AR_STA_ID1_RTS_USE_DEF
385 | ahp->ah_staId1Defaults
387 ar5212SetOperatingMode(ah, opmode);
389 /* Set Venice BSSID mask according to current state */
390 OS_REG_WRITE(ah, AR_BSSMSKL, LE_READ_4(ahp->ah_bssidmask));
391 OS_REG_WRITE(ah, AR_BSSMSKU, LE_READ_2(ahp->ah_bssidmask + 4));
393 /* Restore previous led state */
394 OS_REG_WRITE(ah, AR_MAC_LED, OS_REG_READ(ah, AR_MAC_LED) | saveLedState);
395 /* Restore soft Led state to GPIO */
396 OS_REG_WRITE(ah, AR_GPIO_INTR_OUT, softLedCfg);
398 /* Restore previous antenna */
399 OS_REG_WRITE(ah, AR_DEF_ANTENNA, saveDefAntenna);
401 /* then our BSSID */
402 OS_REG_WRITE(ah, AR_BSS_ID0, LE_READ_4(ahp->ah_bssid));
403 OS_REG_WRITE(ah, AR_BSS_ID1, LE_READ_2(ahp->ah_bssid + 4));
405 /* Restore bmiss rssi & count thresholds */
406 OS_REG_WRITE(ah, AR_RSSI_THR, ahp->ah_rssiThr);
408 OS_REG_WRITE(ah, AR_ISR, ~0); /* cleared on write */
410 if (!ar5212SetChannel(ah, ichan))
411 FAIL(HAL_EIO);
413 OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__);
415 /* Set 1:1 QCU to DCU mapping for all queues */
416 for (i = 0; i < AR_NUM_DCU; i++)
417 OS_REG_WRITE(ah, AR_DQCUMASK(i), 1 << i);
419 ahp->ah_intrTxqs = 0;
420 for (i = 0; i < AH_PRIVATE(ah)->ah_caps.halTotalQueues; i++)
421 ar5212ResetTxQueue(ah, i);
423 ar5416InitIMR(ah, opmode);
424 ar5212SetCoverageClass(ah, AH_PRIVATE(ah)->ah_coverageClass, 1);
425 ar5416InitQoS(ah);
426 ar5416InitUserSettings(ah);
429 * disable seq number generation in hw
431 OS_REG_WRITE(ah, AR_STA_ID1,
432 OS_REG_READ(ah, AR_STA_ID1) | AR_STA_ID1_PRESERVE_SEQNUM);
434 ar5416InitDMA(ah);
437 * program OBS bus to see MAC interrupts
439 OS_REG_WRITE(ah, AR_OBS, 8);
441 #ifdef AR5416_INT_MITIGATION
442 OS_REG_WRITE(ah, AR_MIRT, 0);
443 OS_REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_LAST, 500);
444 OS_REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_FIRST, 2000);
445 #endif
447 ar5416InitBB(ah, chan);
449 /* Setup compression registers */
450 ar5212SetCompRegs(ah); /* XXX not needed? */
453 * 5416 baseband will check the per rate power table
454 * and select the lower of the two
456 ackTpcPow = 63;
457 ctsTpcPow = 63;
458 chirpTpcPow = 63;
459 powerVal = SM(ackTpcPow, AR_TPC_ACK) |
460 SM(ctsTpcPow, AR_TPC_CTS) |
461 SM(chirpTpcPow, AR_TPC_CHIRP);
462 OS_REG_WRITE(ah, AR_TPC, powerVal);
464 if (!ar5416InitCal(ah, chan))
465 FAIL(HAL_ESELFTEST);
467 AH_PRIVATE(ah)->ah_opmode = opmode; /* record operating mode */
469 if (bChannelChange) {
470 if (!(ichan->privFlags & CHANNEL_DFS))
471 ichan->privFlags &= ~CHANNEL_INTERFERENCE;
472 chan->channelFlags = ichan->channelFlags;
473 chan->privFlags = ichan->privFlags;
474 chan->maxRegTxPower = ichan->maxRegTxPower;
475 chan->maxTxPower = ichan->maxTxPower;
476 chan->minTxPower = ichan->minTxPower;
479 HALDEBUG(ah, HAL_DEBUG_RESET, "%s: done\n", __func__);
481 OS_MARK(ah, AH_MARK_RESET_DONE, 0);
483 return AH_TRUE;
484 bad:
485 OS_MARK(ah, AH_MARK_RESET_DONE, ecode);
486 if (*status)
487 *status = ecode;
488 return AH_FALSE;
489 #undef FAIL
490 #undef N
493 #if 0
495 * This channel change evaluates whether the selected hardware can
496 * perform a synthesizer-only channel change (no reset). If the
497 * TX is not stopped, or the RFBus cannot be granted in the given
498 * time, the function returns false as a reset is necessary
500 HAL_BOOL
501 ar5416ChannelChange(struct ath_hal *ah, HAL_CHANNEL *chan)
503 uint32_t ulCount;
504 uint32_t data, synthDelay, qnum;
505 uint16_t rfXpdGain[4];
506 struct ath_hal_5212 *ahp = AH5212(ah);
507 HAL_CHANNEL_INTERNAL *ichan;
510 * Map public channel to private.
512 ichan = ath_hal_checkchannel(ah, chan);
514 /* TX must be stopped or RF Bus grant will not work */
515 for (qnum = 0; qnum < AH_PRIVATE(ah)->ah_caps.halTotalQueues; qnum++) {
516 if (ar5212NumTxPending(ah, qnum)) {
517 HALDEBUG(ah, HAL_DEBUG_ANY,
518 "%s: frames pending on queue %d\n", __func__, qnum);
519 return AH_FALSE;
524 * Kill last Baseband Rx Frame - Request analog bus grant
526 OS_REG_WRITE(ah, AR_PHY_RFBUS_REQ, AR_PHY_RFBUS_REQ_REQUEST);
527 if (!ath_hal_wait(ah, AR_PHY_RFBUS_GNT, AR_PHY_RFBUS_GRANT_EN, AR_PHY_RFBUS_GRANT_EN)) {
528 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: could not kill baseband rx\n",
529 __func__);
530 return AH_FALSE;
533 ar5416Set11nRegs(ah, chan); /* NB: setup 5416-specific regs */
535 /* Change the synth */
536 if (!ar5212SetChannel(ah, ichan))
537 return AH_FALSE;
539 /* Setup the transmit power values. */
540 if (!ar5416SetTransmitPower(ah, ichan, rfXpdGain)) {
541 HALDEBUG(ah, HAL_DEBUG_ANY,
542 "%s: error init'ing transmit power\n", __func__);
543 return AH_FALSE;
547 * Wait for the frequency synth to settle (synth goes on
548 * via PHY_ACTIVE_EN). Read the phy active delay register.
549 * Value is in 100ns increments.
551 data = OS_REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY;
552 if (IS_CHAN_CCK(ichan)) {
553 synthDelay = (4 * data) / 22;
554 } else {
555 synthDelay = data / 10;
558 OS_DELAY(synthDelay + BASE_ACTIVATE_DELAY);
560 /* Release the RFBus Grant */
561 OS_REG_WRITE(ah, AR_PHY_RFBUS_REQ, 0);
563 /* Write delta slope for OFDM enabled modes (A, G, Turbo) */
564 if (IS_CHAN_OFDM(ichan)|| IS_CHAN_HT(chan)) {
565 if (ahp->ah_eeprom.ee_version >= AR_EEPROM_VER5_3 &&
566 !IS_CHAN_B(chan))
567 ar5212SetSpurMitigation(ah, ichan);
568 ar5416SetDeltaSlope(ah, ichan);
571 /* XXX spur mitigation for Melin */
573 /* Copy over internal channel flags to public hal channel */
575 if (!(ichan->privFlags & CHANNEL_DFS))
576 ichan->privFlags &= ~CHANNEL_INTERFERENCE;
577 chan->channelFlags = ichan->channelFlags;
578 chan->privFlags = ichan->privFlags;
579 chan->maxRegTxPower = ichan->maxRegTxPower;
580 chan->maxTxPower = ichan->maxTxPower;
581 chan->minTxPower = ichan->minTxPower;
582 AH_PRIVATE(ah)->ah_curchan->ah_channel_time=0;
583 AH_PRIVATE(ah)->ah_curchan->ah_tsf_last = ar5212GetTsf64(ah);
584 ar5212TxEnable(ah,AH_TRUE);
585 return AH_TRUE;
587 #endif
589 static void
590 ar5416InitDMA(struct ath_hal *ah)
594 * set AHB_MODE not to do cacheline prefetches
596 OS_REG_SET_BIT(ah, AR_AHB_MODE, AR_AHB_PREFETCH_RD_EN);
599 * let mac dma reads be in 128 byte chunks
601 OS_REG_WRITE(ah, AR_TXCFG,
602 (OS_REG_READ(ah, AR_TXCFG) & ~AR_TXCFG_DMASZ_MASK) | AR_TXCFG_DMASZ_128B);
605 * let mac dma writes be in 128 byte chunks
607 OS_REG_WRITE(ah, AR_RXCFG,
608 (OS_REG_READ(ah, AR_RXCFG) & ~AR_RXCFG_DMASZ_MASK) | AR_RXCFG_DMASZ_128B);
610 /* XXX restore TX trigger level */
613 * Setup receive FIFO threshold to hold off TX activities
615 OS_REG_WRITE(ah, AR_RXFIFO_CFG, 0x200);
618 * reduce the number of usable entries in PCU TXBUF to avoid
619 * wrap around.
621 OS_REG_WRITE(ah, AR_PCU_TXBUF_CTRL, AR_PCU_TXBUF_CTRL_USABLE_SIZE);
624 static void
625 ar5416InitBB(struct ath_hal *ah, HAL_CHANNEL *chan)
627 uint32_t synthDelay;
630 * Wait for the frequency synth to settle (synth goes on
631 * via AR_PHY_ACTIVE_EN). Read the phy active delay register.
632 * Value is in 100ns increments.
634 synthDelay = OS_REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY;
635 if (IS_CHAN_CCK(chan)) {
636 synthDelay = (4 * synthDelay) / 22;
637 } else {
638 synthDelay /= 10;
641 /* Turn on PLL on 5416 */
642 HALDEBUG(ah, HAL_DEBUG_RESET, "%s %s channel\n",
643 __func__, IS_CHAN_5GHZ(chan) ? "5GHz" : "2GHz");
644 ar5416InitPLL(ah, chan);
646 /* Activate the PHY (includes baseband activate and synthesizer on) */
647 OS_REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
650 * If the AP starts the calibration before the base band timeout
651 * completes we could get rx_clear false triggering, to avoid this
652 * we add delay an extra BASE_ACTIVATE_DELAY usecs to ensure this
653 * does not happen.
655 if (IS_CHAN_HALF_RATE(AH_PRIVATE(ah)->ah_curchan)) {
656 OS_DELAY((synthDelay << 1) + BASE_ACTIVATE_DELAY);
657 } else if (IS_CHAN_QUARTER_RATE(AH_PRIVATE(ah)->ah_curchan)) {
658 OS_DELAY((synthDelay << 2) + BASE_ACTIVATE_DELAY);
659 } else {
660 OS_DELAY(synthDelay + BASE_ACTIVATE_DELAY);
664 static void
665 ar5416InitIMR(struct ath_hal *ah, HAL_OPMODE opmode)
667 struct ath_hal_5212 *ahp = AH5212(ah);
670 * Setup interrupt handling. Note that ar5212ResetTxQueue
671 * manipulates the secondary IMR's as queues are enabled
672 * and disabled. This is done with RMW ops to insure the
673 * settings we make here are preserved.
675 ahp->ah_maskReg = AR_IMR_TXERR | AR_IMR_TXURN
676 | AR_IMR_RXERR | AR_IMR_RXORN
677 | AR_IMR_BCNMISC;
679 #ifdef AR5416_INT_MITIGATION
680 ahp->ah_maskReg |= AR_IMR_TXINTM | AR_IMR_RXINTM
681 | AR_IMR_TXMINTR | AR_IMR_RXMINTR;
682 #else
683 ahp->ah_maskReg |= AR_IMR_TXOK | AR_IMR_RXOK;
684 #endif
685 if (opmode == HAL_M_HOSTAP)
686 ahp->ah_maskReg |= AR_IMR_MIB;
687 OS_REG_WRITE(ah, AR_IMR, ahp->ah_maskReg);
688 /* Enable bus errors that are OR'd to set the HIUERR bit */
690 #if 0
691 OS_REG_WRITE(ah, AR_IMR_S2,
692 OS_REG_READ(ah, AR_IMR_S2) | AR_IMR_S2_GTT | AR_IMR_S2_CST);
693 #endif
696 static void
697 ar5416InitQoS(struct ath_hal *ah)
699 /* QoS support */
700 OS_REG_WRITE(ah, AR_QOS_CONTROL, 0x100aa); /* XXX magic */
701 OS_REG_WRITE(ah, AR_QOS_SELECT, 0x3210); /* XXX magic */
703 /* Turn on NOACK Support for QoS packets */
704 OS_REG_WRITE(ah, AR_NOACK,
705 SM(2, AR_NOACK_2BIT_VALUE) |
706 SM(5, AR_NOACK_BIT_OFFSET) |
707 SM(0, AR_NOACK_BYTE_OFFSET));
710 * initialize TXOP for all TIDs
712 OS_REG_WRITE(ah, AR_TXOP_X, AR_TXOP_X_VAL);
713 OS_REG_WRITE(ah, AR_TXOP_0_3, 0xFFFFFFFF);
714 OS_REG_WRITE(ah, AR_TXOP_4_7, 0xFFFFFFFF);
715 OS_REG_WRITE(ah, AR_TXOP_8_11, 0xFFFFFFFF);
716 OS_REG_WRITE(ah, AR_TXOP_12_15, 0xFFFFFFFF);
719 static void
720 ar5416InitUserSettings(struct ath_hal *ah)
722 struct ath_hal_5212 *ahp = AH5212(ah);
724 /* Restore user-specified settings */
725 if (ahp->ah_miscMode != 0)
726 OS_REG_WRITE(ah, AR_MISC_MODE, ahp->ah_miscMode);
727 if (ahp->ah_sifstime != (u_int) -1)
728 ar5212SetSifsTime(ah, ahp->ah_sifstime);
729 if (ahp->ah_slottime != (u_int) -1)
730 ar5212SetSlotTime(ah, ahp->ah_slottime);
731 if (ahp->ah_acktimeout != (u_int) -1)
732 ar5212SetAckTimeout(ah, ahp->ah_acktimeout);
733 if (ahp->ah_ctstimeout != (u_int) -1)
734 ar5212SetCTSTimeout(ah, ahp->ah_ctstimeout);
735 if (AH_PRIVATE(ah)->ah_diagreg != 0)
736 OS_REG_WRITE(ah, AR_DIAG_SW, AH_PRIVATE(ah)->ah_diagreg);
737 #if 0 /* XXX Todo */
738 if (ahp->ah_globaltxtimeout != (u_int) -1)
739 ar5416SetGlobalTxTimeout(ah, ahp->ah_globaltxtimeout);
740 #endif
744 * Places the hardware into reset and then pulls it out of reset
746 HAL_BOOL
747 ar5416ChipReset(struct ath_hal *ah, HAL_CHANNEL *chan)
749 uint32_t rfMode = 0;
751 OS_MARK(ah, AH_MARK_CHIPRESET, chan ? chan->channel : 0);
753 * Warm reset is optimistic.
755 if (AR_SREV_MERLIN_20_OR_LATER(ah) &&
756 ath_hal_eepromGetFlag(ah, AR_EEP_OL_PWRCTRL)) {
757 if (!ar5416SetResetReg(ah, HAL_RESET_POWER_ON))
758 return AH_FALSE;
759 } else {
760 if (!ar5416SetResetReg(ah, HAL_RESET_WARM))
761 return AH_FALSE;
764 /* Bring out of sleep mode (AGAIN) */
765 if (!ar5416SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE))
766 return AH_FALSE;
768 ar5416InitPLL(ah, chan);
771 * Perform warm reset before the mode/PLL/turbo registers
772 * are changed in order to deactivate the radio. Mode changes
773 * with an active radio can result in corrupted shifts to the
774 * radio device.
776 if (chan != AH_NULL) {
777 /* treat channel B as channel G , no B mode suport in owl */
778 rfMode |= (IS_CHAN_G(chan) || IS_CHAN_B(chan)) ?
779 AR_PHY_MODE_DYNAMIC : AR_PHY_MODE_OFDM;
780 if (AR_SREV_MERLIN_20(ah) && IS_5GHZ_FAST_CLOCK_EN(ah, chan)) {
781 /* phy mode bits for 5GHz channels require Fast Clock */
782 rfMode |= AR_PHY_MODE_DYNAMIC
783 | AR_PHY_MODE_DYN_CCK_DISABLE;
784 } else if (!AR_SREV_MERLIN_10_OR_LATER(ah)) {
785 rfMode |= (IS_CHAN_5GHZ(chan)) ?
786 AR_PHY_MODE_RF5GHZ : AR_PHY_MODE_RF2GHZ;
788 OS_REG_WRITE(ah, AR_PHY_MODE, rfMode);
790 return AH_TRUE;
794 * Determine if calibration is supported by device and channel flags
796 /* Disabled OS_INLINE due to GCC 4.6 compaints
797 * Jason McMullan, 2011-9-26
799 static /* OS_INLINE */ HAL_BOOL
800 ar5416IsCalSupp(struct ath_hal *ah, HAL_CHANNEL *chan, HAL_CAL_TYPE calType)
802 struct ath_hal_5416 *ahp = AH5416(ah);
804 switch (calType & ahp->ah_suppCals) {
805 case IQ_MISMATCH_CAL:
806 /* Run IQ Mismatch for non-CCK only */
807 return !IS_CHAN_B(chan);
808 case ADC_GAIN_CAL:
809 case ADC_DC_CAL:
810 /* Run ADC Gain Cal for non-CCK & non 2GHz-HT20 only */
811 return !IS_CHAN_B(chan) &&
812 !(IS_CHAN_2GHZ(chan) && IS_CHAN_HT20(chan));
814 return AH_FALSE;
818 * Setup HW to collect samples used for current cal
820 static void
821 ar5416SetupMeasurement(struct ath_hal *ah, HAL_CAL_LIST *currCal)
823 /* Start calibration w/ 2^(INIT_IQCAL_LOG_COUNT_MAX+1) samples */
824 OS_REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4,
825 AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX,
826 currCal->calData->calCountMax);
828 /* Select calibration to run */
829 switch (currCal->calData->calType) {
830 case IQ_MISMATCH_CAL:
831 OS_REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ);
832 HALDEBUG(ah, HAL_DEBUG_PERCAL,
833 "%s: start IQ Mismatch calibration\n", __func__);
834 break;
835 case ADC_GAIN_CAL:
836 OS_REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_GAIN);
837 HALDEBUG(ah, HAL_DEBUG_PERCAL,
838 "%s: start ADC Gain calibration\n", __func__);
839 break;
840 case ADC_DC_CAL:
841 OS_REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_PER);
842 HALDEBUG(ah, HAL_DEBUG_PERCAL,
843 "%s: start ADC DC calibration\n", __func__);
844 break;
845 case ADC_DC_INIT_CAL:
846 OS_REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_INIT);
847 HALDEBUG(ah, HAL_DEBUG_PERCAL,
848 "%s: start Init ADC DC calibration\n", __func__);
849 break;
851 /* Kick-off cal */
852 OS_REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4, AR_PHY_TIMING_CTRL4_DO_CAL);
856 * Initialize shared data structures and prepare a cal to be run.
858 static void
859 ar5416ResetMeasurement(struct ath_hal *ah, HAL_CAL_LIST *currCal)
861 struct ath_hal_5416 *ahp = AH5416(ah);
863 /* Reset data structures shared between different calibrations */
864 OS_MEMZERO(ahp->ah_caldata, sizeof(ahp->ah_caldata));
865 ahp->ah_calSamples = 0;
867 /* Setup HW for new calibration */
868 ar5416SetupMeasurement(ah, currCal);
870 /* Change SW state to RUNNING for this calibration */
871 currCal->calState = CAL_RUNNING;
874 #if 0
876 * Run non-periodic calibrations.
878 static HAL_BOOL
879 ar5416RunInitCals(struct ath_hal *ah, int init_cal_count)
881 struct ath_hal_5416 *ahp = AH5416(ah);
882 HAL_CHANNEL_INTERNAL ichan; /* XXX bogus */
883 HAL_CAL_LIST *curCal = ahp->ah_cal_curr;
884 HAL_BOOL isCalDone;
885 int i;
887 if (curCal == AH_NULL)
888 return AH_FALSE;
890 ichan.calValid = 0;
891 for (i = 0; i < init_cal_count; i++) {
892 /* Reset this Cal */
893 ar5416ResetMeasurement(ah, curCal);
894 /* Poll for offset calibration complete */
895 if (!ath_hal_wait(ah, AR_PHY_TIMING_CTRL4, AR_PHY_TIMING_CTRL4_DO_CAL, 0)) {
896 HALDEBUG(ah, HAL_DEBUG_ANY,
897 "%s: Cal %d failed to finish in 100ms.\n",
898 __func__, curCal->calData->calType);
899 /* Re-initialize list pointers for periodic cals */
900 ahp->ah_cal_list = ahp->ah_cal_last =
901 ahp->ah_cal_curr = AH_NULL;
902 return AH_FALSE;
904 /* Run this cal */
905 ar5416DoCalibration(ah, &ichan, ahp->ah_rxchainmask,
906 curCal, &isCalDone);
907 if (!isCalDone)
908 HALDEBUG(ah, HAL_DEBUG_ANY,
909 "%s: init cal %d did not complete.\n",
910 __func__, curCal->calData->calType);
911 if (curCal->calNext != AH_NULL)
912 curCal = curCal->calNext;
915 /* Re-initialize list pointers for periodic cals */
916 ahp->ah_cal_list = ahp->ah_cal_last =
917 ahp->ah_cal_curr = AH_NULL;
918 return AH_TRUE;
920 #endif
923 * Initialize Calibration infrastructure.
925 static HAL_BOOL
926 ar5416InitCal(struct ath_hal *ah, HAL_CHANNEL *chan)
928 struct ath_hal_5416 *ahp = AH5416(ah);
929 HAL_CHANNEL_INTERNAL *ichan;
931 ichan = ath_hal_checkchannel(ah, chan);
932 HALASSERT(ichan != AH_NULL);
934 /* Calibrate the AGC */
935 OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL);
937 /* Poll for offset calibration complete */
938 if (!ath_hal_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, 0)) {
939 HALDEBUG(ah, HAL_DEBUG_ANY,
940 "%s: offset calibration did not complete in 1ms; "
941 "noisy environment?\n", __func__);
942 return AH_FALSE;
946 * Do NF calibration after DC offset and other CALs.
947 * Per system engineers, noise floor value can sometimes be 20 dB
948 * higher than normal value if DC offset and noise floor cal are
949 * triggered at the same time.
951 OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
953 /* Initialize list pointers */
954 ahp->ah_cal_list = ahp->ah_cal_last =
955 ahp->ah_cal_curr = AH_NULL;
958 * Enable IQ, ADC Gain, ADC DC Offset Cals
960 if (AR_SREV_SOWL_10_OR_LATER(ah)) {
961 /* Setup all non-periodic, init time only calibrations */
962 /* XXX: Init DC Offset not working yet */
963 #if 0
964 if (ar5416IsCalSupp(ah, chan, ADC_DC_INIT_CAL)) {
965 INIT_CAL(&ahp->ah_adcDcCalInitData);
966 INSERT_CAL(ahp, &ahp->ah_adcDcCalInitData);
968 /* Initialize current pointer to first element in list */
969 ahp->ah_cal_curr = ahp->ah_cal_list;
971 if (ahp->ah_cal_curr != AH_NULL && !ar5416RunInitCals(ah, 0))
972 return AH_FALSE;
973 #endif
976 /* If Cals are supported, add them to list via INIT/INSERT_CAL */
977 if (ar5416IsCalSupp(ah, chan, ADC_GAIN_CAL)) {
978 INIT_CAL(&ahp->ah_adcGainCalData);
979 INSERT_CAL(ahp, &ahp->ah_adcGainCalData);
980 HALDEBUG(ah, HAL_DEBUG_PERCAL,
981 "%s: enable ADC Gain Calibration.\n", __func__);
983 if (ar5416IsCalSupp(ah, chan, ADC_DC_CAL)) {
984 INIT_CAL(&ahp->ah_adcDcCalData);
985 INSERT_CAL(ahp, &ahp->ah_adcDcCalData);
986 HALDEBUG(ah, HAL_DEBUG_PERCAL,
987 "%s: enable ADC DC Calibration.\n", __func__);
989 if (ar5416IsCalSupp(ah, chan, IQ_MISMATCH_CAL)) {
990 INIT_CAL(&ahp->ah_iqCalData);
991 INSERT_CAL(ahp, &ahp->ah_iqCalData);
992 HALDEBUG(ah, HAL_DEBUG_PERCAL,
993 "%s: enable IQ Calibration.\n", __func__);
995 /* Initialize current pointer to first element in list */
996 ahp->ah_cal_curr = ahp->ah_cal_list;
998 /* Kick off measurements for the first cal */
999 if (ahp->ah_cal_curr != AH_NULL)
1000 ar5416ResetMeasurement(ah, ahp->ah_cal_curr);
1002 /* Mark all calibrations on this channel as being invalid */
1003 ichan->calValid = 0;
1005 return AH_TRUE;
1009 * Entry point for upper layers to restart current cal.
1010 * Reset the calibration valid bit in channel.
1012 void
1013 ar5416ResetCalValid(struct ath_hal *ah, HAL_CHANNEL *chan, HAL_BOOL *isCalDone)
1015 struct ath_hal_5416 *ahp = AH5416(ah);
1016 HAL_CHANNEL_INTERNAL *ichan = ath_hal_checkchannel(ah, chan);
1017 HAL_CAL_LIST *currCal = ahp->ah_cal_curr;
1019 *isCalDone = AH_TRUE;
1021 if (!AR_SREV_SOWL_10_OR_LATER(ah))
1022 return;
1023 if (currCal == AH_NULL)
1024 return;
1025 if (ichan == AH_NULL) {
1026 HALDEBUG(ah, HAL_DEBUG_ANY,
1027 "%s: invalid channel %u/0x%x; no mapping\n",
1028 __func__, chan->channel, chan->channelFlags);
1029 return;
1032 * Expected that this calibration has run before, post-reset.
1033 * Current state should be done
1035 if (currCal->calState != CAL_DONE) {
1036 HALDEBUG(ah, HAL_DEBUG_ANY,
1037 "%s: Calibration state incorrect, %d\n",
1038 __func__, currCal->calState);
1039 return;
1042 /* Verify Cal is supported on this channel */
1043 if (!ar5416IsCalSupp(ah, chan, currCal->calData->calType))
1044 return;
1046 HALDEBUG(ah, HAL_DEBUG_PERCAL,
1047 "%s: Resetting Cal %d state for channel %u/0x%x\n",
1048 __func__, currCal->calData->calType, chan->channel,
1049 chan->channelFlags);
1051 /* Disable cal validity in channel */
1052 ichan->calValid &= ~currCal->calData->calType;
1053 currCal->calState = CAL_WAITING;
1055 /* Indicate to upper layers that we need polling for Howl/Sowl */
1056 *isCalDone = AH_FALSE;
1060 * Recalibrate the lower PHY chips to account for temperature/environment
1061 * changes.
1063 static void
1064 ar5416DoCalibration(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *ichan,
1065 uint8_t rxchainmask, HAL_CAL_LIST *currCal, HAL_BOOL *isCalDone)
1067 struct ath_hal_5416 *ahp = AH5416(ah);
1069 /* Cal is assumed not done until explicitly set below */
1070 *isCalDone = AH_FALSE;
1072 HALDEBUG(ah, HAL_DEBUG_PERCAL,
1073 "%s: %s Calibration, state %d, calValid 0x%x\n",
1074 __func__, currCal->calData->calName, currCal->calState,
1075 ichan->calValid);
1077 /* Calibration in progress. */
1078 if (currCal->calState == CAL_RUNNING) {
1079 /* Check to see if it has finished. */
1080 if (!(OS_REG_READ(ah, AR_PHY_TIMING_CTRL4) & AR_PHY_TIMING_CTRL4_DO_CAL)) {
1081 HALDEBUG(ah, HAL_DEBUG_PERCAL,
1082 "%s: sample %d of %d finished\n",
1083 __func__, ahp->ah_calSamples,
1084 currCal->calData->calNumSamples);
1086 * Collect measurements for active chains.
1088 currCal->calData->calCollect(ah);
1089 if (++ahp->ah_calSamples >= currCal->calData->calNumSamples) {
1090 int i, numChains = 0;
1091 for (i = 0; i < AR5416_MAX_CHAINS; i++) {
1092 if (rxchainmask & (1 << i))
1093 numChains++;
1096 * Process accumulated data
1098 currCal->calData->calPostProc(ah, numChains);
1100 /* Calibration has finished. */
1101 ichan->calValid |= currCal->calData->calType;
1102 currCal->calState = CAL_DONE;
1103 *isCalDone = AH_TRUE;
1104 } else {
1106 * Set-up to collect of another sub-sample.
1108 ar5416SetupMeasurement(ah, currCal);
1111 } else if (!(ichan->calValid & currCal->calData->calType)) {
1112 /* If current cal is marked invalid in channel, kick it off */
1113 ar5416ResetMeasurement(ah, currCal);
1118 * Internal interface to schedule periodic calibration work.
1120 static HAL_BOOL
1121 _ar5416PerCalibration(struct ath_hal *ah, HAL_CHANNEL *chan,
1122 uint8_t rxchainmask, HAL_BOOL longcal, HAL_BOOL *isCalDone)
1124 struct ath_hal_5416 *ahp = AH5416(ah);
1125 HAL_CAL_LIST *currCal = ahp->ah_cal_curr;
1126 HAL_CHANNEL_INTERNAL *ichan;
1128 OS_MARK(ah, AH_MARK_PERCAL, chan->channel);
1130 *isCalDone = AH_TRUE;
1132 /* Invalid channel check */
1133 ichan = ath_hal_checkchannel(ah, chan);
1134 if (ichan == AH_NULL) {
1135 HALDEBUG(ah, HAL_DEBUG_ANY,
1136 "%s: invalid channel %u/0x%x; no mapping\n",
1137 __func__, chan->channel, chan->channelFlags);
1138 return AH_FALSE;
1142 * For given calibration:
1143 * 1. Call generic cal routine
1144 * 2. When this cal is done (isCalDone) if we have more cals waiting
1145 * (eg after reset), mask this to upper layers by not propagating
1146 * isCalDone if it is set to TRUE.
1147 * Instead, change isCalDone to FALSE and setup the waiting cal(s)
1148 * to be run.
1150 if (currCal != AH_NULL &&
1151 (currCal->calState == CAL_RUNNING ||
1152 currCal->calState == CAL_WAITING)) {
1153 ar5416DoCalibration(ah, ichan, rxchainmask, currCal, isCalDone);
1154 if (*isCalDone == AH_TRUE) {
1155 ahp->ah_cal_curr = currCal = currCal->calNext;
1156 if (currCal->calState == CAL_WAITING) {
1157 *isCalDone = AH_FALSE;
1158 ar5416ResetMeasurement(ah, currCal);
1163 /* Do NF cal only at longer intervals */
1164 if (longcal) {
1166 * Get the value from the previous NF cal
1167 * and update the history buffer.
1169 ar5416GetNf(ah, ichan);
1172 * Load the NF from history buffer of the current channel.
1173 * NF is slow time-variant, so it is OK to use a
1174 * historical value.
1176 ar5416LoadNF(ah, AH_PRIVATE(ah)->ah_curchan);
1178 /* start NF calibration, without updating BB NF register*/
1179 ar5416StartNFCal(ah);
1181 if ((ichan->channelFlags & CHANNEL_CW_INT) != 0) {
1182 /* report up and clear internal state */
1183 chan->channelFlags |= CHANNEL_CW_INT;
1184 ichan->channelFlags &= ~CHANNEL_CW_INT;
1187 return AH_TRUE;
1191 * Recalibrate the lower PHY chips to account for temperature/environment
1192 * changes.
1194 HAL_BOOL
1195 ar5416PerCalibration(struct ath_hal *ah, HAL_CHANNEL *chan, HAL_BOOL *isIQdone)
1197 struct ath_hal_5416 *ahp = AH5416(ah);
1198 HAL_CAL_LIST *curCal = ahp->ah_cal_curr;
1200 if (curCal != AH_NULL && curCal->calData->calType == IQ_MISMATCH_CAL) {
1201 return _ar5416PerCalibration(ah, chan, ahp->ah_rx_chainmask,
1202 AH_TRUE, isIQdone);
1203 } else {
1204 HAL_BOOL isCalDone;
1206 *isIQdone = AH_FALSE;
1207 return _ar5416PerCalibration(ah, chan, ahp->ah_rx_chainmask,
1208 AH_TRUE, &isCalDone);
1213 * Collect data from HW to later perform IQ Mismatch Calibration
1215 void
1216 ar5416IQCalCollect(struct ath_hal *ah)
1218 struct ath_hal_5416 *ahp = AH5416(ah);
1219 int i;
1222 * Accumulate IQ cal measures for active chains
1224 for (i = 0; i < AR5416_MAX_CHAINS; i++) {
1225 ahp->ah_totalPowerMeasI(i) +=
1226 OS_REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
1227 ahp->ah_totalPowerMeasQ(i) +=
1228 OS_REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
1229 ahp->ah_totalIqCorrMeas(i) += (int32_t)
1230 OS_REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
1231 HALDEBUG(ah, HAL_DEBUG_PERCAL,
1232 "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n",
1233 ahp->ah_calSamples, i, ahp->ah_totalPowerMeasI(i),
1234 ahp->ah_totalPowerMeasQ(i), ahp->ah_totalIqCorrMeas(i));
1239 * Use HW data to do IQ Mismatch Calibration
1241 void
1242 ar5416IQCalibration(struct ath_hal *ah, uint8_t numChains)
1244 struct ath_hal_5416 *ahp = AH5416(ah);
1245 int i;
1247 for (i = 0; i < numChains; i++) {
1248 uint32_t powerMeasI = ahp->ah_totalPowerMeasI(i);
1249 uint32_t powerMeasQ = ahp->ah_totalPowerMeasQ(i);
1250 uint32_t iqCorrMeas = ahp->ah_totalIqCorrMeas(i);
1251 uint32_t qCoffDenom, iCoffDenom;
1252 int iqCorrNeg;
1254 HALDEBUG(ah, HAL_DEBUG_PERCAL,
1255 "Start IQ Cal and Correction for Chain %d\n", i);
1256 HALDEBUG(ah, HAL_DEBUG_PERCAL,
1257 "Orignal: iq_corr_meas = 0x%08x\n", iqCorrMeas);
1259 iqCorrNeg = 0;
1260 /* iqCorrMeas is always negative. */
1261 if (iqCorrMeas > 0x80000000) {
1262 iqCorrMeas = (0xffffffff - iqCorrMeas) + 1;
1263 iqCorrNeg = 1;
1266 HALDEBUG(ah, HAL_DEBUG_PERCAL, " pwr_meas_i = 0x%08x\n",
1267 powerMeasI);
1268 HALDEBUG(ah, HAL_DEBUG_PERCAL, " pwr_meas_q = 0x%08x\n",
1269 powerMeasQ);
1270 HALDEBUG(ah, HAL_DEBUG_PERCAL, " iqCorrNeg is 0x%08x\n",
1271 iqCorrNeg);
1273 iCoffDenom = (powerMeasI/2 + powerMeasQ/2)/ 128;
1274 qCoffDenom = powerMeasQ / 64;
1275 /* Protect against divide-by-0 */
1276 if (powerMeasQ != 0) {
1277 /* IQ corr_meas is already negated if iqcorr_neg == 1 */
1278 int32_t iCoff = iqCorrMeas/iCoffDenom;
1279 int32_t qCoff = powerMeasI/qCoffDenom - 64;
1281 HALDEBUG(ah, HAL_DEBUG_PERCAL, " iCoff = 0x%08x\n",
1282 iCoff);
1283 HALDEBUG(ah, HAL_DEBUG_PERCAL, " qCoff = 0x%08x\n",
1284 qCoff);
1286 /* Negate iCoff if iqCorrNeg == 0 */
1287 iCoff = iCoff & 0x3f;
1288 HALDEBUG(ah, HAL_DEBUG_PERCAL,
1289 "New: iCoff = 0x%08x\n", iCoff);
1291 if (iqCorrNeg == 0x0)
1292 iCoff = 0x40 - iCoff;
1293 if (qCoff > 15)
1294 qCoff = 15;
1295 else if (qCoff <= -16)
1296 qCoff = 16;
1297 HALDEBUG(ah, HAL_DEBUG_PERCAL,
1298 " : iCoff = 0x%x qCoff = 0x%x\n", iCoff, qCoff);
1300 OS_REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4_CHAIN(i),
1301 AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF, iCoff);
1302 OS_REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4_CHAIN(i),
1303 AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF, qCoff);
1304 HALDEBUG(ah, HAL_DEBUG_PERCAL,
1305 "IQ Cal and Correction done for Chain %d\n", i);
1308 OS_REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4,
1309 AR_PHY_TIMING_CTRL4_IQCORR_ENABLE);
1313 * Collect data from HW to later perform ADC Gain Calibration
1315 void
1316 ar5416AdcGainCalCollect(struct ath_hal *ah)
1318 struct ath_hal_5416 *ahp = AH5416(ah);
1319 int i;
1322 * Accumulate ADC Gain cal measures for active chains
1324 for (i = 0; i < AR5416_MAX_CHAINS; i++) {
1325 ahp->ah_totalAdcIOddPhase(i) +=
1326 OS_REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
1327 ahp->ah_totalAdcIEvenPhase(i) +=
1328 OS_REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
1329 ahp->ah_totalAdcQOddPhase(i) +=
1330 OS_REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
1331 ahp->ah_totalAdcQEvenPhase(i) +=
1332 OS_REG_READ(ah, AR_PHY_CAL_MEAS_3(i));
1334 HALDEBUG(ah, HAL_DEBUG_PERCAL,
1335 "%d: Chn %d oddi=0x%08x; eveni=0x%08x; oddq=0x%08x; evenq=0x%08x;\n",
1336 ahp->ah_calSamples, i, ahp->ah_totalAdcIOddPhase(i),
1337 ahp->ah_totalAdcIEvenPhase(i), ahp->ah_totalAdcQOddPhase(i),
1338 ahp->ah_totalAdcQEvenPhase(i));
1343 * Use HW data to do ADC Gain Calibration
1345 void
1346 ar5416AdcGainCalibration(struct ath_hal *ah, uint8_t numChains)
1348 struct ath_hal_5416 *ahp = AH5416(ah);
1349 uint32_t i;
1351 for (i = 0; i < numChains; i++) {
1352 uint32_t iOddMeasOffset = ahp->ah_totalAdcIOddPhase(i);
1353 uint32_t iEvenMeasOffset = ahp->ah_totalAdcIEvenPhase(i);
1354 uint32_t qOddMeasOffset = ahp->ah_totalAdcQOddPhase(i);
1355 uint32_t qEvenMeasOffset = ahp->ah_totalAdcQEvenPhase(i);
1357 HALDEBUG(ah, HAL_DEBUG_PERCAL,
1358 "Start ADC Gain Cal for Chain %d\n", i);
1359 HALDEBUG(ah, HAL_DEBUG_PERCAL,
1360 " pwr_meas_odd_i = 0x%08x\n", iOddMeasOffset);
1361 HALDEBUG(ah, HAL_DEBUG_PERCAL,
1362 " pwr_meas_even_i = 0x%08x\n", iEvenMeasOffset);
1363 HALDEBUG(ah, HAL_DEBUG_PERCAL,
1364 " pwr_meas_odd_q = 0x%08x\n", qOddMeasOffset);
1365 HALDEBUG(ah, HAL_DEBUG_PERCAL,
1366 " pwr_meas_even_q = 0x%08x\n", qEvenMeasOffset);
1368 if (iOddMeasOffset != 0 && qEvenMeasOffset != 0) {
1369 uint32_t iGainMismatch =
1370 ((iEvenMeasOffset*32)/iOddMeasOffset) & 0x3f;
1371 uint32_t qGainMismatch =
1372 ((qOddMeasOffset*32)/qEvenMeasOffset) & 0x3f;
1373 uint32_t val;
1375 HALDEBUG(ah, HAL_DEBUG_PERCAL,
1376 " gain_mismatch_i = 0x%08x\n",
1377 iGainMismatch);
1378 HALDEBUG(ah, HAL_DEBUG_PERCAL,
1379 " gain_mismatch_q = 0x%08x\n",
1380 qGainMismatch);
1382 val = OS_REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i));
1383 val &= 0xfffff000;
1384 val |= (qGainMismatch) | (iGainMismatch << 6);
1385 OS_REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val);
1387 HALDEBUG(ah, HAL_DEBUG_PERCAL,
1388 "ADC Gain Cal done for Chain %d\n", i);
1391 OS_REG_SET_BIT(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0),
1392 AR_PHY_NEW_ADC_GAIN_CORR_ENABLE);
1395 void
1396 ar5416AdcDcCalCollect(struct ath_hal *ah)
1398 struct ath_hal_5416 *ahp = AH5416(ah);
1399 int i;
1401 for (i = 0; i < AR5416_MAX_CHAINS; i++) {
1402 ahp->ah_totalAdcDcOffsetIOddPhase(i) += (int32_t)
1403 OS_REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
1404 ahp->ah_totalAdcDcOffsetIEvenPhase(i) += (int32_t)
1405 OS_REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
1406 ahp->ah_totalAdcDcOffsetQOddPhase(i) += (int32_t)
1407 OS_REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
1408 ahp->ah_totalAdcDcOffsetQEvenPhase(i) += (int32_t)
1409 OS_REG_READ(ah, AR_PHY_CAL_MEAS_3(i));
1411 HALDEBUG(ah, HAL_DEBUG_PERCAL,
1412 "%d: Chn %d oddi=0x%08x; eveni=0x%08x; oddq=0x%08x; evenq=0x%08x;\n",
1413 ahp->ah_calSamples, i,
1414 ahp->ah_totalAdcDcOffsetIOddPhase(i),
1415 ahp->ah_totalAdcDcOffsetIEvenPhase(i),
1416 ahp->ah_totalAdcDcOffsetQOddPhase(i),
1417 ahp->ah_totalAdcDcOffsetQEvenPhase(i));
1421 void
1422 ar5416AdcDcCalibration(struct ath_hal *ah, uint8_t numChains)
1424 struct ath_hal_5416 *ahp = AH5416(ah);
1425 const HAL_PERCAL_DATA *calData = ahp->ah_cal_curr->calData;
1426 uint32_t numSamples;
1427 int i;
1429 numSamples = (1 << (calData->calCountMax + 5)) * calData->calNumSamples;
1430 for (i = 0; i < numChains; i++) {
1431 uint32_t iOddMeasOffset = ahp->ah_totalAdcDcOffsetIOddPhase(i);
1432 uint32_t iEvenMeasOffset = ahp->ah_totalAdcDcOffsetIEvenPhase(i);
1433 int32_t qOddMeasOffset = ahp->ah_totalAdcDcOffsetQOddPhase(i);
1434 int32_t qEvenMeasOffset = ahp->ah_totalAdcDcOffsetQEvenPhase(i);
1435 int32_t qDcMismatch, iDcMismatch;
1436 uint32_t val;
1438 HALDEBUG(ah, HAL_DEBUG_PERCAL,
1439 "Starting ADC DC Offset Cal for Chain %d\n", i);
1441 HALDEBUG(ah, HAL_DEBUG_PERCAL, " pwr_meas_odd_i = %d\n",
1442 iOddMeasOffset);
1443 HALDEBUG(ah, HAL_DEBUG_PERCAL, " pwr_meas_even_i = %d\n",
1444 iEvenMeasOffset);
1445 HALDEBUG(ah, HAL_DEBUG_PERCAL, " pwr_meas_odd_q = %d\n",
1446 qOddMeasOffset);
1447 HALDEBUG(ah, HAL_DEBUG_PERCAL, " pwr_meas_even_q = %d\n",
1448 qEvenMeasOffset);
1450 HALASSERT(numSamples);
1452 iDcMismatch = (((iEvenMeasOffset - iOddMeasOffset) * 2) /
1453 numSamples) & 0x1ff;
1454 qDcMismatch = (((qOddMeasOffset - qEvenMeasOffset) * 2) /
1455 numSamples) & 0x1ff;
1456 HALDEBUG(ah, HAL_DEBUG_PERCAL,
1457 " dc_offset_mismatch_i = 0x%08x\n", iDcMismatch);
1458 HALDEBUG(ah, HAL_DEBUG_PERCAL,
1459 " dc_offset_mismatch_q = 0x%08x\n", qDcMismatch);
1461 val = OS_REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i));
1462 val &= 0xc0000fff;
1463 val |= (qDcMismatch << 12) | (iDcMismatch << 21);
1464 OS_REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val);
1466 HALDEBUG(ah, HAL_DEBUG_PERCAL,
1467 "ADC DC Offset Cal done for Chain %d\n", i);
1469 OS_REG_SET_BIT(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0),
1470 AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE);
1473 #ifdef AH_SUPPORT_AR9280
1474 static void
1475 ar9280GetNoiseFloor(struct ath_hal *ah, int16_t nfarray[NUM_NOISEFLOOR_READINGS])
1477 int16_t nf;
1479 nf = MS(OS_REG_READ(ah, AR_PHY_CCA), AR9280_PHY_MINCCA_PWR);
1480 if (nf & 0x100)
1481 nf = 0 - ((nf ^ 0x1ff) + 1);
1482 HALDEBUG(ah, HAL_DEBUG_NFCAL,
1483 "NF calibrated [ctl] [chain 0] is %d\n", nf);
1484 nfarray[0] = nf;
1486 nf = MS(OS_REG_READ(ah, AR_PHY_CH1_CCA), AR9280_PHY_CH1_MINCCA_PWR);
1487 if (nf & 0x100)
1488 nf = 0 - ((nf ^ 0x1ff) + 1);
1489 HALDEBUG(ah, HAL_DEBUG_NFCAL,
1490 "NF calibrated [ctl] [chain 1] is %d\n", nf);
1491 nfarray[1] = nf;
1493 nf = MS(OS_REG_READ(ah, AR_PHY_EXT_CCA), AR9280_PHY_EXT_MINCCA_PWR);
1494 if (nf & 0x100)
1495 nf = 0 - ((nf ^ 0x1ff) + 1);
1496 HALDEBUG(ah, HAL_DEBUG_NFCAL,
1497 "NF calibrated [ext] [chain 0] is %d\n", nf);
1498 nfarray[3] = nf;
1500 nf = MS(OS_REG_READ(ah, AR_PHY_CH1_EXT_CCA), AR9280_PHY_CH1_EXT_MINCCA_PWR);
1501 if (nf & 0x100)
1502 nf = 0 - ((nf ^ 0x1ff) + 1);
1503 HALDEBUG(ah, HAL_DEBUG_NFCAL,
1504 "NF calibrated [ext] [chain 1] is %d\n", nf);
1505 nfarray[4] = nf;
1507 #endif /* AH_SUPPORT_AR9280 */
1509 static void
1510 ar5416GetNoiseFloor(struct ath_hal *ah, int16_t nfarray[NUM_NOISEFLOOR_READINGS])
1512 struct ath_hal_5416 *ahp = AH5416(ah);
1513 int16_t nf;
1515 switch (ahp->ah_rx_chainmask) {
1516 case 0x7:
1517 nf = MS(OS_REG_READ(ah, AR_PHY_CH2_CCA), AR_PHY_CH2_MINCCA_PWR);
1518 if (nf & 0x100)
1519 nf = 0 - ((nf ^ 0x1ff) + 1);
1520 HALDEBUG(ah, HAL_DEBUG_NFCAL,
1521 "NF calibrated [ctl] [chain 2] is %d\n", nf);
1522 nfarray[4] = nf;
1524 nf = MS(OS_REG_READ(ah, AR_PHY_CH2_EXT_CCA), AR_PHY_CH2_EXT_MINCCA_PWR);
1525 if (nf & 0x100)
1526 nf = 0 - ((nf ^ 0x1ff) + 1);
1527 HALDEBUG(ah, HAL_DEBUG_NFCAL,
1528 "NF calibrated [ext] [chain 2] is %d\n", nf);
1529 nfarray[5] = nf;
1530 /* fall thru... */
1531 case 0x3:
1532 case 0x5:
1533 nf = MS(OS_REG_READ(ah, AR_PHY_CH1_CCA), AR_PHY_CH1_MINCCA_PWR);
1534 if (nf & 0x100)
1535 nf = 0 - ((nf ^ 0x1ff) + 1);
1536 HALDEBUG(ah, HAL_DEBUG_NFCAL,
1537 "NF calibrated [ctl] [chain 1] is %d\n", nf);
1538 nfarray[2] = nf;
1541 nf = MS(OS_REG_READ(ah, AR_PHY_CH1_EXT_CCA), AR_PHY_CH1_EXT_MINCCA_PWR);
1542 if (nf & 0x100)
1543 nf = 0 - ((nf ^ 0x1ff) + 1);
1544 HALDEBUG(ah, HAL_DEBUG_NFCAL,
1545 "NF calibrated [ext] [chain 1] is %d\n", nf);
1546 nfarray[3] = nf;
1547 /* fall thru... */
1548 case 0x1:
1549 nf = MS(OS_REG_READ(ah, AR_PHY_CCA), AR_PHY_MINCCA_PWR);
1550 if (nf & 0x100)
1551 nf = 0 - ((nf ^ 0x1ff) + 1);
1552 HALDEBUG(ah, HAL_DEBUG_NFCAL,
1553 "NF calibrated [ctl] [chain 0] is %d\n", nf);
1554 nfarray[0] = nf;
1556 nf = MS(OS_REG_READ(ah, AR_PHY_EXT_CCA), AR_PHY_EXT_MINCCA_PWR);
1557 if (nf & 0x100)
1558 nf = 0 - ((nf ^ 0x1ff) + 1);
1559 HALDEBUG(ah, HAL_DEBUG_NFCAL,
1560 "NF calibrated [ext] [chain 0] is %d\n", nf);
1561 nfarray[1] = nf;
1563 break;
1567 static HAL_BOOL
1568 ar5416GetEepromNoiseFloorThresh(struct ath_hal *ah,
1569 const HAL_CHANNEL_INTERNAL *chan, int16_t *nft)
1571 switch (chan->channelFlags & CHANNEL_ALL_NOTURBO) {
1572 case CHANNEL_A:
1573 case CHANNEL_A_HT20:
1574 case CHANNEL_A_HT40PLUS:
1575 case CHANNEL_A_HT40MINUS:
1576 ath_hal_eepromGet(ah, AR_EEP_NFTHRESH_5, nft);
1577 break;
1578 case CHANNEL_B:
1579 case CHANNEL_G:
1580 case CHANNEL_G_HT20:
1581 case CHANNEL_G_HT40PLUS:
1582 case CHANNEL_G_HT40MINUS:
1583 ath_hal_eepromGet(ah, AR_EEP_NFTHRESH_2, nft);
1584 break;
1585 default:
1586 HALDEBUG(ah, HAL_DEBUG_ANY,
1587 "%s: invalid channel flags 0x%x\n",
1588 __func__, chan->channelFlags);
1589 return AH_FALSE;
1591 return AH_TRUE;
1594 static void
1595 ar5416StartNFCal(struct ath_hal *ah)
1597 OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_ENABLE_NF);
1598 OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
1599 OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
1602 static void
1603 ar5416LoadNF(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan)
1605 static const uint32_t ar5416_cca_regs[] = {
1606 AR_PHY_CCA,
1607 AR_PHY_CH1_CCA,
1608 AR_PHY_CH2_CCA,
1609 AR_PHY_EXT_CCA,
1610 AR_PHY_CH1_EXT_CCA,
1611 AR_PHY_CH2_EXT_CCA
1613 struct ar5212NfCalHist *h;
1614 int i, j;
1615 int32_t val;
1616 uint8_t chainmask;
1619 * Force NF calibration for all chains, otherwise Vista station
1620 * would conduct a bad performance
1622 if (AR_SREV_KITE(ah)) {
1623 /* Kite has only one chain */
1624 chainmask = 0x9;
1625 } else if (AR_SREV_MERLIN(ah)) {
1626 /* Merlin has only two chains */
1627 chainmask = 0x1B;
1628 } else {
1629 chainmask = 0x3F;
1633 * Write filtered NF values into maxCCApwr register parameter
1634 * so we can load below.
1636 h = AH5416(ah)->ah_nfCalHist;
1637 for (i = 0; i < AR5416_NUM_NF_READINGS; i ++)
1638 if (chainmask & (1 << i)) {
1639 val = OS_REG_READ(ah, ar5416_cca_regs[i]);
1640 val &= 0xFFFFFE00;
1641 val |= (((uint32_t)(h[i].privNF) << 1) & 0x1ff);
1642 OS_REG_WRITE(ah, ar5416_cca_regs[i], val);
1645 /* Load software filtered NF value into baseband internal minCCApwr variable. */
1646 OS_REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_ENABLE_NF);
1647 OS_REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
1648 OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
1650 /* Wait for load to complete, should be fast, a few 10s of us. */
1651 for (j = 0; j < 1000; j++) {
1652 if ((OS_REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) == 0)
1653 break;
1654 OS_DELAY(10);
1658 * Restore maxCCAPower register parameter again so that we're not capped
1659 * by the median we just loaded. This will be initial (and max) value
1660 * of next noise floor calibration the baseband does.
1662 for (i = 0; i < AR5416_NUM_NF_READINGS; i ++)
1663 if (chainmask & (1 << i)) {
1664 val = OS_REG_READ(ah, ar5416_cca_regs[i]);
1665 val &= 0xFFFFFE00;
1666 val |= (((uint32_t)(-50) << 1) & 0x1ff);
1667 OS_REG_WRITE(ah, ar5416_cca_regs[i], val);
1671 void
1672 ar5416InitNfHistBuff(struct ar5212NfCalHist *h)
1674 int i, j;
1676 for (i = 0; i < AR5416_NUM_NF_READINGS; i ++) {
1677 h[i].currIndex = 0;
1678 h[i].privNF = AR5416_CCA_MAX_GOOD_VALUE;
1679 h[i].invalidNFcount = AR512_NF_CAL_HIST_MAX;
1680 for (j = 0; j < AR512_NF_CAL_HIST_MAX; j ++)
1681 h[i].nfCalBuffer[j] = AR5416_CCA_MAX_GOOD_VALUE;
1686 * Update the noise floor buffer as a ring buffer
1688 static void
1689 ar5416UpdateNFHistBuff(struct ar5212NfCalHist *h, int16_t *nfarray)
1691 int i;
1693 for (i = 0; i < AR5416_NUM_NF_READINGS; i ++) {
1694 h[i].nfCalBuffer[h[i].currIndex] = nfarray[i];
1696 if (++h[i].currIndex >= AR512_NF_CAL_HIST_MAX)
1697 h[i].currIndex = 0;
1698 if (h[i].invalidNFcount > 0) {
1699 if (nfarray[i] < AR5416_CCA_MIN_BAD_VALUE ||
1700 nfarray[i] > AR5416_CCA_MAX_HIGH_VALUE) {
1701 h[i].invalidNFcount = AR512_NF_CAL_HIST_MAX;
1702 } else {
1703 h[i].invalidNFcount--;
1704 h[i].privNF = nfarray[i];
1706 } else {
1707 h[i].privNF = ar5212GetNfHistMid(h[i].nfCalBuffer);
1713 * Read the NF and check it against the noise floor threshhold
1715 static int16_t
1716 ar5416GetNf(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan)
1718 int16_t nf, nfThresh;
1720 if (OS_REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) {
1721 HALDEBUG(ah, HAL_DEBUG_ANY,
1722 "%s: NF didn't complete in calibration window\n", __func__);
1723 nf = 0;
1724 } else {
1725 /* Finished NF cal, check against threshold */
1726 int16_t nfarray[NUM_NOISEFLOOR_READINGS]= { 0 };
1728 /* TODO - enhance for multiple chains and ext ch */
1729 #ifdef AH_SUPPORT_AR9280
1730 if (AR_SREV_MERLIN_10_OR_LATER(ah))
1731 ar9280GetNoiseFloor(ah, nfarray);
1732 else
1733 #endif
1734 ar5416GetNoiseFloor(ah, nfarray);
1735 nf = nfarray[0];
1736 if (ar5416GetEepromNoiseFloorThresh(ah, chan, &nfThresh)) {
1737 if (nf > nfThresh) {
1738 HALDEBUG(ah, HAL_DEBUG_ANY,
1739 "%s: noise floor failed detected; "
1740 "detected %d, threshold %d\n", __func__,
1741 nf, nfThresh);
1743 * NB: Don't discriminate 2.4 vs 5Ghz, if this
1744 * happens it indicates a problem regardless
1745 * of the band.
1747 chan->channelFlags |= CHANNEL_CW_INT;
1748 nf = 0;
1750 } else {
1751 nf = 0;
1753 ar5416UpdateNFHistBuff(AH5416(ah)->ah_nfCalHist, nfarray);
1754 chan->rawNoiseFloor = nf;
1756 return nf;
1760 * Delta slope coefficient computation.
1761 * Required for OFDM operation.
1763 static void
1764 ar5416GetDeltaSlopeValues(struct ath_hal *ah, uint32_t coef_scaled,
1765 uint32_t *coef_mantissa, uint32_t *coef_exponent)
1767 #define COEF_SCALE_S 24
1768 uint32_t coef_exp, coef_man;
1770 * ALGO -> coef_exp = 14-floor(log2(coef));
1771 * floor(log2(x)) is the highest set bit position
1773 for (coef_exp = 31; coef_exp > 0; coef_exp--)
1774 if ((coef_scaled >> coef_exp) & 0x1)
1775 break;
1776 /* A coef_exp of 0 is a legal bit position but an unexpected coef_exp */
1777 HALASSERT(coef_exp);
1778 coef_exp = 14 - (coef_exp - COEF_SCALE_S);
1781 * ALGO -> coef_man = floor(coef* 2^coef_exp+0.5);
1782 * The coefficient is already shifted up for scaling
1784 coef_man = coef_scaled + (1 << (COEF_SCALE_S - coef_exp - 1));
1786 *coef_mantissa = coef_man >> (COEF_SCALE_S - coef_exp);
1787 *coef_exponent = coef_exp - 16;
1789 #undef COEF_SCALE_S
1792 void
1793 ar5416SetDeltaSlope(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan)
1795 #define INIT_CLOCKMHZSCALED 0x64000000
1796 uint32_t coef_scaled, ds_coef_exp, ds_coef_man;
1797 uint32_t clockMhzScaled = INIT_CLOCKMHZSCALED;
1799 CHAN_CENTERS centers;
1801 if (IS_CHAN_TURBO(chan))
1802 clockMhzScaled *= 2;
1803 /* half and quarter rate can divide the scaled clock by 2 or 4 respectively */
1804 /* scale for selected channel bandwidth */
1805 if (IS_CHAN_HALF_RATE(chan)) {
1806 clockMhzScaled = clockMhzScaled >> 1;
1807 } else if (IS_CHAN_QUARTER_RATE(chan)) {
1808 clockMhzScaled = clockMhzScaled >> 2;
1812 * ALGO -> coef = 1e8/fcarrier*fclock/40;
1813 * scaled coef to provide precision for this floating calculation
1815 ar5416GetChannelCenters(ah, chan, &centers);
1816 coef_scaled = clockMhzScaled / centers.synth_center;
1818 ar5416GetDeltaSlopeValues(ah, coef_scaled, &ds_coef_man, &ds_coef_exp);
1820 OS_REG_RMW_FIELD(ah, AR_PHY_TIMING3,
1821 AR_PHY_TIMING3_DSC_MAN, ds_coef_man);
1822 OS_REG_RMW_FIELD(ah, AR_PHY_TIMING3,
1823 AR_PHY_TIMING3_DSC_EXP, ds_coef_exp);
1826 * For Short GI,
1827 * scaled coeff is 9/10 that of normal coeff
1829 coef_scaled = (9 * coef_scaled)/10;
1831 ar5416GetDeltaSlopeValues(ah, coef_scaled, &ds_coef_man, &ds_coef_exp);
1833 /* for short gi */
1834 OS_REG_RMW_FIELD(ah, AR_PHY_HALFGI,
1835 AR_PHY_HALFGI_DSC_MAN, ds_coef_man);
1836 OS_REG_RMW_FIELD(ah, AR_PHY_HALFGI,
1837 AR_PHY_HALFGI_DSC_EXP, ds_coef_exp);
1838 #undef INIT_CLOCKMHZSCALED
1842 * Convert to baseband spur frequency given input channel frequency
1843 * and compute register settings below.
1845 #define SPUR_RSSI_THRESH 40
1847 static void
1848 ar5416SpurMitigate(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan)
1850 static const int pilot_mask_reg[4] = { AR_PHY_TIMING7, AR_PHY_TIMING8,
1851 AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60 };
1852 static const int chan_mask_reg[4] = { AR_PHY_TIMING9, AR_PHY_TIMING10,
1853 AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60 };
1854 static const int inc[4] = { 0, 100, 0, 0 };
1856 int bb_spur = AR_NO_SPUR;
1857 int bin, cur_bin;
1858 int spur_freq_sd;
1859 int spur_delta_phase;
1860 int denominator;
1861 int upper, lower, cur_vit_mask;
1862 int tmp, new;
1863 int i;
1865 int8_t mask_m[123];
1866 int8_t mask_p[123];
1867 int8_t mask_amt;
1868 int tmp_mask;
1869 int cur_bb_spur;
1870 HAL_BOOL is2GHz = IS_CHAN_2GHZ(chan);
1872 OS_MEMZERO(mask_m, sizeof(mask_m));
1873 OS_MEMZERO(mask_p, sizeof(mask_p));
1876 * Need to verify range +/- 9.5 for static ht20, otherwise spur
1877 * is out-of-band and can be ignored.
1879 for (i = 0; i < AR5416_EEPROM_MODAL_SPURS; i++) {
1880 cur_bb_spur = ath_hal_getSpurChan(ah, i, is2GHz);
1881 if (AR_NO_SPUR == cur_bb_spur)
1882 break;
1883 cur_bb_spur = cur_bb_spur - (chan->channel * 10);
1884 if ((cur_bb_spur > -95) && (cur_bb_spur < 95)) {
1885 bb_spur = cur_bb_spur;
1886 break;
1889 if (AR_NO_SPUR == bb_spur)
1890 return;
1892 bin = bb_spur * 32;
1894 tmp = OS_REG_READ(ah, AR_PHY_TIMING_CTRL4_CHAIN(0));
1895 new = tmp | (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI |
1896 AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER |
1897 AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK |
1898 AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK);
1900 OS_REG_WRITE(ah, AR_PHY_TIMING_CTRL4_CHAIN(0), new);
1902 new = (AR_PHY_SPUR_REG_MASK_RATE_CNTL |
1903 AR_PHY_SPUR_REG_ENABLE_MASK_PPM |
1904 AR_PHY_SPUR_REG_MASK_RATE_SELECT |
1905 AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI |
1906 SM(SPUR_RSSI_THRESH, AR_PHY_SPUR_REG_SPUR_RSSI_THRESH));
1907 OS_REG_WRITE(ah, AR_PHY_SPUR_REG, new);
1909 * Should offset bb_spur by +/- 10 MHz for dynamic 2040 MHz
1910 * config, no offset for HT20.
1911 * spur_delta_phase = bb_spur/40 * 2**21 for static ht20,
1912 * /80 for dyn2040.
1914 spur_delta_phase = ((bb_spur * 524288) / 100) &
1915 AR_PHY_TIMING11_SPUR_DELTA_PHASE;
1917 * in 11A mode the denominator of spur_freq_sd should be 40 and
1918 * it should be 44 in 11G
1920 denominator = IS_CHAN_2GHZ(chan) ? 440 : 400;
1921 spur_freq_sd = ((bb_spur * 2048) / denominator) & 0x3ff;
1923 new = (AR_PHY_TIMING11_USE_SPUR_IN_AGC |
1924 SM(spur_freq_sd, AR_PHY_TIMING11_SPUR_FREQ_SD) |
1925 SM(spur_delta_phase, AR_PHY_TIMING11_SPUR_DELTA_PHASE));
1926 OS_REG_WRITE(ah, AR_PHY_TIMING11, new);
1930 * ============================================
1931 * pilot mask 1 [31:0] = +6..-26, no 0 bin
1932 * pilot mask 2 [19:0] = +26..+7
1934 * channel mask 1 [31:0] = +6..-26, no 0 bin
1935 * channel mask 2 [19:0] = +26..+7
1937 //cur_bin = -26;
1938 cur_bin = -6000;
1939 upper = bin + 100;
1940 lower = bin - 100;
1942 for (i = 0; i < 4; i++) {
1943 int pilot_mask = 0;
1944 int chan_mask = 0;
1945 int bp = 0;
1946 for (bp = 0; bp < 30; bp++) {
1947 if ((cur_bin > lower) && (cur_bin < upper)) {
1948 pilot_mask = pilot_mask | 0x1 << bp;
1949 chan_mask = chan_mask | 0x1 << bp;
1951 cur_bin += 100;
1953 cur_bin += inc[i];
1954 OS_REG_WRITE(ah, pilot_mask_reg[i], pilot_mask);
1955 OS_REG_WRITE(ah, chan_mask_reg[i], chan_mask);
1958 /* =================================================
1959 * viterbi mask 1 based on channel magnitude
1960 * four levels 0-3
1961 * - mask (-27 to 27) (reg 64,0x9900 to 67,0x990c)
1962 * [1 2 2 1] for -9.6 or [1 2 1] for +16
1963 * - enable_mask_ppm, all bins move with freq
1965 * - mask_select, 8 bits for rates (reg 67,0x990c)
1966 * - mask_rate_cntl, 8 bits for rates (reg 67,0x990c)
1967 * choose which mask to use mask or mask2
1971 * viterbi mask 2 2nd set for per data rate puncturing
1972 * four levels 0-3
1973 * - mask_select, 8 bits for rates (reg 67)
1974 * - mask (-27 to 27) (reg 98,0x9988 to 101,0x9994)
1975 * [1 2 2 1] for -9.6 or [1 2 1] for +16
1977 cur_vit_mask = 6100;
1978 upper = bin + 120;
1979 lower = bin - 120;
1981 for (i = 0; i < 123; i++) {
1982 if ((cur_vit_mask > lower) && (cur_vit_mask < upper)) {
1983 if ((abs(cur_vit_mask - bin)) < 75) {
1984 mask_amt = 1;
1985 } else {
1986 mask_amt = 0;
1988 if (cur_vit_mask < 0) {
1989 mask_m[abs(cur_vit_mask / 100)] = mask_amt;
1990 } else {
1991 mask_p[cur_vit_mask / 100] = mask_amt;
1994 cur_vit_mask -= 100;
1997 tmp_mask = (mask_m[46] << 30) | (mask_m[47] << 28)
1998 | (mask_m[48] << 26) | (mask_m[49] << 24)
1999 | (mask_m[50] << 22) | (mask_m[51] << 20)
2000 | (mask_m[52] << 18) | (mask_m[53] << 16)
2001 | (mask_m[54] << 14) | (mask_m[55] << 12)
2002 | (mask_m[56] << 10) | (mask_m[57] << 8)
2003 | (mask_m[58] << 6) | (mask_m[59] << 4)
2004 | (mask_m[60] << 2) | (mask_m[61] << 0);
2005 OS_REG_WRITE(ah, AR_PHY_BIN_MASK_1, tmp_mask);
2006 OS_REG_WRITE(ah, AR_PHY_VIT_MASK2_M_46_61, tmp_mask);
2008 tmp_mask = (mask_m[31] << 28)
2009 | (mask_m[32] << 26) | (mask_m[33] << 24)
2010 | (mask_m[34] << 22) | (mask_m[35] << 20)
2011 | (mask_m[36] << 18) | (mask_m[37] << 16)
2012 | (mask_m[48] << 14) | (mask_m[39] << 12)
2013 | (mask_m[40] << 10) | (mask_m[41] << 8)
2014 | (mask_m[42] << 6) | (mask_m[43] << 4)
2015 | (mask_m[44] << 2) | (mask_m[45] << 0);
2016 OS_REG_WRITE(ah, AR_PHY_BIN_MASK_2, tmp_mask);
2017 OS_REG_WRITE(ah, AR_PHY_MASK2_M_31_45, tmp_mask);
2019 tmp_mask = (mask_m[16] << 30) | (mask_m[16] << 28)
2020 | (mask_m[18] << 26) | (mask_m[18] << 24)
2021 | (mask_m[20] << 22) | (mask_m[20] << 20)
2022 | (mask_m[22] << 18) | (mask_m[22] << 16)
2023 | (mask_m[24] << 14) | (mask_m[24] << 12)
2024 | (mask_m[25] << 10) | (mask_m[26] << 8)
2025 | (mask_m[27] << 6) | (mask_m[28] << 4)
2026 | (mask_m[29] << 2) | (mask_m[30] << 0);
2027 OS_REG_WRITE(ah, AR_PHY_BIN_MASK_3, tmp_mask);
2028 OS_REG_WRITE(ah, AR_PHY_MASK2_M_16_30, tmp_mask);
2030 tmp_mask = (mask_m[ 0] << 30) | (mask_m[ 1] << 28)
2031 | (mask_m[ 2] << 26) | (mask_m[ 3] << 24)
2032 | (mask_m[ 4] << 22) | (mask_m[ 5] << 20)
2033 | (mask_m[ 6] << 18) | (mask_m[ 7] << 16)
2034 | (mask_m[ 8] << 14) | (mask_m[ 9] << 12)
2035 | (mask_m[10] << 10) | (mask_m[11] << 8)
2036 | (mask_m[12] << 6) | (mask_m[13] << 4)
2037 | (mask_m[14] << 2) | (mask_m[15] << 0);
2038 OS_REG_WRITE(ah, AR_PHY_MASK_CTL, tmp_mask);
2039 OS_REG_WRITE(ah, AR_PHY_MASK2_M_00_15, tmp_mask);
2041 tmp_mask = (mask_p[15] << 28)
2042 | (mask_p[14] << 26) | (mask_p[13] << 24)
2043 | (mask_p[12] << 22) | (mask_p[11] << 20)
2044 | (mask_p[10] << 18) | (mask_p[ 9] << 16)
2045 | (mask_p[ 8] << 14) | (mask_p[ 7] << 12)
2046 | (mask_p[ 6] << 10) | (mask_p[ 5] << 8)
2047 | (mask_p[ 4] << 6) | (mask_p[ 3] << 4)
2048 | (mask_p[ 2] << 2) | (mask_p[ 1] << 0);
2049 OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_1, tmp_mask);
2050 OS_REG_WRITE(ah, AR_PHY_MASK2_P_15_01, tmp_mask);
2052 tmp_mask = (mask_p[30] << 28)
2053 | (mask_p[29] << 26) | (mask_p[28] << 24)
2054 | (mask_p[27] << 22) | (mask_p[26] << 20)
2055 | (mask_p[25] << 18) | (mask_p[24] << 16)
2056 | (mask_p[23] << 14) | (mask_p[22] << 12)
2057 | (mask_p[21] << 10) | (mask_p[20] << 8)
2058 | (mask_p[19] << 6) | (mask_p[18] << 4)
2059 | (mask_p[17] << 2) | (mask_p[16] << 0);
2060 OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_2, tmp_mask);
2061 OS_REG_WRITE(ah, AR_PHY_MASK2_P_30_16, tmp_mask);
2063 tmp_mask = (mask_p[45] << 28)
2064 | (mask_p[44] << 26) | (mask_p[43] << 24)
2065 | (mask_p[42] << 22) | (mask_p[41] << 20)
2066 | (mask_p[40] << 18) | (mask_p[39] << 16)
2067 | (mask_p[38] << 14) | (mask_p[37] << 12)
2068 | (mask_p[36] << 10) | (mask_p[35] << 8)
2069 | (mask_p[34] << 6) | (mask_p[33] << 4)
2070 | (mask_p[32] << 2) | (mask_p[31] << 0);
2071 OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_3, tmp_mask);
2072 OS_REG_WRITE(ah, AR_PHY_MASK2_P_45_31, tmp_mask);
2074 tmp_mask = (mask_p[61] << 30) | (mask_p[60] << 28)
2075 | (mask_p[59] << 26) | (mask_p[58] << 24)
2076 | (mask_p[57] << 22) | (mask_p[56] << 20)
2077 | (mask_p[55] << 18) | (mask_p[54] << 16)
2078 | (mask_p[53] << 14) | (mask_p[52] << 12)
2079 | (mask_p[51] << 10) | (mask_p[50] << 8)
2080 | (mask_p[49] << 6) | (mask_p[48] << 4)
2081 | (mask_p[47] << 2) | (mask_p[46] << 0);
2082 OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_4, tmp_mask);
2083 OS_REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask);
2086 #ifdef AH_SUPPORT_AR9280
2087 #define AR_BASE_FREQ_2GHZ 2300
2088 #define AR_BASE_FREQ_5GHZ 4900
2089 #define AR_SPUR_FEEQ_BOUND_HT40 19
2090 #define AR_SPUR_FEEQ_BOUND_HT20 10
2092 static void
2093 ar9280SpurMitigate(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *ichan)
2095 static const int pilot_mask_reg[4] = { AR_PHY_TIMING7, AR_PHY_TIMING8,
2096 AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60 };
2097 static const int chan_mask_reg[4] = { AR_PHY_TIMING9, AR_PHY_TIMING10,
2098 AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60 };
2099 static int inc[4] = { 0, 100, 0, 0 };
2101 int bb_spur = AR_NO_SPUR;
2102 int freq;
2103 int bin, cur_bin;
2104 int bb_spur_off, spur_subchannel_sd;
2105 int spur_freq_sd;
2106 int spur_delta_phase;
2107 int denominator;
2108 int upper, lower, cur_vit_mask;
2109 int tmp, newVal;
2110 int i;
2111 CHAN_CENTERS centers;
2113 int8_t mask_m[123];
2114 int8_t mask_p[123];
2115 int8_t mask_amt;
2116 int tmp_mask;
2117 int cur_bb_spur;
2118 HAL_BOOL is2GHz = IS_CHAN_2GHZ(ichan);
2120 OS_MEMZERO(&mask_m, sizeof(int8_t) * 123);
2121 OS_MEMZERO(&mask_p, sizeof(int8_t) * 123);
2123 ar5416GetChannelCenters(ah, ichan, &centers);
2124 freq = centers.synth_center;
2127 * Need to verify range +/- 9.38 for static ht20 and +/- 18.75 for ht40,
2128 * otherwise spur is out-of-band and can be ignored.
2130 for (i = 0; i < AR5416_EEPROM_MODAL_SPURS; i++) {
2131 cur_bb_spur = ath_hal_getSpurChan(ah, i, is2GHz);
2132 /* Get actual spur freq in MHz from EEPROM read value */
2133 if (is2GHz) {
2134 cur_bb_spur = (cur_bb_spur / 10) + AR_BASE_FREQ_2GHZ;
2135 } else {
2136 cur_bb_spur = (cur_bb_spur / 10) + AR_BASE_FREQ_5GHZ;
2139 if (AR_NO_SPUR == cur_bb_spur)
2140 break;
2141 cur_bb_spur = cur_bb_spur - freq;
2143 if (IS_CHAN_HT40(ichan)) {
2144 if ((cur_bb_spur > -AR_SPUR_FEEQ_BOUND_HT40) &&
2145 (cur_bb_spur < AR_SPUR_FEEQ_BOUND_HT40)) {
2146 bb_spur = cur_bb_spur;
2147 break;
2149 } else if ((cur_bb_spur > -AR_SPUR_FEEQ_BOUND_HT20) &&
2150 (cur_bb_spur < AR_SPUR_FEEQ_BOUND_HT20)) {
2151 bb_spur = cur_bb_spur;
2152 break;
2156 if (AR_NO_SPUR == bb_spur) {
2157 #if 1
2159 * MRC CCK can interfere with beacon detection and cause deaf/mute.
2160 * Disable MRC CCK
2162 OS_REG_CLR_BIT(ah, AR_PHY_FORCE_CLKEN_CCK, AR_PHY_FORCE_CLKEN_CCK_MRC_MUX);
2163 #else
2164 /* Enable MRC CCK if no spur is found in this channel. */
2165 OS_REG_SET_BIT(ah, AR_PHY_FORCE_CLKEN_CCK, AR_PHY_FORCE_CLKEN_CCK_MRC_MUX);
2166 #endif
2167 return;
2168 } else {
2170 * For Merlin, spur can break CCK MRC algorithm. Disable CCK MRC if spur
2171 * is found in this channel.
2173 OS_REG_CLR_BIT(ah, AR_PHY_FORCE_CLKEN_CCK, AR_PHY_FORCE_CLKEN_CCK_MRC_MUX);
2176 bin = bb_spur * 320;
2178 tmp = OS_REG_READ(ah, AR_PHY_TIMING_CTRL4_CHAIN(0));
2180 newVal = tmp | (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI |
2181 AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER |
2182 AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK |
2183 AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK);
2184 OS_REG_WRITE(ah, AR_PHY_TIMING_CTRL4_CHAIN(0), newVal);
2186 newVal = (AR_PHY_SPUR_REG_MASK_RATE_CNTL |
2187 AR_PHY_SPUR_REG_ENABLE_MASK_PPM |
2188 AR_PHY_SPUR_REG_MASK_RATE_SELECT |
2189 AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI |
2190 SM(SPUR_RSSI_THRESH, AR_PHY_SPUR_REG_SPUR_RSSI_THRESH));
2191 OS_REG_WRITE(ah, AR_PHY_SPUR_REG, newVal);
2193 /* Pick control or extn channel to cancel the spur */
2194 if (IS_CHAN_HT40(ichan)) {
2195 if (bb_spur < 0) {
2196 spur_subchannel_sd = 1;
2197 bb_spur_off = bb_spur + 10;
2198 } else {
2199 spur_subchannel_sd = 0;
2200 bb_spur_off = bb_spur - 10;
2202 } else {
2203 spur_subchannel_sd = 0;
2204 bb_spur_off = bb_spur;
2208 * spur_delta_phase = bb_spur/40 * 2**21 for static ht20,
2209 * /80 for dyn2040.
2211 if (IS_CHAN_HT40(ichan))
2212 spur_delta_phase = ((bb_spur * 262144) / 10) & AR_PHY_TIMING11_SPUR_DELTA_PHASE;
2213 else
2214 spur_delta_phase = ((bb_spur * 524288) / 10) & AR_PHY_TIMING11_SPUR_DELTA_PHASE;
2217 * in 11A mode the denominator of spur_freq_sd should be 40 and
2218 * it should be 44 in 11G
2220 denominator = IS_CHAN_2GHZ(ichan) ? 44 : 40;
2221 spur_freq_sd = ((bb_spur_off * 2048) / denominator) & 0x3ff;
2223 newVal = (AR_PHY_TIMING11_USE_SPUR_IN_AGC |
2224 SM(spur_freq_sd, AR_PHY_TIMING11_SPUR_FREQ_SD) |
2225 SM(spur_delta_phase, AR_PHY_TIMING11_SPUR_DELTA_PHASE));
2226 OS_REG_WRITE(ah, AR_PHY_TIMING11, newVal);
2228 /* Choose to cancel between control and extension channels */
2229 newVal = spur_subchannel_sd << AR_PHY_SFCORR_SPUR_SUBCHNL_SD_S;
2230 OS_REG_WRITE(ah, AR_PHY_SFCORR_EXT, newVal);
2233 * ============================================
2234 * Set Pilot and Channel Masks
2236 * pilot mask 1 [31:0] = +6..-26, no 0 bin
2237 * pilot mask 2 [19:0] = +26..+7
2239 * channel mask 1 [31:0] = +6..-26, no 0 bin
2240 * channel mask 2 [19:0] = +26..+7
2242 cur_bin = -6000;
2243 upper = bin + 100;
2244 lower = bin - 100;
2246 for (i = 0; i < 4; i++) {
2247 int pilot_mask = 0;
2248 int chan_mask = 0;
2249 int bp = 0;
2250 for (bp = 0; bp < 30; bp++) {
2251 if ((cur_bin > lower) && (cur_bin < upper)) {
2252 pilot_mask = pilot_mask | 0x1 << bp;
2253 chan_mask = chan_mask | 0x1 << bp;
2255 cur_bin += 100;
2257 cur_bin += inc[i];
2258 OS_REG_WRITE(ah, pilot_mask_reg[i], pilot_mask);
2259 OS_REG_WRITE(ah, chan_mask_reg[i], chan_mask);
2262 /* =================================================
2263 * viterbi mask 1 based on channel magnitude
2264 * four levels 0-3
2265 * - mask (-27 to 27) (reg 64,0x9900 to 67,0x990c)
2266 * [1 2 2 1] for -9.6 or [1 2 1] for +16
2267 * - enable_mask_ppm, all bins move with freq
2269 * - mask_select, 8 bits for rates (reg 67,0x990c)
2270 * - mask_rate_cntl, 8 bits for rates (reg 67,0x990c)
2271 * choose which mask to use mask or mask2
2275 * viterbi mask 2 2nd set for per data rate puncturing
2276 * four levels 0-3
2277 * - mask_select, 8 bits for rates (reg 67)
2278 * - mask (-27 to 27) (reg 98,0x9988 to 101,0x9994)
2279 * [1 2 2 1] for -9.6 or [1 2 1] for +16
2281 cur_vit_mask = 6100;
2282 upper = bin + 120;
2283 lower = bin - 120;
2285 for (i = 0; i < 123; i++) {
2286 if ((cur_vit_mask > lower) && (cur_vit_mask < upper)) {
2287 if ((abs(cur_vit_mask - bin)) < 75) {
2288 mask_amt = 1;
2289 } else {
2290 mask_amt = 0;
2292 if (cur_vit_mask < 0) {
2293 mask_m[abs(cur_vit_mask / 100)] = mask_amt;
2294 } else {
2295 mask_p[cur_vit_mask / 100] = mask_amt;
2298 cur_vit_mask -= 100;
2301 tmp_mask = (mask_m[46] << 30) | (mask_m[47] << 28)
2302 | (mask_m[48] << 26) | (mask_m[49] << 24)
2303 | (mask_m[50] << 22) | (mask_m[51] << 20)
2304 | (mask_m[52] << 18) | (mask_m[53] << 16)
2305 | (mask_m[54] << 14) | (mask_m[55] << 12)
2306 | (mask_m[56] << 10) | (mask_m[57] << 8)
2307 | (mask_m[58] << 6) | (mask_m[59] << 4)
2308 | (mask_m[60] << 2) | (mask_m[61] << 0);
2309 OS_REG_WRITE(ah, AR_PHY_BIN_MASK_1, tmp_mask);
2310 OS_REG_WRITE(ah, AR_PHY_VIT_MASK2_M_46_61, tmp_mask);
2312 tmp_mask = (mask_m[31] << 28)
2313 | (mask_m[32] << 26) | (mask_m[33] << 24)
2314 | (mask_m[34] << 22) | (mask_m[35] << 20)
2315 | (mask_m[36] << 18) | (mask_m[37] << 16)
2316 | (mask_m[48] << 14) | (mask_m[39] << 12)
2317 | (mask_m[40] << 10) | (mask_m[41] << 8)
2318 | (mask_m[42] << 6) | (mask_m[43] << 4)
2319 | (mask_m[44] << 2) | (mask_m[45] << 0);
2320 OS_REG_WRITE(ah, AR_PHY_BIN_MASK_2, tmp_mask);
2321 OS_REG_WRITE(ah, AR_PHY_MASK2_M_31_45, tmp_mask);
2323 tmp_mask = (mask_m[16] << 30) | (mask_m[16] << 28)
2324 | (mask_m[18] << 26) | (mask_m[18] << 24)
2325 | (mask_m[20] << 22) | (mask_m[20] << 20)
2326 | (mask_m[22] << 18) | (mask_m[22] << 16)
2327 | (mask_m[24] << 14) | (mask_m[24] << 12)
2328 | (mask_m[25] << 10) | (mask_m[26] << 8)
2329 | (mask_m[27] << 6) | (mask_m[28] << 4)
2330 | (mask_m[29] << 2) | (mask_m[30] << 0);
2331 OS_REG_WRITE(ah, AR_PHY_BIN_MASK_3, tmp_mask);
2332 OS_REG_WRITE(ah, AR_PHY_MASK2_M_16_30, tmp_mask);
2334 tmp_mask = (mask_m[ 0] << 30) | (mask_m[ 1] << 28)
2335 | (mask_m[ 2] << 26) | (mask_m[ 3] << 24)
2336 | (mask_m[ 4] << 22) | (mask_m[ 5] << 20)
2337 | (mask_m[ 6] << 18) | (mask_m[ 7] << 16)
2338 | (mask_m[ 8] << 14) | (mask_m[ 9] << 12)
2339 | (mask_m[10] << 10) | (mask_m[11] << 8)
2340 | (mask_m[12] << 6) | (mask_m[13] << 4)
2341 | (mask_m[14] << 2) | (mask_m[15] << 0);
2342 OS_REG_WRITE(ah, AR_PHY_MASK_CTL, tmp_mask);
2343 OS_REG_WRITE(ah, AR_PHY_MASK2_M_00_15, tmp_mask);
2345 tmp_mask = (mask_p[15] << 28)
2346 | (mask_p[14] << 26) | (mask_p[13] << 24)
2347 | (mask_p[12] << 22) | (mask_p[11] << 20)
2348 | (mask_p[10] << 18) | (mask_p[ 9] << 16)
2349 | (mask_p[ 8] << 14) | (mask_p[ 7] << 12)
2350 | (mask_p[ 6] << 10) | (mask_p[ 5] << 8)
2351 | (mask_p[ 4] << 6) | (mask_p[ 3] << 4)
2352 | (mask_p[ 2] << 2) | (mask_p[ 1] << 0);
2353 OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_1, tmp_mask);
2354 OS_REG_WRITE(ah, AR_PHY_MASK2_P_15_01, tmp_mask);
2356 tmp_mask = (mask_p[30] << 28)
2357 | (mask_p[29] << 26) | (mask_p[28] << 24)
2358 | (mask_p[27] << 22) | (mask_p[26] << 20)
2359 | (mask_p[25] << 18) | (mask_p[24] << 16)
2360 | (mask_p[23] << 14) | (mask_p[22] << 12)
2361 | (mask_p[21] << 10) | (mask_p[20] << 8)
2362 | (mask_p[19] << 6) | (mask_p[18] << 4)
2363 | (mask_p[17] << 2) | (mask_p[16] << 0);
2364 OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_2, tmp_mask);
2365 OS_REG_WRITE(ah, AR_PHY_MASK2_P_30_16, tmp_mask);
2367 tmp_mask = (mask_p[45] << 28)
2368 | (mask_p[44] << 26) | (mask_p[43] << 24)
2369 | (mask_p[42] << 22) | (mask_p[41] << 20)
2370 | (mask_p[40] << 18) | (mask_p[39] << 16)
2371 | (mask_p[38] << 14) | (mask_p[37] << 12)
2372 | (mask_p[36] << 10) | (mask_p[35] << 8)
2373 | (mask_p[34] << 6) | (mask_p[33] << 4)
2374 | (mask_p[32] << 2) | (mask_p[31] << 0);
2375 OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_3, tmp_mask);
2376 OS_REG_WRITE(ah, AR_PHY_MASK2_P_45_31, tmp_mask);
2378 tmp_mask = (mask_p[61] << 30) | (mask_p[60] << 28)
2379 | (mask_p[59] << 26) | (mask_p[58] << 24)
2380 | (mask_p[57] << 22) | (mask_p[56] << 20)
2381 | (mask_p[55] << 18) | (mask_p[54] << 16)
2382 | (mask_p[53] << 14) | (mask_p[52] << 12)
2383 | (mask_p[51] << 10) | (mask_p[50] << 8)
2384 | (mask_p[49] << 6) | (mask_p[48] << 4)
2385 | (mask_p[47] << 2) | (mask_p[46] << 0);
2386 OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_4, tmp_mask);
2387 OS_REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask);
2389 #endif /* AH_SUPPORT_AR9280 */
2392 * Set a limit on the overall output power. Used for dynamic
2393 * transmit power control and the like.
2395 * NB: limit is in units of 0.5 dbM.
2397 HAL_BOOL
2398 ar5416SetTxPowerLimit(struct ath_hal *ah, uint32_t limit)
2400 uint16_t dummyXpdGains[2];
2402 AH_PRIVATE(ah)->ah_powerLimit = AH_MIN(limit, MAX_RATE_POWER);
2403 return ar5416SetTransmitPower(ah, AH_PRIVATE(ah)->ah_curchan,
2404 dummyXpdGains);
2407 HAL_BOOL
2408 ar5416GetChipPowerLimits(struct ath_hal *ah, HAL_CHANNEL *chans, uint32_t nchans)
2410 struct ath_hal_5212 *ahp = AH5212(ah);
2411 int16_t minPower, maxPower;
2412 HAL_CHANNEL *chan;
2413 int i;
2416 * Get Pier table max and min powers.
2418 for (i = 0; i < nchans; i++) {
2419 chan = &chans[i];
2420 if (ahp->ah_rfHal->getChannelMaxMinPower(ah, chan, &maxPower, &minPower)) {
2421 /* NB: rf code returns 1/4 dBm units, convert */
2422 chan->maxTxPower = maxPower / 2;
2423 chan->minTxPower = minPower / 2;
2424 } else {
2425 HALDEBUG(ah, HAL_DEBUG_ANY,
2426 "%s: no min/max power for %u/0x%x\n",
2427 __func__, chan->channel, chan->channelFlags);
2428 chan->maxTxPower = AR5416_MAX_RATE_POWER;
2429 chan->minTxPower = 0;
2432 #ifdef AH_DEBUG
2433 for (i=0; i<nchans; i++) {
2434 HALDEBUG(ah, HAL_DEBUG_RESET,
2435 "Chan %d: MaxPow = %d MinPow = %d\n",
2436 chans[i].channel,chans[i].maxTxPower, chans[i].minTxPower);
2438 #endif
2439 return AH_TRUE;
2442 /* XXX gag, this is sick */
2443 typedef enum Ar5416_Rates {
2444 rate6mb, rate9mb, rate12mb, rate18mb,
2445 rate24mb, rate36mb, rate48mb, rate54mb,
2446 rate1l, rate2l, rate2s, rate5_5l,
2447 rate5_5s, rate11l, rate11s, rateXr,
2448 rateHt20_0, rateHt20_1, rateHt20_2, rateHt20_3,
2449 rateHt20_4, rateHt20_5, rateHt20_6, rateHt20_7,
2450 rateHt40_0, rateHt40_1, rateHt40_2, rateHt40_3,
2451 rateHt40_4, rateHt40_5, rateHt40_6, rateHt40_7,
2452 rateDupCck, rateDupOfdm, rateExtCck, rateExtOfdm,
2453 Ar5416RateSize
2454 } AR5416_RATES;
2456 /**************************************************************
2457 * ar5416SetTransmitPower
2459 * Set the transmit power in the baseband for the given
2460 * operating channel and mode.
2462 static HAL_BOOL
2463 ar5416SetTransmitPower(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan, uint16_t *rfXpdGain)
2465 #define POW_SM(_r, _s) (((_r) & 0x3f) << (_s))
2466 #define N(a) (sizeof (a) / sizeof (a[0]))
2468 MODAL_EEP_HEADER *pModal;
2469 struct ath_hal_5212 *ahp = AH5212(ah);
2470 int16_t ratesArray[Ar5416RateSize];
2471 int16_t txPowerIndexOffset = 0;
2472 uint8_t ht40PowerIncForPdadc = 2;
2473 int i;
2475 uint16_t cfgCtl;
2476 uint16_t powerLimit;
2477 uint16_t twiceAntennaReduction;
2478 uint16_t twiceMaxRegulatoryPower;
2479 int16_t maxPower;
2480 HAL_EEPROM_v14 *ee = AH_PRIVATE(ah)->ah_eeprom;
2481 struct ar5416eeprom *pEepData = &ee->ee_base;
2483 HALASSERT(AH_PRIVATE(ah)->ah_eeversion >= AR_EEPROM_VER14_1);
2485 /* Setup info for the actual eeprom */
2486 ath_hal_memzero(ratesArray, sizeof(ratesArray));
2487 cfgCtl = ath_hal_getctl(ah, (HAL_CHANNEL *)chan);
2488 powerLimit = chan->maxRegTxPower * 2;
2489 twiceAntennaReduction = chan->antennaMax;
2490 twiceMaxRegulatoryPower = AH_MIN(MAX_RATE_POWER, AH_PRIVATE(ah)->ah_powerLimit);
2491 pModal = &pEepData->modalHeader[IS_CHAN_2GHZ(chan)];
2492 HALDEBUG(ah, HAL_DEBUG_RESET, "%s Channel=%u CfgCtl=%u\n",
2493 __func__,chan->channel, cfgCtl );
2495 if (IS_EEP_MINOR_V2(ah)) {
2496 ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc;
2499 if (!ar5416SetPowerPerRateTable(ah, pEepData, chan,
2500 &ratesArray[0],cfgCtl,
2501 twiceAntennaReduction,
2502 twiceMaxRegulatoryPower, powerLimit)) {
2503 HALDEBUG(ah, HAL_DEBUG_ANY,
2504 "%s: unable to set tx power per rate table\n", __func__);
2505 return AH_FALSE;
2508 if (!ar5416SetPowerCalTable(ah, pEepData, chan, &txPowerIndexOffset)) {
2509 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unable to set power table\n",
2510 __func__);
2511 return AH_FALSE;
2514 maxPower = AH_MAX(ratesArray[rate6mb], ratesArray[rateHt20_0]);
2516 if (IS_CHAN_2GHZ(chan)) {
2517 maxPower = AH_MAX(maxPower, ratesArray[rate1l]);
2520 if (IS_CHAN_HT40(chan)) {
2521 maxPower = AH_MAX(maxPower, ratesArray[rateHt40_0]);
2524 ahp->ah_tx6PowerInHalfDbm = maxPower;
2525 AH_PRIVATE(ah)->ah_maxPowerLevel = maxPower;
2526 ahp->ah_txPowerIndexOffset = txPowerIndexOffset;
2529 * txPowerIndexOffset is set by the SetPowerTable() call -
2530 * adjust the rate table (0 offset if rates EEPROM not loaded)
2532 for (i = 0; i < N(ratesArray); i++) {
2533 ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]);
2534 if (ratesArray[i] > AR5416_MAX_RATE_POWER)
2535 ratesArray[i] = AR5416_MAX_RATE_POWER;
2538 #ifdef AH_EEPROM_DUMP
2539 ar5416PrintPowerPerRate(ah, ratesArray);
2540 #endif
2542 /* Write the OFDM power per rate set */
2543 OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE1,
2544 POW_SM(ratesArray[rate18mb], 24)
2545 | POW_SM(ratesArray[rate12mb], 16)
2546 | POW_SM(ratesArray[rate9mb], 8)
2547 | POW_SM(ratesArray[rate6mb], 0)
2549 OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE2,
2550 POW_SM(ratesArray[rate54mb], 24)
2551 | POW_SM(ratesArray[rate48mb], 16)
2552 | POW_SM(ratesArray[rate36mb], 8)
2553 | POW_SM(ratesArray[rate24mb], 0)
2556 if (IS_CHAN_2GHZ(chan)) {
2557 /* Write the CCK power per rate set */
2558 OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE3,
2559 POW_SM(ratesArray[rate2s], 24)
2560 | POW_SM(ratesArray[rate2l], 16)
2561 | POW_SM(ratesArray[rateXr], 8) /* XR target power */
2562 | POW_SM(ratesArray[rate1l], 0)
2564 OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE4,
2565 POW_SM(ratesArray[rate11s], 24)
2566 | POW_SM(ratesArray[rate11l], 16)
2567 | POW_SM(ratesArray[rate5_5s], 8)
2568 | POW_SM(ratesArray[rate5_5l], 0)
2570 HALDEBUG(ah, HAL_DEBUG_RESET,
2571 "%s AR_PHY_POWER_TX_RATE3=0x%x AR_PHY_POWER_TX_RATE4=0x%x\n",
2572 __func__, OS_REG_READ(ah,AR_PHY_POWER_TX_RATE3),
2573 OS_REG_READ(ah,AR_PHY_POWER_TX_RATE4));
2576 /* Write the HT20 power per rate set */
2577 OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE5,
2578 POW_SM(ratesArray[rateHt20_3], 24)
2579 | POW_SM(ratesArray[rateHt20_2], 16)
2580 | POW_SM(ratesArray[rateHt20_1], 8)
2581 | POW_SM(ratesArray[rateHt20_0], 0)
2583 OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE6,
2584 POW_SM(ratesArray[rateHt20_7], 24)
2585 | POW_SM(ratesArray[rateHt20_6], 16)
2586 | POW_SM(ratesArray[rateHt20_5], 8)
2587 | POW_SM(ratesArray[rateHt20_4], 0)
2590 if (IS_CHAN_HT40(chan)) {
2591 /* Write the HT40 power per rate set */
2592 /* Correct PAR difference between HT40 and HT20/LEGACY */
2593 OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE7,
2594 POW_SM(ratesArray[rateHt40_3] + ht40PowerIncForPdadc, 24)
2595 | POW_SM(ratesArray[rateHt40_2] + ht40PowerIncForPdadc, 16)
2596 | POW_SM(ratesArray[rateHt40_1] + ht40PowerIncForPdadc, 8)
2597 | POW_SM(ratesArray[rateHt40_0] + ht40PowerIncForPdadc, 0)
2599 OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE8,
2600 POW_SM(ratesArray[rateHt40_7] + ht40PowerIncForPdadc, 24)
2601 | POW_SM(ratesArray[rateHt40_6] + ht40PowerIncForPdadc, 16)
2602 | POW_SM(ratesArray[rateHt40_5] + ht40PowerIncForPdadc, 8)
2603 | POW_SM(ratesArray[rateHt40_4] + ht40PowerIncForPdadc, 0)
2605 /* Write the Dup/Ext 40 power per rate set */
2606 OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE9,
2607 POW_SM(ratesArray[rateExtOfdm], 24)
2608 | POW_SM(ratesArray[rateExtCck], 16)
2609 | POW_SM(ratesArray[rateDupOfdm], 8)
2610 | POW_SM(ratesArray[rateDupCck], 0)
2614 /* Write the Power subtraction for dynamic chain changing, for per-packet powertx */
2615 OS_REG_WRITE(ah, AR_PHY_POWER_TX_SUB,
2616 POW_SM(pModal->pwrDecreaseFor3Chain, 6)
2617 | POW_SM(pModal->pwrDecreaseFor2Chain, 0)
2619 return AH_TRUE;
2620 #undef POW_SM
2621 #undef N
2625 * Exported call to check for a recent gain reading and return
2626 * the current state of the thermal calibration gain engine.
2628 HAL_RFGAIN
2629 ar5416GetRfgain(struct ath_hal *ah)
2631 return HAL_RFGAIN_INACTIVE;
2635 * Places all of hardware into reset
2637 HAL_BOOL
2638 ar5416Disable(struct ath_hal *ah)
2640 if (!ar5212SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE))
2641 return AH_FALSE;
2642 return ar5416SetResetReg(ah, HAL_RESET_COLD);
2646 * Places the PHY and Radio chips into reset. A full reset
2647 * must be called to leave this state. The PCI/MAC/PCU are
2648 * not placed into reset as we must receive interrupt to
2649 * re-enable the hardware.
2651 HAL_BOOL
2652 ar5416PhyDisable(struct ath_hal *ah)
2654 return ar5416SetResetReg(ah, HAL_RESET_WARM);
2658 * Write the given reset bit mask into the reset register
2660 HAL_BOOL
2661 ar5416SetResetReg(struct ath_hal *ah, uint32_t type)
2664 * Set force wake
2666 OS_REG_WRITE(ah, AR_RTC_FORCE_WAKE,
2667 AR_RTC_FORCE_WAKE_EN | AR_RTC_FORCE_WAKE_ON_INT);
2669 switch (type) {
2670 case HAL_RESET_POWER_ON:
2671 return ar5416SetResetPowerOn(ah);
2672 break;
2673 case HAL_RESET_WARM:
2674 case HAL_RESET_COLD:
2675 return ar5416SetReset(ah, type);
2676 break;
2677 default:
2678 return AH_FALSE;
2682 static HAL_BOOL
2683 ar5416SetResetPowerOn(struct ath_hal *ah)
2685 /* Power On Reset (Hard Reset) */
2688 * Set force wake
2690 * If the MAC was running, previously calling
2691 * reset will wake up the MAC but it may go back to sleep
2692 * before we can start polling.
2693 * Set force wake stops that
2694 * This must be called before initiating a hard reset.
2696 OS_REG_WRITE(ah, AR_RTC_FORCE_WAKE,
2697 AR_RTC_FORCE_WAKE_EN | AR_RTC_FORCE_WAKE_ON_INT);
2700 * RTC reset and clear
2702 OS_REG_WRITE(ah, AR_RTC_RESET, 0);
2703 OS_DELAY(20);
2704 OS_REG_WRITE(ah, AR_RTC_RESET, 1);
2707 * Poll till RTC is ON
2709 if (!ath_hal_wait(ah, AR_RTC_STATUS, AR_RTC_PM_STATUS_M, AR_RTC_STATUS_ON)) {
2710 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: RTC not waking up\n", __func__);
2711 return AH_FALSE;
2714 return ar5416SetReset(ah, HAL_RESET_COLD);
2717 static HAL_BOOL
2718 ar5416SetReset(struct ath_hal *ah, int type)
2720 uint32_t tmpReg;
2723 * Force wake
2725 OS_REG_WRITE(ah, AR_RTC_FORCE_WAKE,
2726 AR_RTC_FORCE_WAKE_EN | AR_RTC_FORCE_WAKE_ON_INT);
2729 * Reset AHB
2731 tmpReg = OS_REG_READ(ah, AR_INTR_SYNC_CAUSE);
2732 if (tmpReg & (AR_INTR_SYNC_LOCAL_TIMEOUT|AR_INTR_SYNC_RADM_CPL_TIMEOUT)) {
2733 OS_REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0);
2734 OS_REG_WRITE(ah, AR_RC, AR_RC_AHB|AR_RC_HOSTIF);
2735 } else {
2736 OS_REG_WRITE(ah, AR_RC, AR_RC_AHB);
2740 * Set Mac(BB,Phy) Warm Reset
2742 switch (type) {
2743 case HAL_RESET_WARM:
2744 OS_REG_WRITE(ah, AR_RTC_RC, AR_RTC_RC_MAC_WARM);
2745 break;
2746 case HAL_RESET_COLD:
2747 OS_REG_WRITE(ah, AR_RTC_RC, AR_RTC_RC_MAC_WARM|AR_RTC_RC_MAC_COLD);
2748 break;
2749 default:
2750 HALASSERT(0);
2751 break;
2755 * Clear resets and force wakeup
2757 OS_REG_WRITE(ah, AR_RTC_RC, 0);
2758 if (!ath_hal_wait(ah, AR_RTC_RC, AR_RTC_RC_M, 0)) {
2759 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: RTC stuck in MAC reset\n", __func__);
2760 return AH_FALSE;
2763 /* Clear AHB reset */
2764 OS_REG_WRITE(ah, AR_RC, 0);
2766 /* Set register and descriptor swapping on
2767 * Bigendian platforms on cold reset
2769 #ifdef __BIG_ENDIAN__
2770 if (type == HAL_RESET_COLD) {
2771 uint32_t mask;
2773 HALDEBUG(ah, HAL_DEBUG_RESET,
2774 "%s Applying descriptor swap\n", __func__);
2776 mask = INIT_CONFIG_STATUS | AR_CFG_SWRD | AR_CFG_SWRG;
2777 #ifndef AH_NEED_DESC_SWAP
2778 mask |= AR_CFG_SWTD;
2779 #endif
2780 OS_REG_WRITE(ah, AR_CFG, LE_READ_4(&mask));
2782 #endif
2784 ar5416InitPLL(ah, AH_NULL);
2786 return AH_TRUE;
2789 #ifndef IS_5GHZ_FAST_CLOCK_EN
2790 #define IS_5GHZ_FAST_CLOCK_EN(ah, chan) AH_FALSE
2791 #endif
2793 static void
2794 ar5416InitPLL(struct ath_hal *ah, HAL_CHANNEL *chan)
2796 uint32_t pll;
2798 if (AR_SREV_MERLIN_10_OR_LATER(ah)) {
2799 pll = SM(0x5, AR_RTC_SOWL_PLL_REFDIV);
2801 if (chan != AH_NULL && IS_CHAN_HALF_RATE(chan)) {
2802 pll |= SM(0x1, AR_RTC_SOWL_PLL_CLKSEL);
2803 } else if (chan && IS_CHAN_QUARTER_RATE(chan)) {
2804 pll |= SM(0x2, AR_RTC_SOWL_PLL_CLKSEL);
2806 if (chan != AH_NULL && IS_CHAN_5GHZ(chan)) {
2807 pll |= SM(0x28, AR_RTC_SOWL_PLL_DIV);
2810 * PLL WAR for Merlin 2.0/2.1
2811 * When doing fast clock, set PLL to 0x142c
2812 * Else, set PLL to 0x2850 to prevent reset-to-reset variation
2814 if (AR_SREV_MERLIN_20(ah)) {
2815 if (IS_5GHZ_FAST_CLOCK_EN(ah, chan)) {
2816 pll = 0x142c;
2817 } else {
2818 pll = 0x2850;
2821 } else {
2822 pll |= SM(0x2c, AR_RTC_SOWL_PLL_DIV);
2824 } else if (AR_SREV_SOWL_10_OR_LATER(ah)) {
2825 pll = SM(0x5, AR_RTC_SOWL_PLL_REFDIV);
2827 if (chan != AH_NULL && IS_CHAN_HALF_RATE(chan)) {
2828 pll |= SM(0x1, AR_RTC_SOWL_PLL_CLKSEL);
2829 } else if (chan && IS_CHAN_QUARTER_RATE(chan)) {
2830 pll |= SM(0x2, AR_RTC_SOWL_PLL_CLKSEL);
2832 if (chan != AH_NULL && IS_CHAN_5GHZ(chan)) {
2833 pll |= SM(0x50, AR_RTC_SOWL_PLL_DIV);
2834 } else {
2835 pll |= SM(0x58, AR_RTC_SOWL_PLL_DIV);
2837 } else {
2838 pll = AR_RTC_PLL_REFDIV_5 | AR_RTC_PLL_DIV2;
2840 if (chan != AH_NULL && IS_CHAN_HALF_RATE(chan)) {
2841 pll |= SM(0x1, AR_RTC_PLL_CLKSEL);
2842 } else if (chan != AH_NULL && IS_CHAN_QUARTER_RATE(chan)) {
2843 pll |= SM(0x2, AR_RTC_PLL_CLKSEL);
2845 if (chan != AH_NULL && IS_CHAN_5GHZ(chan)) {
2846 pll |= SM(0xa, AR_RTC_PLL_DIV);
2847 } else {
2848 pll |= SM(0xb, AR_RTC_PLL_DIV);
2851 OS_REG_WRITE(ah, AR_RTC_PLL_CONTROL, pll);
2853 /* TODO:
2854 * For multi-band owl, switch between bands by reiniting the PLL.
2857 OS_DELAY(RTC_PLL_SETTLE_DELAY);
2859 OS_REG_WRITE(ah, AR_RTC_SLEEP_CLK, AR_RTC_SLEEP_DERIVED_CLK);
2863 * Read EEPROM header info and program the device for correct operation
2864 * given the channel value.
2866 static HAL_BOOL
2867 ar5416SetBoardValues(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan)
2869 const HAL_EEPROM_v14 *ee = AH_PRIVATE(ah)->ah_eeprom;
2870 const struct ar5416eeprom *eep = &ee->ee_base;
2871 const MODAL_EEP_HEADER *pModal;
2872 int i, regChainOffset;
2873 uint8_t txRxAttenLocal; /* workaround for eeprom versions <= 14.2 */
2875 HALASSERT(AH_PRIVATE(ah)->ah_eeversion >= AR_EEPROM_VER14_1);
2876 pModal = &(eep->modalHeader[IS_CHAN_2GHZ(chan)]);
2878 txRxAttenLocal = IS_CHAN_2GHZ(chan) ? 23 : 38; /* workaround for eeprom versions <= 14.2 */
2880 OS_REG_WRITE(ah, AR_PHY_SWITCH_COM, pModal->antCtrlCommon);
2881 for (i = 0; i < AR5416_MAX_CHAINS; i++) {
2882 if (AR_SREV_OWL_20_OR_LATER(ah) &&
2883 (AH5416(ah)->ah_rx_chainmask == 0x5 ||
2884 AH5416(ah)->ah_tx_chainmask == 0x5) && i != 0) {
2885 /* Regs are swapped from chain 2 to 1 for 5416 2_0 with
2886 * only chains 0 and 2 populated
2888 regChainOffset = (i == 1) ? 0x2000 : 0x1000;
2889 } else {
2890 regChainOffset = i * 0x1000;
2893 OS_REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0 + regChainOffset, pModal->antCtrlChain[i]);
2894 OS_REG_WRITE(ah, AR_PHY_TIMING_CTRL4 + regChainOffset,
2895 (OS_REG_READ(ah, AR_PHY_TIMING_CTRL4 + regChainOffset) &
2896 ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF | AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) |
2897 SM(pModal->iqCalICh[i], AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) |
2898 SM(pModal->iqCalQCh[i], AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF));
2901 * Large signal upgrade.
2904 if ((i == 0) || AR_SREV_OWL_20_OR_LATER(ah)) {
2905 OS_REG_WRITE(ah, AR_PHY_RXGAIN + regChainOffset,
2906 (OS_REG_READ(ah, AR_PHY_RXGAIN + regChainOffset) & ~AR_PHY_RXGAIN_TXRX_ATTEN) |
2907 SM(IS_EEP_MINOR_V3(ah) ? pModal->txRxAttenCh[i] : txRxAttenLocal,
2908 AR_PHY_RXGAIN_TXRX_ATTEN));
2910 OS_REG_WRITE(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
2911 (OS_REG_READ(ah, AR_PHY_GAIN_2GHZ + regChainOffset) & ~AR_PHY_GAIN_2GHZ_RXTX_MARGIN) |
2912 SM(pModal->rxTxMarginCh[i], AR_PHY_GAIN_2GHZ_RXTX_MARGIN));
2916 OS_REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH, pModal->switchSettling);
2917 OS_REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_ADC, pModal->adcDesiredSize);
2918 OS_REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_PGA, pModal->pgaDesiredSize);
2919 OS_REG_WRITE(ah, AR_PHY_RF_CTL4,
2920 SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAA_OFF)
2921 | SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAB_OFF)
2922 | SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAA_ON)
2923 | SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAB_ON));
2925 OS_REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON, pModal->txEndToRxOn);
2927 if (AR_SREV_MERLIN_10_OR_LATER(ah)) {
2928 OS_REG_RMW_FIELD(ah, AR_PHY_CCA, AR9280_PHY_CCA_THRESH62,
2929 pModal->thresh62);
2930 OS_REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0, AR_PHY_EXT_CCA0_THRESH62,
2931 pModal->thresh62);
2932 } else {
2933 OS_REG_RMW_FIELD(ah, AR_PHY_CCA, AR_PHY_CCA_THRESH62,
2934 pModal->thresh62);
2935 OS_REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0, AR_PHY_EXT_CCA_THRESH62,
2936 pModal->thresh62);
2939 /* Minor Version Specific application */
2940 if (IS_EEP_MINOR_V2(ah)) {
2941 OS_REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_FRAME_TO_DATA_START, pModal->txFrameToDataStart);
2942 OS_REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_FRAME_TO_PA_ON, pModal->txFrameToPaOn);
2945 if (IS_EEP_MINOR_V3(ah)) {
2946 if (IS_CHAN_HT40(chan)) {
2947 /* Overwrite switch settling with HT40 value */
2948 OS_REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH, pModal->swSettleHt40);
2951 if ((AR_SREV_OWL_20_OR_LATER(ah)) &&
2952 ( AH5416(ah)->ah_rx_chainmask == 0x5 || AH5416(ah)->ah_tx_chainmask == 0x5)){
2953 /* Reg Offsets are swapped for logical mapping */
2954 OS_REG_WRITE(ah, AR_PHY_GAIN_2GHZ + 0x1000, (OS_REG_READ(ah, AR_PHY_GAIN_2GHZ + 0x1000) & ~AR_PHY_GAIN_2GHZ_BSW_MARGIN) |
2955 SM(pModal->bswMargin[2], AR_PHY_GAIN_2GHZ_BSW_MARGIN));
2956 OS_REG_WRITE(ah, AR_PHY_GAIN_2GHZ + 0x1000, (OS_REG_READ(ah, AR_PHY_GAIN_2GHZ + 0x1000) & ~AR_PHY_GAIN_2GHZ_BSW_ATTEN) |
2957 SM(pModal->bswAtten[2], AR_PHY_GAIN_2GHZ_BSW_ATTEN));
2958 OS_REG_WRITE(ah, AR_PHY_GAIN_2GHZ + 0x2000, (OS_REG_READ(ah, AR_PHY_GAIN_2GHZ + 0x2000) & ~AR_PHY_GAIN_2GHZ_BSW_MARGIN) |
2959 SM(pModal->bswMargin[1], AR_PHY_GAIN_2GHZ_BSW_MARGIN));
2960 OS_REG_WRITE(ah, AR_PHY_GAIN_2GHZ + 0x2000, (OS_REG_READ(ah, AR_PHY_GAIN_2GHZ + 0x2000) & ~AR_PHY_GAIN_2GHZ_BSW_ATTEN) |
2961 SM(pModal->bswAtten[1], AR_PHY_GAIN_2GHZ_BSW_ATTEN));
2962 } else {
2963 OS_REG_WRITE(ah, AR_PHY_GAIN_2GHZ + 0x1000, (OS_REG_READ(ah, AR_PHY_GAIN_2GHZ + 0x1000) & ~AR_PHY_GAIN_2GHZ_BSW_MARGIN) |
2964 SM(pModal->bswMargin[1], AR_PHY_GAIN_2GHZ_BSW_MARGIN));
2965 OS_REG_WRITE(ah, AR_PHY_GAIN_2GHZ + 0x1000, (OS_REG_READ(ah, AR_PHY_GAIN_2GHZ + 0x1000) & ~AR_PHY_GAIN_2GHZ_BSW_ATTEN) |
2966 SM(pModal->bswAtten[1], AR_PHY_GAIN_2GHZ_BSW_ATTEN));
2967 OS_REG_WRITE(ah, AR_PHY_GAIN_2GHZ + 0x2000, (OS_REG_READ(ah, AR_PHY_GAIN_2GHZ + 0x2000) & ~AR_PHY_GAIN_2GHZ_BSW_MARGIN) |
2968 SM(pModal->bswMargin[2],AR_PHY_GAIN_2GHZ_BSW_MARGIN));
2969 OS_REG_WRITE(ah, AR_PHY_GAIN_2GHZ + 0x2000, (OS_REG_READ(ah, AR_PHY_GAIN_2GHZ + 0x2000) & ~AR_PHY_GAIN_2GHZ_BSW_ATTEN) |
2970 SM(pModal->bswAtten[2], AR_PHY_GAIN_2GHZ_BSW_ATTEN));
2972 OS_REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ, AR_PHY_GAIN_2GHZ_BSW_MARGIN, pModal->bswMargin[0]);
2973 OS_REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ, AR_PHY_GAIN_2GHZ_BSW_ATTEN, pModal->bswAtten[0]);
2975 return AH_TRUE;
2979 * Helper functions common for AP/CB/XB
2983 * ar5416SetPowerPerRateTable
2985 * Sets the transmit power in the baseband for the given
2986 * operating channel and mode.
2988 static HAL_BOOL
2989 ar5416SetPowerPerRateTable(struct ath_hal *ah, struct ar5416eeprom *pEepData,
2990 HAL_CHANNEL_INTERNAL *chan,
2991 int16_t *ratesArray, uint16_t cfgCtl,
2992 uint16_t AntennaReduction,
2993 uint16_t twiceMaxRegulatoryPower,
2994 uint16_t powerLimit)
2996 #define N(a) (sizeof(a)/sizeof(a[0]))
2997 /* Local defines to distinguish between extension and control CTL's */
2998 #define EXT_ADDITIVE (0x8000)
2999 #define CTL_11A_EXT (CTL_11A | EXT_ADDITIVE)
3000 #define CTL_11G_EXT (CTL_11G | EXT_ADDITIVE)
3001 #define CTL_11B_EXT (CTL_11B | EXT_ADDITIVE)
3003 uint16_t twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
3004 int i;
3005 int16_t twiceLargestAntenna;
3006 CAL_CTL_DATA *rep;
3007 CAL_TARGET_POWER_LEG targetPowerOfdm, targetPowerCck = {0, {0, 0, 0, 0}};
3008 CAL_TARGET_POWER_LEG targetPowerOfdmExt = {0, {0, 0, 0, 0}}, targetPowerCckExt = {0, {0, 0, 0, 0}};
3009 CAL_TARGET_POWER_HT targetPowerHt20, targetPowerHt40 = {0, {0, 0, 0, 0}};
3010 int16_t scaledPower, minCtlPower;
3012 #define SUB_NUM_CTL_MODES_AT_5G_40 2 /* excluding HT40, EXT-OFDM */
3013 #define SUB_NUM_CTL_MODES_AT_2G_40 3 /* excluding HT40, EXT-OFDM, EXT-CCK */
3014 static const uint16_t ctlModesFor11a[] = {
3015 CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40
3017 static const uint16_t ctlModesFor11g[] = {
3018 CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT, CTL_11G_EXT, CTL_2GHT40
3020 const uint16_t *pCtlMode;
3021 uint16_t numCtlModes, ctlMode, freq;
3022 CHAN_CENTERS centers;
3024 ar5416GetChannelCenters(ah, chan, &centers);
3026 /* Compute TxPower reduction due to Antenna Gain */
3028 twiceLargestAntenna = AH_MAX(AH_MAX(pEepData->modalHeader[IS_CHAN_2GHZ(chan)].antennaGainCh[0],
3029 pEepData->modalHeader[IS_CHAN_2GHZ(chan)].antennaGainCh[1]),
3030 pEepData->modalHeader[IS_CHAN_2GHZ(chan)].antennaGainCh[2]);
3031 #if 0
3032 /* Turn it back on if we need to calculate per chain antenna gain reduction */
3033 /* Use only if the expected gain > 6dbi */
3034 /* Chain 0 is always used */
3035 twiceLargestAntenna = pEepData->modalHeader[IS_CHAN_2GHZ(chan)].antennaGainCh[0];
3037 /* Look at antenna gains of Chains 1 and 2 if the TX mask is set */
3038 if (ahp->ah_tx_chainmask & 0x2)
3039 twiceLargestAntenna = AH_MAX(twiceLargestAntenna,
3040 pEepData->modalHeader[IS_CHAN_2GHZ(chan)].antennaGainCh[1]);
3042 if (ahp->ah_tx_chainmask & 0x4)
3043 twiceLargestAntenna = AH_MAX(twiceLargestAntenna,
3044 pEepData->modalHeader[IS_CHAN_2GHZ(chan)].antennaGainCh[2]);
3045 #endif
3046 twiceLargestAntenna = (int16_t)AH_MIN((AntennaReduction) - twiceLargestAntenna, 0);
3048 /* XXX setup for 5212 use (really used?) */
3049 ath_hal_eepromSet(ah,
3050 IS_CHAN_2GHZ(chan) ? AR_EEP_ANTGAINMAX_2 : AR_EEP_ANTGAINMAX_5,
3051 twiceLargestAntenna);
3054 * scaledPower is the minimum of the user input power level and
3055 * the regulatory allowed power level
3057 scaledPower = AH_MIN(powerLimit, twiceMaxRegulatoryPower + twiceLargestAntenna);
3059 /* Reduce scaled Power by number of chains active to get to per chain tx power level */
3060 /* TODO: better value than these? */
3061 switch (owl_get_ntxchains(AH5416(ah)->ah_tx_chainmask)) {
3062 case 1:
3063 break;
3064 case 2:
3065 scaledPower -= pEepData->modalHeader[IS_CHAN_2GHZ(chan)].pwrDecreaseFor2Chain;
3066 break;
3067 case 3:
3068 scaledPower -= pEepData->modalHeader[IS_CHAN_2GHZ(chan)].pwrDecreaseFor3Chain;
3069 break;
3070 default:
3071 return AH_FALSE; /* Unsupported number of chains */
3074 scaledPower = AH_MAX(0, scaledPower);
3076 /* Get target powers from EEPROM - our baseline for TX Power */
3077 if (IS_CHAN_2GHZ(chan)) {
3078 /* Setup for CTL modes */
3079 numCtlModes = N(ctlModesFor11g) - SUB_NUM_CTL_MODES_AT_2G_40; /* CTL_11B, CTL_11G, CTL_2GHT20 */
3080 pCtlMode = ctlModesFor11g;
3082 ar5416GetTargetPowersLeg(ah, chan, pEepData->calTargetPowerCck,
3083 AR5416_NUM_2G_CCK_TARGET_POWERS, &targetPowerCck, 4, AH_FALSE);
3084 ar5416GetTargetPowersLeg(ah, chan, pEepData->calTargetPower2G,
3085 AR5416_NUM_2G_20_TARGET_POWERS, &targetPowerOfdm, 4, AH_FALSE);
3086 ar5416GetTargetPowers(ah, chan, pEepData->calTargetPower2GHT20,
3087 AR5416_NUM_2G_20_TARGET_POWERS, &targetPowerHt20, 8, AH_FALSE);
3089 if (IS_CHAN_HT40(chan)) {
3090 numCtlModes = N(ctlModesFor11g); /* All 2G CTL's */
3092 ar5416GetTargetPowers(ah, chan, pEepData->calTargetPower2GHT40,
3093 AR5416_NUM_2G_40_TARGET_POWERS, &targetPowerHt40, 8, AH_TRUE);
3094 /* Get target powers for extension channels */
3095 ar5416GetTargetPowersLeg(ah, chan, pEepData->calTargetPowerCck,
3096 AR5416_NUM_2G_CCK_TARGET_POWERS, &targetPowerCckExt, 4, AH_TRUE);
3097 ar5416GetTargetPowersLeg(ah, chan, pEepData->calTargetPower2G,
3098 AR5416_NUM_2G_20_TARGET_POWERS, &targetPowerOfdmExt, 4, AH_TRUE);
3100 } else {
3101 /* Setup for CTL modes */
3102 numCtlModes = N(ctlModesFor11a) - SUB_NUM_CTL_MODES_AT_5G_40; /* CTL_11A, CTL_5GHT20 */
3103 pCtlMode = ctlModesFor11a;
3105 ar5416GetTargetPowersLeg(ah, chan, pEepData->calTargetPower5G,
3106 AR5416_NUM_5G_20_TARGET_POWERS, &targetPowerOfdm, 4, AH_FALSE);
3107 ar5416GetTargetPowers(ah, chan, pEepData->calTargetPower5GHT20,
3108 AR5416_NUM_5G_20_TARGET_POWERS, &targetPowerHt20, 8, AH_FALSE);
3110 if (IS_CHAN_HT40(chan)) {
3111 numCtlModes = N(ctlModesFor11a); /* All 5G CTL's */
3113 ar5416GetTargetPowers(ah, chan, pEepData->calTargetPower5GHT40,
3114 AR5416_NUM_5G_40_TARGET_POWERS, &targetPowerHt40, 8, AH_TRUE);
3115 ar5416GetTargetPowersLeg(ah, chan, pEepData->calTargetPower5G,
3116 AR5416_NUM_5G_20_TARGET_POWERS, &targetPowerOfdmExt, 4, AH_TRUE);
3121 * For MIMO, need to apply regulatory caps individually across dynamically
3122 * running modes: CCK, OFDM, HT20, HT40
3124 * The outer loop walks through each possible applicable runtime mode.
3125 * The inner loop walks through each ctlIndex entry in EEPROM.
3126 * The ctl value is encoded as [7:4] == test group, [3:0] == test mode.
3129 for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) {
3131 HAL_BOOL isHt40CtlMode = (pCtlMode[ctlMode] == CTL_5GHT40) ||
3132 (pCtlMode[ctlMode] == CTL_2GHT40);
3133 if (isHt40CtlMode) {
3134 freq = centers.ctl_center;
3135 } else if (pCtlMode[ctlMode] & EXT_ADDITIVE) {
3136 freq = centers.ext_center;
3137 } else {
3138 freq = centers.ctl_center;
3141 /* walk through each CTL index stored in EEPROM */
3142 for (i = 0; (i < AR5416_NUM_CTLS) && pEepData->ctlIndex[i]; i++) {
3143 uint16_t twiceMinEdgePower;
3145 /* compare test group from regulatory channel list with test mode from pCtlMode list */
3146 if ((((cfgCtl & ~CTL_MODE_M) | (pCtlMode[ctlMode] & CTL_MODE_M)) == pEepData->ctlIndex[i]) ||
3147 (((cfgCtl & ~CTL_MODE_M) | (pCtlMode[ctlMode] & CTL_MODE_M)) ==
3148 ((pEepData->ctlIndex[i] & CTL_MODE_M) | SD_NO_CTL))) {
3149 rep = &(pEepData->ctlData[i]);
3150 twiceMinEdgePower = ar5416GetMaxEdgePower(freq,
3151 rep->ctlEdges[owl_get_ntxchains(AH5416(ah)->ah_tx_chainmask) - 1],
3152 IS_CHAN_2GHZ(chan));
3153 if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) {
3154 /* Find the minimum of all CTL edge powers that apply to this channel */
3155 twiceMaxEdgePower = AH_MIN(twiceMaxEdgePower, twiceMinEdgePower);
3156 } else {
3157 /* specific */
3158 twiceMaxEdgePower = twiceMinEdgePower;
3159 break;
3163 minCtlPower = (uint8_t)AH_MIN(twiceMaxEdgePower, scaledPower);
3164 /* Apply ctl mode to correct target power set */
3165 switch(pCtlMode[ctlMode]) {
3166 case CTL_11B:
3167 for (i = 0; i < N(targetPowerCck.tPow2x); i++) {
3168 targetPowerCck.tPow2x[i] = (uint8_t)AH_MIN(targetPowerCck.tPow2x[i], minCtlPower);
3170 break;
3171 case CTL_11A:
3172 case CTL_11G:
3173 for (i = 0; i < N(targetPowerOfdm.tPow2x); i++) {
3174 targetPowerOfdm.tPow2x[i] = (uint8_t)AH_MIN(targetPowerOfdm.tPow2x[i], minCtlPower);
3176 break;
3177 case CTL_5GHT20:
3178 case CTL_2GHT20:
3179 for (i = 0; i < N(targetPowerHt20.tPow2x); i++) {
3180 targetPowerHt20.tPow2x[i] = (uint8_t)AH_MIN(targetPowerHt20.tPow2x[i], minCtlPower);
3182 break;
3183 case CTL_11B_EXT:
3184 targetPowerCckExt.tPow2x[0] = (uint8_t)AH_MIN(targetPowerCckExt.tPow2x[0], minCtlPower);
3185 break;
3186 case CTL_11A_EXT:
3187 case CTL_11G_EXT:
3188 targetPowerOfdmExt.tPow2x[0] = (uint8_t)AH_MIN(targetPowerOfdmExt.tPow2x[0], minCtlPower);
3189 break;
3190 case CTL_5GHT40:
3191 case CTL_2GHT40:
3192 for (i = 0; i < N(targetPowerHt40.tPow2x); i++) {
3193 targetPowerHt40.tPow2x[i] = (uint8_t)AH_MIN(targetPowerHt40.tPow2x[i], minCtlPower);
3195 break;
3196 default:
3197 return AH_FALSE;
3198 break;
3200 } /* end ctl mode checking */
3202 /* Set rates Array from collected data */
3203 ratesArray[rate6mb] = ratesArray[rate9mb] = ratesArray[rate12mb] = ratesArray[rate18mb] = ratesArray[rate24mb] = targetPowerOfdm.tPow2x[0];
3204 ratesArray[rate36mb] = targetPowerOfdm.tPow2x[1];
3205 ratesArray[rate48mb] = targetPowerOfdm.tPow2x[2];
3206 ratesArray[rate54mb] = targetPowerOfdm.tPow2x[3];
3207 ratesArray[rateXr] = targetPowerOfdm.tPow2x[0];
3209 for (i = 0; i < N(targetPowerHt20.tPow2x); i++) {
3210 ratesArray[rateHt20_0 + i] = targetPowerHt20.tPow2x[i];
3213 if (IS_CHAN_2GHZ(chan)) {
3214 ratesArray[rate1l] = targetPowerCck.tPow2x[0];
3215 ratesArray[rate2s] = ratesArray[rate2l] = targetPowerCck.tPow2x[1];
3216 ratesArray[rate5_5s] = ratesArray[rate5_5l] = targetPowerCck.tPow2x[2];
3217 ratesArray[rate11s] = ratesArray[rate11l] = targetPowerCck.tPow2x[3];
3219 if (IS_CHAN_HT40(chan)) {
3220 for (i = 0; i < N(targetPowerHt40.tPow2x); i++) {
3221 ratesArray[rateHt40_0 + i] = targetPowerHt40.tPow2x[i];
3223 ratesArray[rateDupOfdm] = targetPowerHt40.tPow2x[0];
3224 ratesArray[rateDupCck] = targetPowerHt40.tPow2x[0];
3225 ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0];
3226 if (IS_CHAN_2GHZ(chan)) {
3227 ratesArray[rateExtCck] = targetPowerCckExt.tPow2x[0];
3230 return AH_TRUE;
3231 #undef EXT_ADDITIVE
3232 #undef CTL_11A_EXT
3233 #undef CTL_11G_EXT
3234 #undef CTL_11B_EXT
3235 #undef SUB_NUM_CTL_MODES_AT_5G_40
3236 #undef SUB_NUM_CTL_MODES_AT_2G_40
3237 #undef N
3240 /**************************************************************************
3241 * fbin2freq
3243 * Get channel value from binary representation held in eeprom
3244 * RETURNS: the frequency in MHz
3246 static uint16_t
3247 fbin2freq(uint8_t fbin, HAL_BOOL is2GHz)
3250 * Reserved value 0xFF provides an empty definition both as
3251 * an fbin and as a frequency - do not convert
3253 if (fbin == AR5416_BCHAN_UNUSED) {
3254 return fbin;
3257 return (uint16_t)((is2GHz) ? (2300 + fbin) : (4800 + 5 * fbin));
3261 * ar5416GetMaxEdgePower
3263 * Find the maximum conformance test limit for the given channel and CTL info
3265 static uint16_t
3266 ar5416GetMaxEdgePower(uint16_t freq, CAL_CTL_EDGES *pRdEdgesPower, HAL_BOOL is2GHz)
3268 uint16_t twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
3269 int i;
3271 /* Get the edge power */
3272 for (i = 0; (i < AR5416_NUM_BAND_EDGES) && (pRdEdgesPower[i].bChannel != AR5416_BCHAN_UNUSED) ; i++) {
3274 * If there's an exact channel match or an inband flag set
3275 * on the lower channel use the given rdEdgePower
3277 if (freq == fbin2freq(pRdEdgesPower[i].bChannel, is2GHz)) {
3278 twiceMaxEdgePower = MS(pRdEdgesPower[i].tPowerFlag, CAL_CTL_EDGES_POWER);
3279 break;
3280 } else if ((i > 0) && (freq < fbin2freq(pRdEdgesPower[i].bChannel, is2GHz))) {
3281 if (fbin2freq(pRdEdgesPower[i - 1].bChannel, is2GHz) < freq && (pRdEdgesPower[i - 1].tPowerFlag & CAL_CTL_EDGES_FLAG) != 0) {
3282 twiceMaxEdgePower = MS(pRdEdgesPower[i - 1].tPowerFlag, CAL_CTL_EDGES_POWER);
3284 /* Leave loop - no more affecting edges possible in this monotonic increasing list */
3285 break;
3288 HALASSERT(twiceMaxEdgePower > 0);
3289 return twiceMaxEdgePower;
3292 /**************************************************************
3293 * ar5416GetTargetPowers
3295 * Return the rates of target power for the given target power table
3296 * channel, and number of channels
3298 static void
3299 ar5416GetTargetPowers(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan,
3300 CAL_TARGET_POWER_HT *powInfo, uint16_t numChannels,
3301 CAL_TARGET_POWER_HT *pNewPower, uint16_t numRates,
3302 HAL_BOOL isHt40Target)
3304 uint16_t clo, chi;
3305 int i;
3306 int matchIndex = -1, lowIndex = -1;
3307 uint16_t freq;
3308 CHAN_CENTERS centers;
3310 ar5416GetChannelCenters(ah, chan, &centers);
3311 freq = isHt40Target ? centers.synth_center : centers.ctl_center;
3313 /* Copy the target powers into the temp channel list */
3314 if (freq <= fbin2freq(powInfo[0].bChannel, IS_CHAN_2GHZ(chan))) {
3315 matchIndex = 0;
3316 } else {
3317 for (i = 0; (i < numChannels) && (powInfo[i].bChannel != AR5416_BCHAN_UNUSED); i++) {
3318 if (freq == fbin2freq(powInfo[i].bChannel, IS_CHAN_2GHZ(chan))) {
3319 matchIndex = i;
3320 break;
3321 } else if ((freq < fbin2freq(powInfo[i].bChannel, IS_CHAN_2GHZ(chan))) &&
3322 (freq > fbin2freq(powInfo[i - 1].bChannel, IS_CHAN_2GHZ(chan))))
3324 lowIndex = i - 1;
3325 break;
3328 if ((matchIndex == -1) && (lowIndex == -1)) {
3329 HALASSERT(freq > fbin2freq(powInfo[i - 1].bChannel, IS_CHAN_2GHZ(chan)));
3330 matchIndex = i - 1;
3334 if (matchIndex != -1) {
3335 OS_MEMCPY(pNewPower, &powInfo[matchIndex], sizeof(*pNewPower));
3336 } else {
3337 HALASSERT(lowIndex != -1);
3339 * Get the lower and upper channels, target powers,
3340 * and interpolate between them.
3342 clo = fbin2freq(powInfo[lowIndex].bChannel, IS_CHAN_2GHZ(chan));
3343 chi = fbin2freq(powInfo[lowIndex + 1].bChannel, IS_CHAN_2GHZ(chan));
3345 for (i = 0; i < numRates; i++) {
3346 pNewPower->tPow2x[i] = (uint8_t)interpolate(freq, clo, chi,
3347 powInfo[lowIndex].tPow2x[i], powInfo[lowIndex + 1].tPow2x[i]);
3351 /**************************************************************
3352 * ar5416GetTargetPowersLeg
3354 * Return the four rates of target power for the given target power table
3355 * channel, and number of channels
3357 static void
3358 ar5416GetTargetPowersLeg(struct ath_hal *ah,
3359 HAL_CHANNEL_INTERNAL *chan,
3360 CAL_TARGET_POWER_LEG *powInfo, uint16_t numChannels,
3361 CAL_TARGET_POWER_LEG *pNewPower, uint16_t numRates,
3362 HAL_BOOL isExtTarget)
3364 uint16_t clo, chi;
3365 int i;
3366 int matchIndex = -1, lowIndex = -1;
3367 uint16_t freq;
3368 CHAN_CENTERS centers;
3370 ar5416GetChannelCenters(ah, chan, &centers);
3371 freq = (isExtTarget) ? centers.ext_center :centers.ctl_center;
3373 /* Copy the target powers into the temp channel list */
3374 if (freq <= fbin2freq(powInfo[0].bChannel, IS_CHAN_2GHZ(chan))) {
3375 matchIndex = 0;
3376 } else {
3377 for (i = 0; (i < numChannels) && (powInfo[i].bChannel != AR5416_BCHAN_UNUSED); i++) {
3378 if (freq == fbin2freq(powInfo[i].bChannel, IS_CHAN_2GHZ(chan))) {
3379 matchIndex = i;
3380 break;
3381 } else if ((freq < fbin2freq(powInfo[i].bChannel, IS_CHAN_2GHZ(chan))) &&
3382 (freq > fbin2freq(powInfo[i - 1].bChannel, IS_CHAN_2GHZ(chan))))
3384 lowIndex = i - 1;
3385 break;
3388 if ((matchIndex == -1) && (lowIndex == -1)) {
3389 HALASSERT(freq > fbin2freq(powInfo[i - 1].bChannel, IS_CHAN_2GHZ(chan)));
3390 matchIndex = i - 1;
3394 if (matchIndex != -1) {
3395 OS_MEMCPY(pNewPower, &powInfo[matchIndex], sizeof(*pNewPower));
3396 } else {
3397 HALASSERT(lowIndex != -1);
3399 * Get the lower and upper channels, target powers,
3400 * and interpolate between them.
3402 clo = fbin2freq(powInfo[lowIndex].bChannel, IS_CHAN_2GHZ(chan));
3403 chi = fbin2freq(powInfo[lowIndex + 1].bChannel, IS_CHAN_2GHZ(chan));
3405 for (i = 0; i < numRates; i++) {
3406 pNewPower->tPow2x[i] = (uint8_t)interpolate(freq, clo, chi,
3407 powInfo[lowIndex].tPow2x[i], powInfo[lowIndex + 1].tPow2x[i]);
3412 /**************************************************************
3413 * ar5416SetPowerCalTable
3415 * Pull the PDADC piers from cal data and interpolate them across the given
3416 * points as well as from the nearest pier(s) to get a power detector
3417 * linear voltage to power level table.
3419 static HAL_BOOL
3420 ar5416SetPowerCalTable(struct ath_hal *ah, struct ar5416eeprom *pEepData, HAL_CHANNEL_INTERNAL *chan, int16_t *pTxPowerIndexOffset)
3422 CAL_DATA_PER_FREQ *pRawDataset;
3423 uint8_t *pCalBChans = AH_NULL;
3424 uint16_t pdGainOverlap_t2;
3425 static uint8_t pdadcValues[AR5416_NUM_PDADC_VALUES];
3426 uint16_t gainBoundaries[AR5416_PD_GAINS_IN_MASK];
3427 uint16_t numPiers, i, j;
3428 int16_t tMinCalPower;
3429 uint16_t numXpdGain, xpdMask;
3430 uint16_t xpdGainValues[AR5416_NUM_PD_GAINS];
3431 uint32_t reg32, regOffset, regChainOffset;
3433 ath_hal_memzero(xpdGainValues, sizeof(xpdGainValues));
3435 xpdMask = pEepData->modalHeader[IS_CHAN_2GHZ(chan)].xpdGain;
3437 if (IS_EEP_MINOR_V2(ah)) {
3438 pdGainOverlap_t2 = pEepData->modalHeader[IS_CHAN_2GHZ(chan)].pdGainOverlap;
3439 } else {
3440 pdGainOverlap_t2 = (uint16_t)(MS(OS_REG_READ(ah, AR_PHY_TPCRG5), AR_PHY_TPCRG5_PD_GAIN_OVERLAP));
3443 if (IS_CHAN_2GHZ(chan)) {
3444 pCalBChans = pEepData->calFreqPier2G;
3445 numPiers = AR5416_NUM_2G_CAL_PIERS;
3446 } else {
3447 pCalBChans = pEepData->calFreqPier5G;
3448 numPiers = AR5416_NUM_5G_CAL_PIERS;
3451 numXpdGain = 0;
3452 /* Calculate the value of xpdgains from the xpdGain Mask */
3453 for (i = 1; i <= AR5416_PD_GAINS_IN_MASK; i++) {
3454 if ((xpdMask >> (AR5416_PD_GAINS_IN_MASK - i)) & 1) {
3455 if (numXpdGain >= AR5416_NUM_PD_GAINS) {
3456 HALASSERT(0);
3457 break;
3459 xpdGainValues[numXpdGain] = (uint16_t)(AR5416_PD_GAINS_IN_MASK - i);
3460 numXpdGain++;
3464 /* Write the detector gain biases and their number */
3465 OS_REG_WRITE(ah, AR_PHY_TPCRG1, (OS_REG_READ(ah, AR_PHY_TPCRG1) &
3466 ~(AR_PHY_TPCRG1_NUM_PD_GAIN | AR_PHY_TPCRG1_PD_GAIN_1 | AR_PHY_TPCRG1_PD_GAIN_2 | AR_PHY_TPCRG1_PD_GAIN_3)) |
3467 SM(numXpdGain - 1, AR_PHY_TPCRG1_NUM_PD_GAIN) | SM(xpdGainValues[0], AR_PHY_TPCRG1_PD_GAIN_1 ) |
3468 SM(xpdGainValues[1], AR_PHY_TPCRG1_PD_GAIN_2) | SM(xpdGainValues[2], AR_PHY_TPCRG1_PD_GAIN_3));
3470 for (i = 0; i < AR5416_MAX_CHAINS; i++) {
3472 if (AR_SREV_OWL_20_OR_LATER(ah) &&
3473 ( AH5416(ah)->ah_rx_chainmask == 0x5 || AH5416(ah)->ah_tx_chainmask == 0x5) && (i != 0)) {
3474 /* Regs are swapped from chain 2 to 1 for 5416 2_0 with
3475 * only chains 0 and 2 populated
3477 regChainOffset = (i == 1) ? 0x2000 : 0x1000;
3478 } else {
3479 regChainOffset = i * 0x1000;
3482 if (pEepData->baseEepHeader.txMask & (1 << i)) {
3483 if (IS_CHAN_2GHZ(chan)) {
3484 pRawDataset = pEepData->calPierData2G[i];
3485 } else {
3486 pRawDataset = pEepData->calPierData5G[i];
3489 ar5416GetGainBoundariesAndPdadcs(ah, chan, pRawDataset,
3490 pCalBChans, numPiers,
3491 pdGainOverlap_t2,
3492 &tMinCalPower, gainBoundaries,
3493 pdadcValues, numXpdGain);
3495 if ((i == 0) || AR_SREV_OWL_20_OR_LATER(ah)) {
3497 * Note the pdadc table may not start at 0 dBm power, could be
3498 * negative or greater than 0. Need to offset the power
3499 * values by the amount of minPower for griffin
3502 OS_REG_WRITE(ah, AR_PHY_TPCRG5 + regChainOffset,
3503 SM(pdGainOverlap_t2, AR_PHY_TPCRG5_PD_GAIN_OVERLAP) |
3504 SM(gainBoundaries[0], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1) |
3505 SM(gainBoundaries[1], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2) |
3506 SM(gainBoundaries[2], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3) |
3507 SM(gainBoundaries[3], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4));
3510 /* Write the power values into the baseband power table */
3511 regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset;
3513 for (j = 0; j < 32; j++) {
3514 reg32 = ((pdadcValues[4*j + 0] & 0xFF) << 0) |
3515 ((pdadcValues[4*j + 1] & 0xFF) << 8) |
3516 ((pdadcValues[4*j + 2] & 0xFF) << 16) |
3517 ((pdadcValues[4*j + 3] & 0xFF) << 24) ;
3518 OS_REG_WRITE(ah, regOffset, reg32);
3520 #ifdef PDADC_DUMP
3521 ath_hal_printf(ah, "PDADC: Chain %d | PDADC %3d Value %3d | PDADC %3d Value %3d | PDADC %3d Value %3d | PDADC %3d Value %3d |\n",
3523 4*j, pdadcValues[4*j],
3524 4*j+1, pdadcValues[4*j + 1],
3525 4*j+2, pdadcValues[4*j + 2],
3526 4*j+3, pdadcValues[4*j + 3]);
3527 #endif
3528 regOffset += 4;
3532 *pTxPowerIndexOffset = 0;
3534 return AH_TRUE;
3537 /**************************************************************
3538 * ar5416GetGainBoundariesAndPdadcs
3540 * Uses the data points read from EEPROM to reconstruct the pdadc power table
3541 * Called by ar5416SetPowerCalTable only.
3543 static void
3544 ar5416GetGainBoundariesAndPdadcs(struct ath_hal *ah,
3545 HAL_CHANNEL_INTERNAL *chan, CAL_DATA_PER_FREQ *pRawDataSet,
3546 uint8_t * bChans, uint16_t availPiers,
3547 uint16_t tPdGainOverlap, int16_t *pMinCalPower, uint16_t * pPdGainBoundaries,
3548 uint8_t * pPDADCValues, uint16_t numXpdGains)
3551 int i, j, k;
3552 int16_t ss; /* potentially -ve index for taking care of pdGainOverlap */
3553 uint16_t idxL, idxR, numPiers; /* Pier indexes */
3555 /* filled out Vpd table for all pdGains (chanL) */
3556 static uint8_t vpdTableL[AR5416_NUM_PD_GAINS][AR5416_MAX_PWR_RANGE_IN_HALF_DB];
3558 /* filled out Vpd table for all pdGains (chanR) */
3559 static uint8_t vpdTableR[AR5416_NUM_PD_GAINS][AR5416_MAX_PWR_RANGE_IN_HALF_DB];
3561 /* filled out Vpd table for all pdGains (interpolated) */
3562 static uint8_t vpdTableI[AR5416_NUM_PD_GAINS][AR5416_MAX_PWR_RANGE_IN_HALF_DB];
3564 uint8_t *pVpdL, *pVpdR, *pPwrL, *pPwrR;
3565 uint8_t minPwrT4[AR5416_NUM_PD_GAINS];
3566 uint8_t maxPwrT4[AR5416_NUM_PD_GAINS];
3567 int16_t vpdStep;
3568 int16_t tmpVal;
3569 uint16_t sizeCurrVpdTable, maxIndex, tgtIndex;
3570 HAL_BOOL match;
3571 int16_t minDelta = 0;
3572 CHAN_CENTERS centers;
3574 ar5416GetChannelCenters(ah, chan, &centers);
3576 /* Trim numPiers for the number of populated channel Piers */
3577 for (numPiers = 0; numPiers < availPiers; numPiers++) {
3578 if (bChans[numPiers] == AR5416_BCHAN_UNUSED) {
3579 break;
3583 /* Find pier indexes around the current channel */
3584 match = getLowerUpperIndex((uint8_t)FREQ2FBIN(centers.synth_center, IS_CHAN_2GHZ(chan)),
3585 bChans, numPiers, &idxL, &idxR);
3587 if (match) {
3588 /* Directly fill both vpd tables from the matching index */
3589 for (i = 0; i < numXpdGains; i++) {
3590 minPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][0];
3591 maxPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][4];
3592 ar5416FillVpdTable(minPwrT4[i], maxPwrT4[i], pRawDataSet[idxL].pwrPdg[i],
3593 pRawDataSet[idxL].vpdPdg[i], AR5416_PD_GAIN_ICEPTS, vpdTableI[i]);
3595 } else {
3596 for (i = 0; i < numXpdGains; i++) {
3597 pVpdL = pRawDataSet[idxL].vpdPdg[i];
3598 pPwrL = pRawDataSet[idxL].pwrPdg[i];
3599 pVpdR = pRawDataSet[idxR].vpdPdg[i];
3600 pPwrR = pRawDataSet[idxR].pwrPdg[i];
3602 /* Start Vpd interpolation from the max of the minimum powers */
3603 minPwrT4[i] = AH_MAX(pPwrL[0], pPwrR[0]);
3605 /* End Vpd interpolation from the min of the max powers */
3606 maxPwrT4[i] = AH_MIN(pPwrL[AR5416_PD_GAIN_ICEPTS - 1], pPwrR[AR5416_PD_GAIN_ICEPTS - 1]);
3607 HALASSERT(maxPwrT4[i] > minPwrT4[i]);
3609 /* Fill pier Vpds */
3610 ar5416FillVpdTable(minPwrT4[i], maxPwrT4[i], pPwrL, pVpdL, AR5416_PD_GAIN_ICEPTS, vpdTableL[i]);
3611 ar5416FillVpdTable(minPwrT4[i], maxPwrT4[i], pPwrR, pVpdR, AR5416_PD_GAIN_ICEPTS, vpdTableR[i]);
3613 /* Interpolate the final vpd */
3614 for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) {
3615 vpdTableI[i][j] = (uint8_t)(interpolate((uint16_t)FREQ2FBIN(centers.synth_center, IS_CHAN_2GHZ(chan)),
3616 bChans[idxL], bChans[idxR], vpdTableL[i][j], vpdTableR[i][j]));
3620 *pMinCalPower = (int16_t)(minPwrT4[0] / 2);
3622 k = 0; /* index for the final table */
3623 for (i = 0; i < numXpdGains; i++) {
3624 if (i == (numXpdGains - 1)) {
3625 pPdGainBoundaries[i] = (uint16_t)(maxPwrT4[i] / 2);
3626 } else {
3627 pPdGainBoundaries[i] = (uint16_t)((maxPwrT4[i] + minPwrT4[i+1]) / 4);
3630 pPdGainBoundaries[i] = (uint16_t)AH_MIN(AR5416_MAX_RATE_POWER, pPdGainBoundaries[i]);
3632 if ((i == 0) && !AR_SREV_OWL_20_OR_LATER(ah) ) {
3634 * fix the gain delta, but get a delta that can be applied to min to
3635 * keep the upper power values accurate, don't think max needs to
3636 * be adjusted because should not be at that area of the table?
3638 minDelta = pPdGainBoundaries[0] - 23;
3639 pPdGainBoundaries[0] = 23;
3641 else {
3642 minDelta = 0;
3645 /* Find starting index for this pdGain */
3646 if (i == 0) {
3647 ss = 0; /* for the first pdGain, start from index 0 */
3648 } else {
3649 /* need overlap entries extrapolated below. */
3650 ss = (int16_t)((pPdGainBoundaries[i-1] - (minPwrT4[i] / 2)) - tPdGainOverlap + 1 + minDelta);
3652 vpdStep = (int16_t)(vpdTableI[i][1] - vpdTableI[i][0]);
3653 vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
3655 *-ve ss indicates need to extrapolate data below for this pdGain
3657 while ((ss < 0) && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
3658 tmpVal = (int16_t)(vpdTableI[i][0] + ss * vpdStep);
3659 pPDADCValues[k++] = (uint8_t)((tmpVal < 0) ? 0 : tmpVal);
3660 ss++;
3663 sizeCurrVpdTable = (uint8_t)((maxPwrT4[i] - minPwrT4[i]) / 2 +1);
3664 tgtIndex = (uint8_t)(pPdGainBoundaries[i] + tPdGainOverlap - (minPwrT4[i] / 2));
3665 maxIndex = (tgtIndex < sizeCurrVpdTable) ? tgtIndex : sizeCurrVpdTable;
3667 while ((ss < maxIndex) && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
3668 pPDADCValues[k++] = vpdTableI[i][ss++];
3671 vpdStep = (int16_t)(vpdTableI[i][sizeCurrVpdTable - 1] - vpdTableI[i][sizeCurrVpdTable - 2]);
3672 vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
3674 * for last gain, pdGainBoundary == Pmax_t2, so will
3675 * have to extrapolate
3677 if (tgtIndex > maxIndex) { /* need to extrapolate above */
3678 while ((ss <= tgtIndex) && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
3679 tmpVal = (int16_t)((vpdTableI[i][sizeCurrVpdTable - 1] +
3680 (ss - maxIndex +1) * vpdStep));
3681 pPDADCValues[k++] = (uint8_t)((tmpVal > 255) ? 255 : tmpVal);
3682 ss++;
3684 } /* extrapolated above */
3685 } /* for all pdGainUsed */
3687 /* Fill out pdGainBoundaries - only up to 2 allowed here, but hardware allows up to 4 */
3688 while (i < AR5416_PD_GAINS_IN_MASK) {
3689 pPdGainBoundaries[i] = pPdGainBoundaries[i-1];
3690 i++;
3693 while (k < AR5416_NUM_PDADC_VALUES) {
3694 pPDADCValues[k] = pPDADCValues[k-1];
3695 k++;
3697 return;
3700 /**************************************************************
3701 * getLowerUppderIndex
3703 * Return indices surrounding the value in sorted integer lists.
3704 * Requirement: the input list must be monotonically increasing
3705 * and populated up to the list size
3706 * Returns: match is set if an index in the array matches exactly
3707 * or a the target is before or after the range of the array.
3709 HAL_BOOL
3710 getLowerUpperIndex(uint8_t target, uint8_t *pList, uint16_t listSize,
3711 uint16_t *indexL, uint16_t *indexR)
3713 uint16_t i;
3716 * Check first and last elements for beyond ordered array cases.
3718 if (target <= pList[0]) {
3719 *indexL = *indexR = 0;
3720 return AH_TRUE;
3722 if (target >= pList[listSize-1]) {
3723 *indexL = *indexR = (uint16_t)(listSize - 1);
3724 return AH_TRUE;
3727 /* look for value being near or between 2 values in list */
3728 for (i = 0; i < listSize - 1; i++) {
3730 * If value is close to the current value of the list
3731 * then target is not between values, it is one of the values
3733 if (pList[i] == target) {
3734 *indexL = *indexR = i;
3735 return AH_TRUE;
3738 * Look for value being between current value and next value
3739 * if so return these 2 values
3741 if (target < pList[i + 1]) {
3742 *indexL = i;
3743 *indexR = (uint16_t)(i + 1);
3744 return AH_FALSE;
3747 HALASSERT(0);
3748 return AH_FALSE;
3751 /**************************************************************
3752 * ar5416FillVpdTable
3754 * Fill the Vpdlist for indices Pmax-Pmin
3755 * Note: pwrMin, pwrMax and Vpdlist are all in dBm * 4
3757 static HAL_BOOL
3758 ar5416FillVpdTable(uint8_t pwrMin, uint8_t pwrMax, uint8_t *pPwrList,
3759 uint8_t *pVpdList, uint16_t numIntercepts, uint8_t *pRetVpdList)
3761 uint16_t i, k;
3762 uint8_t currPwr = pwrMin;
3763 uint16_t idxL, idxR;
3765 HALASSERT(pwrMax > pwrMin);
3766 for (i = 0; i <= (pwrMax - pwrMin) / 2; i++) {
3767 getLowerUpperIndex(currPwr, pPwrList, numIntercepts,
3768 &(idxL), &(idxR));
3769 if (idxR < 1)
3770 idxR = 1; /* extrapolate below */
3771 if (idxL == numIntercepts - 1)
3772 idxL = (uint16_t)(numIntercepts - 2); /* extrapolate above */
3773 if (pPwrList[idxL] == pPwrList[idxR])
3774 k = pVpdList[idxL];
3775 else
3776 k = (uint16_t)( ((currPwr - pPwrList[idxL]) * pVpdList[idxR] + (pPwrList[idxR] - currPwr) * pVpdList[idxL]) /
3777 (pPwrList[idxR] - pPwrList[idxL]) );
3778 HALASSERT(k < 256);
3779 pRetVpdList[i] = (uint8_t)k;
3780 currPwr += 2; /* half dB steps */
3783 return AH_TRUE;
3786 /**************************************************************************
3787 * interpolate
3789 * Returns signed interpolated or the scaled up interpolated value
3791 static int16_t
3792 interpolate(uint16_t target, uint16_t srcLeft, uint16_t srcRight,
3793 int16_t targetLeft, int16_t targetRight)
3795 int16_t rv;
3797 if (srcRight == srcLeft) {
3798 rv = targetLeft;
3799 } else {
3800 rv = (int16_t)( ((target - srcLeft) * targetRight +
3801 (srcRight - target) * targetLeft) / (srcRight - srcLeft) );
3803 return rv;
3806 static void
3807 ar5416Set11nRegs(struct ath_hal *ah, HAL_CHANNEL *chan)
3809 uint32_t phymode;
3810 HAL_HT_MACMODE macmode; /* MAC - 20/40 mode */
3812 if (!IS_CHAN_HT(chan))
3813 return;
3815 /* Enable 11n HT, 20 MHz */
3816 phymode = AR_PHY_FC_HT_EN | AR_PHY_FC_SHORT_GI_40
3817 | AR_PHY_FC_SINGLE_HT_LTF1 | AR_PHY_FC_WALSH;
3819 /* Configure baseband for dynamic 20/40 operation */
3820 if (IS_CHAN_HT40(chan)) {
3821 phymode |= AR_PHY_FC_DYN2040_EN | AR_PHY_FC_SHORT_GI_40;
3823 /* Configure control (primary) channel at +-10MHz */
3824 if ((chan->channelFlags & CHANNEL_HT40PLUS))
3825 phymode |= AR_PHY_FC_DYN2040_PRI_CH;
3826 #if 0
3827 /* Configure 20/25 spacing */
3828 if (ht->ht_extprotspacing == HAL_HT_EXTPROTSPACING_25)
3829 phymode |= AR_PHY_FC_DYN2040_EXT_CH;
3830 #endif
3831 macmode = HAL_HT_MACMODE_2040;
3832 } else
3833 macmode = HAL_HT_MACMODE_20;
3834 OS_REG_WRITE(ah, AR_PHY_TURBO, phymode);
3836 /* Configure MAC for 20/40 operation */
3837 ar5416Set11nMac2040(ah, macmode);
3839 /* global transmit timeout (25 TUs default)*/
3840 /* XXX - put this elsewhere??? */
3841 OS_REG_WRITE(ah, AR_GTXTO, 25 << AR_GTXTO_TIMEOUT_LIMIT_S) ;
3843 /* carrier sense timeout */
3844 OS_REG_SET_BIT(ah, AR_GTTM, AR_GTTM_CST_USEC);
3845 OS_REG_WRITE(ah, AR_CST, 1 << AR_CST_TIMEOUT_LIMIT_S);
3848 void
3849 ar5416GetChannelCenters(struct ath_hal *ah,
3850 HAL_CHANNEL_INTERNAL *chan, CHAN_CENTERS *centers)
3852 centers->ctl_center = chan->channel;
3853 centers->synth_center = chan->channel;
3855 * In 20/40 phy mode, the center frequency is
3856 * "between" the control and extension channels.
3858 if (chan->channelFlags & CHANNEL_HT40PLUS) {
3859 centers->synth_center += HT40_CHANNEL_CENTER_SHIFT;
3860 centers->ext_center =
3861 centers->synth_center + HT40_CHANNEL_CENTER_SHIFT;
3862 } else if (chan->channelFlags & CHANNEL_HT40MINUS) {
3863 centers->synth_center -= HT40_CHANNEL_CENTER_SHIFT;
3864 centers->ext_center =
3865 centers->synth_center - HT40_CHANNEL_CENTER_SHIFT;
3866 } else {
3867 centers->ext_center = chan->channel;
3870 #endif /* AH_SUPPORT_AR5416 */