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.
21 #ifdef AH_SUPPORT_AR5416
24 #include "ah_internal.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"
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
);
59 static HAL_BOOL
ar5416ChannelChange(struct ath_hal
*, HAL_CHANNEL
*);
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
);
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
,
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.
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
;
133 uint32_t saveDefAntenna
, saveLedState
;
135 uint16_t rfXpdGain
[2];
136 u_int modesIndex
, freqIndex
;
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
);
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
);
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",
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
);
175 HALDEBUG(ah
, HAL_DEBUG_RESET
,
176 "%s: Ch=%u Max=%d Min=%d\n",__func__
,
177 ichan
->channel
, ichan
->maxTxPower
, ichan
->minTxPower
);
186 HALDEBUG(ah
, HAL_DEBUG_ANY
, "%s: invalid operating mode %u\n",
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
198 rssiThrReg
= OS_REG_READ(ah
, AR_RSSI_THR
);
199 /* If reg is zero, first time thru set to default val */
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 */
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__
);
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
) {
243 case CHANNEL_A_HT40PLUS
:
244 case CHANNEL_A_HT40MINUS
:
250 case CHANNEL_B
: /* treat as channel G , no B mode suport in owl */
254 case CHANNEL_G_HT40PLUS
:
255 case CHANNEL_G_HT40MINUS
:
264 HALDEBUG(ah
, HAL_DEBUG_ANY
, "%s: invalid channel flags 0x%x\n",
265 __func__
, chan
->channelFlags
);
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);
277 OS_REG_WRITE(ah
, AR_PHY_ADC_SERIAL_CTL
, AR_PHY_SEL_EXTERNAL_RADIO
);
279 /* NB: only required for Sowl */
280 ar5416EepromSetAddac(ah
, ichan
);
282 regWrites
= ath_hal_ini_write(ah
, &AH5416(ah
)->ah_ini_addac
, 1,
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
,
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
);
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
);
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
) {
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
);
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__
);
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__
);
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
);
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__
);
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)
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
);
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
))
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);
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
);
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);
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
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
))
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);
485 OS_MARK(ah
, AH_MARK_RESET_DONE
, ecode
);
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
501 ar5416ChannelChange(struct ath_hal
*ah
, HAL_CHANNEL
*chan
)
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
);
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",
533 ar5416Set11nRegs(ah
, chan
); /* NB: setup 5416-specific regs */
535 /* Change the synth */
536 if (!ar5212SetChannel(ah
, ichan
))
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__
);
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;
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
&&
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
);
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
621 OS_REG_WRITE(ah
, AR_PCU_TXBUF_CTRL
, AR_PCU_TXBUF_CTRL_USABLE_SIZE
);
625 ar5416InitBB(struct ath_hal
*ah
, HAL_CHANNEL
*chan
)
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;
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
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
);
660 OS_DELAY(synthDelay
+ BASE_ACTIVATE_DELAY
);
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
679 #ifdef AR5416_INT_MITIGATION
680 ahp
->ah_maskReg
|= AR_IMR_TXINTM
| AR_IMR_RXINTM
681 | AR_IMR_TXMINTR
| AR_IMR_RXMINTR
;
683 ahp
->ah_maskReg
|= AR_IMR_TXOK
| AR_IMR_RXOK
;
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 */
691 OS_REG_WRITE(ah
, AR_IMR_S2
,
692 OS_REG_READ(ah
, AR_IMR_S2
) | AR_IMR_S2_GTT
| AR_IMR_S2_CST
);
697 ar5416InitQoS(struct ath_hal
*ah
)
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);
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
);
738 if (ahp
->ah_globaltxtimeout
!= (u_int
) -1)
739 ar5416SetGlobalTxTimeout(ah
, ahp
->ah_globaltxtimeout
);
744 * Places the hardware into reset and then pulls it out of reset
747 ar5416ChipReset(struct ath_hal
*ah
, HAL_CHANNEL
*chan
)
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
))
760 if (!ar5416SetResetReg(ah
, HAL_RESET_WARM
))
764 /* Bring out of sleep mode (AGAIN) */
765 if (!ar5416SetPowerMode(ah
, HAL_PM_AWAKE
, AH_TRUE
))
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
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
);
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
);
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
));
818 * Setup HW to collect samples used for current cal
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__
);
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__
);
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__
);
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__
);
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.
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
;
876 * Run non-periodic calibrations.
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
;
887 if (curCal
== AH_NULL
)
891 for (i
= 0; i
< init_cal_count
; i
++) {
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
;
905 ar5416DoCalibration(ah
, &ichan
, ahp
->ah_rxchainmask
,
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
;
923 * Initialize Calibration infrastructure.
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__
);
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 */
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))
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;
1009 * Entry point for upper layers to restart current cal.
1010 * Reset the calibration valid bit in channel.
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
))
1023 if (currCal
== AH_NULL
)
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
);
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
);
1042 /* Verify Cal is supported on this channel */
1043 if (!ar5416IsCalSupp(ah
, chan
, currCal
->calData
->calType
))
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
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
,
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
))
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
;
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.
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
);
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)
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 */
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
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
;
1191 * Recalibrate the lower PHY chips to account for temperature/environment
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
,
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
1216 ar5416IQCalCollect(struct ath_hal
*ah
)
1218 struct ath_hal_5416
*ahp
= AH5416(ah
);
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
1242 ar5416IQCalibration(struct ath_hal
*ah
, uint8_t numChains
)
1244 struct ath_hal_5416
*ahp
= AH5416(ah
);
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
;
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
);
1260 /* iqCorrMeas is always negative. */
1261 if (iqCorrMeas
> 0x80000000) {
1262 iqCorrMeas
= (0xffffffff - iqCorrMeas
) + 1;
1266 HALDEBUG(ah
, HAL_DEBUG_PERCAL
, " pwr_meas_i = 0x%08x\n",
1268 HALDEBUG(ah
, HAL_DEBUG_PERCAL
, " pwr_meas_q = 0x%08x\n",
1270 HALDEBUG(ah
, HAL_DEBUG_PERCAL
, " iqCorrNeg is 0x%08x\n",
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",
1283 HALDEBUG(ah
, HAL_DEBUG_PERCAL
, " qCoff = 0x%08x\n",
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
;
1295 else if (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
1316 ar5416AdcGainCalCollect(struct ath_hal
*ah
)
1318 struct ath_hal_5416
*ahp
= AH5416(ah
);
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
1346 ar5416AdcGainCalibration(struct ath_hal
*ah
, uint8_t numChains
)
1348 struct ath_hal_5416
*ahp
= AH5416(ah
);
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;
1375 HALDEBUG(ah
, HAL_DEBUG_PERCAL
,
1376 " gain_mismatch_i = 0x%08x\n",
1378 HALDEBUG(ah
, HAL_DEBUG_PERCAL
,
1379 " gain_mismatch_q = 0x%08x\n",
1382 val
= OS_REG_READ(ah
, AR_PHY_NEW_ADC_DC_GAIN_CORR(i
));
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
);
1396 ar5416AdcDcCalCollect(struct ath_hal
*ah
)
1398 struct ath_hal_5416
*ahp
= AH5416(ah
);
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
));
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
;
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
;
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",
1443 HALDEBUG(ah
, HAL_DEBUG_PERCAL
, " pwr_meas_even_i = %d\n",
1445 HALDEBUG(ah
, HAL_DEBUG_PERCAL
, " pwr_meas_odd_q = %d\n",
1447 HALDEBUG(ah
, HAL_DEBUG_PERCAL
, " pwr_meas_even_q = %d\n",
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
));
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
1475 ar9280GetNoiseFloor(struct ath_hal
*ah
, int16_t nfarray
[NUM_NOISEFLOOR_READINGS
])
1479 nf
= MS(OS_REG_READ(ah
, AR_PHY_CCA
), AR9280_PHY_MINCCA_PWR
);
1481 nf
= 0 - ((nf
^ 0x1ff) + 1);
1482 HALDEBUG(ah
, HAL_DEBUG_NFCAL
,
1483 "NF calibrated [ctl] [chain 0] is %d\n", nf
);
1486 nf
= MS(OS_REG_READ(ah
, AR_PHY_CH1_CCA
), AR9280_PHY_CH1_MINCCA_PWR
);
1488 nf
= 0 - ((nf
^ 0x1ff) + 1);
1489 HALDEBUG(ah
, HAL_DEBUG_NFCAL
,
1490 "NF calibrated [ctl] [chain 1] is %d\n", nf
);
1493 nf
= MS(OS_REG_READ(ah
, AR_PHY_EXT_CCA
), AR9280_PHY_EXT_MINCCA_PWR
);
1495 nf
= 0 - ((nf
^ 0x1ff) + 1);
1496 HALDEBUG(ah
, HAL_DEBUG_NFCAL
,
1497 "NF calibrated [ext] [chain 0] is %d\n", nf
);
1500 nf
= MS(OS_REG_READ(ah
, AR_PHY_CH1_EXT_CCA
), AR9280_PHY_CH1_EXT_MINCCA_PWR
);
1502 nf
= 0 - ((nf
^ 0x1ff) + 1);
1503 HALDEBUG(ah
, HAL_DEBUG_NFCAL
,
1504 "NF calibrated [ext] [chain 1] is %d\n", nf
);
1507 #endif /* AH_SUPPORT_AR9280 */
1510 ar5416GetNoiseFloor(struct ath_hal
*ah
, int16_t nfarray
[NUM_NOISEFLOOR_READINGS
])
1512 struct ath_hal_5416
*ahp
= AH5416(ah
);
1515 switch (ahp
->ah_rx_chainmask
) {
1517 nf
= MS(OS_REG_READ(ah
, AR_PHY_CH2_CCA
), AR_PHY_CH2_MINCCA_PWR
);
1519 nf
= 0 - ((nf
^ 0x1ff) + 1);
1520 HALDEBUG(ah
, HAL_DEBUG_NFCAL
,
1521 "NF calibrated [ctl] [chain 2] is %d\n", nf
);
1524 nf
= MS(OS_REG_READ(ah
, AR_PHY_CH2_EXT_CCA
), AR_PHY_CH2_EXT_MINCCA_PWR
);
1526 nf
= 0 - ((nf
^ 0x1ff) + 1);
1527 HALDEBUG(ah
, HAL_DEBUG_NFCAL
,
1528 "NF calibrated [ext] [chain 2] is %d\n", nf
);
1533 nf
= MS(OS_REG_READ(ah
, AR_PHY_CH1_CCA
), AR_PHY_CH1_MINCCA_PWR
);
1535 nf
= 0 - ((nf
^ 0x1ff) + 1);
1536 HALDEBUG(ah
, HAL_DEBUG_NFCAL
,
1537 "NF calibrated [ctl] [chain 1] is %d\n", nf
);
1541 nf
= MS(OS_REG_READ(ah
, AR_PHY_CH1_EXT_CCA
), AR_PHY_CH1_EXT_MINCCA_PWR
);
1543 nf
= 0 - ((nf
^ 0x1ff) + 1);
1544 HALDEBUG(ah
, HAL_DEBUG_NFCAL
,
1545 "NF calibrated [ext] [chain 1] is %d\n", nf
);
1549 nf
= MS(OS_REG_READ(ah
, AR_PHY_CCA
), AR_PHY_MINCCA_PWR
);
1551 nf
= 0 - ((nf
^ 0x1ff) + 1);
1552 HALDEBUG(ah
, HAL_DEBUG_NFCAL
,
1553 "NF calibrated [ctl] [chain 0] is %d\n", nf
);
1556 nf
= MS(OS_REG_READ(ah
, AR_PHY_EXT_CCA
), AR_PHY_EXT_MINCCA_PWR
);
1558 nf
= 0 - ((nf
^ 0x1ff) + 1);
1559 HALDEBUG(ah
, HAL_DEBUG_NFCAL
,
1560 "NF calibrated [ext] [chain 0] is %d\n", nf
);
1568 ar5416GetEepromNoiseFloorThresh(struct ath_hal
*ah
,
1569 const HAL_CHANNEL_INTERNAL
*chan
, int16_t *nft
)
1571 switch (chan
->channelFlags
& CHANNEL_ALL_NOTURBO
) {
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
);
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
);
1586 HALDEBUG(ah
, HAL_DEBUG_ANY
,
1587 "%s: invalid channel flags 0x%x\n",
1588 __func__
, chan
->channelFlags
);
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
);
1603 ar5416LoadNF(struct ath_hal
*ah
, HAL_CHANNEL_INTERNAL
*chan
)
1605 static const uint32_t ar5416_cca_regs
[] = {
1613 struct ar5212NfCalHist
*h
;
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 */
1625 } else if (AR_SREV_MERLIN(ah
)) {
1626 /* Merlin has only two chains */
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
]);
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)
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
]);
1666 val
|= (((uint32_t)(-50) << 1) & 0x1ff);
1667 OS_REG_WRITE(ah
, ar5416_cca_regs
[i
], val
);
1672 ar5416InitNfHistBuff(struct ar5212NfCalHist
*h
)
1676 for (i
= 0; i
< AR5416_NUM_NF_READINGS
; i
++) {
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
1689 ar5416UpdateNFHistBuff(struct ar5212NfCalHist
*h
, int16_t *nfarray
)
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
)
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
;
1703 h
[i
].invalidNFcount
--;
1704 h
[i
].privNF
= nfarray
[i
];
1707 h
[i
].privNF
= ar5212GetNfHistMid(h
[i
].nfCalBuffer
);
1713 * Read the NF and check it against the noise floor threshhold
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__
);
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
);
1734 ar5416GetNoiseFloor(ah
, nfarray
);
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__
,
1743 * NB: Don't discriminate 2.4 vs 5Ghz, if this
1744 * happens it indicates a problem regardless
1747 chan
->channelFlags
|= CHANNEL_CW_INT
;
1753 ar5416UpdateNFHistBuff(AH5416(ah
)->ah_nfCalHist
, nfarray
);
1754 chan
->rawNoiseFloor
= nf
;
1760 * Delta slope coefficient computation.
1761 * Required for OFDM operation.
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)
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;
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
, ¢ers
);
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
);
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
);
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
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
;
1859 int spur_delta_phase
;
1861 int upper
, lower
, cur_vit_mask
;
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
)
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
;
1889 if (AR_NO_SPUR
== bb_spur
)
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,
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
1942 for (i
= 0; i
< 4; i
++) {
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
;
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
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
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;
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) {
1988 if (cur_vit_mask
< 0) {
1989 mask_m
[abs(cur_vit_mask
/ 100)] = mask_amt
;
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
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
;
2104 int bb_spur_off
, spur_subchannel_sd
;
2106 int spur_delta_phase
;
2108 int upper
, lower
, cur_vit_mask
;
2111 CHAN_CENTERS centers
;
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
, ¢ers
);
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 */
2134 cur_bb_spur
= (cur_bb_spur
/ 10) + AR_BASE_FREQ_2GHZ
;
2136 cur_bb_spur
= (cur_bb_spur
/ 10) + AR_BASE_FREQ_5GHZ
;
2139 if (AR_NO_SPUR
== cur_bb_spur
)
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
;
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
;
2156 if (AR_NO_SPUR
== bb_spur
) {
2159 * MRC CCK can interfere with beacon detection and cause deaf/mute.
2162 OS_REG_CLR_BIT(ah
, AR_PHY_FORCE_CLKEN_CCK
, AR_PHY_FORCE_CLKEN_CCK_MRC_MUX
);
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
);
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
)) {
2196 spur_subchannel_sd
= 1;
2197 bb_spur_off
= bb_spur
+ 10;
2199 spur_subchannel_sd
= 0;
2200 bb_spur_off
= bb_spur
- 10;
2203 spur_subchannel_sd
= 0;
2204 bb_spur_off
= bb_spur
;
2208 * spur_delta_phase = bb_spur/40 * 2**21 for static ht20,
2211 if (IS_CHAN_HT40(ichan
))
2212 spur_delta_phase
= ((bb_spur
* 262144) / 10) & AR_PHY_TIMING11_SPUR_DELTA_PHASE
;
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
2246 for (i
= 0; i
< 4; i
++) {
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
;
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
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
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;
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) {
2292 if (cur_vit_mask
< 0) {
2293 mask_m
[abs(cur_vit_mask
/ 100)] = mask_amt
;
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.
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
,
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
;
2416 * Get Pier table max and min powers.
2418 for (i
= 0; i
< nchans
; 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;
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;
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
);
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
,
2456 /**************************************************************
2457 * ar5416SetTransmitPower
2459 * Set the transmit power in the baseband for the given
2460 * operating channel and mode.
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;
2476 uint16_t powerLimit
;
2477 uint16_t twiceAntennaReduction
;
2478 uint16_t twiceMaxRegulatoryPower
;
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__
);
2508 if (!ar5416SetPowerCalTable(ah
, pEepData
, chan
, &txPowerIndexOffset
)) {
2509 HALDEBUG(ah
, HAL_DEBUG_ANY
, "%s: unable to set power table\n",
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
);
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)
2625 * Exported call to check for a recent gain reading and return
2626 * the current state of the thermal calibration gain engine.
2629 ar5416GetRfgain(struct ath_hal
*ah
)
2631 return HAL_RFGAIN_INACTIVE
;
2635 * Places all of hardware into reset
2638 ar5416Disable(struct ath_hal
*ah
)
2640 if (!ar5212SetPowerMode(ah
, HAL_PM_AWAKE
, AH_TRUE
))
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.
2652 ar5416PhyDisable(struct ath_hal
*ah
)
2654 return ar5416SetResetReg(ah
, HAL_RESET_WARM
);
2658 * Write the given reset bit mask into the reset register
2661 ar5416SetResetReg(struct ath_hal
*ah
, uint32_t type
)
2666 OS_REG_WRITE(ah
, AR_RTC_FORCE_WAKE
,
2667 AR_RTC_FORCE_WAKE_EN
| AR_RTC_FORCE_WAKE_ON_INT
);
2670 case HAL_RESET_POWER_ON
:
2671 return ar5416SetResetPowerOn(ah
);
2673 case HAL_RESET_WARM
:
2674 case HAL_RESET_COLD
:
2675 return ar5416SetReset(ah
, type
);
2683 ar5416SetResetPowerOn(struct ath_hal
*ah
)
2685 /* Power On Reset (Hard Reset) */
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);
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__
);
2714 return ar5416SetReset(ah
, HAL_RESET_COLD
);
2718 ar5416SetReset(struct ath_hal
*ah
, int type
)
2725 OS_REG_WRITE(ah
, AR_RTC_FORCE_WAKE
,
2726 AR_RTC_FORCE_WAKE_EN
| AR_RTC_FORCE_WAKE_ON_INT
);
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
);
2736 OS_REG_WRITE(ah
, AR_RC
, AR_RC_AHB
);
2740 * Set Mac(BB,Phy) Warm Reset
2743 case HAL_RESET_WARM
:
2744 OS_REG_WRITE(ah
, AR_RTC_RC
, AR_RTC_RC_MAC_WARM
);
2746 case HAL_RESET_COLD
:
2747 OS_REG_WRITE(ah
, AR_RTC_RC
, AR_RTC_RC_MAC_WARM
|AR_RTC_RC_MAC_COLD
);
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__
);
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
) {
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
;
2780 OS_REG_WRITE(ah
, AR_CFG
, LE_READ_4(&mask
));
2784 ar5416InitPLL(ah
, AH_NULL
);
2789 #ifndef IS_5GHZ_FAST_CLOCK_EN
2790 #define IS_5GHZ_FAST_CLOCK_EN(ah, chan) AH_FALSE
2794 ar5416InitPLL(struct ath_hal
*ah
, HAL_CHANNEL
*chan
)
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
)) {
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
);
2835 pll
|= SM(0x58, AR_RTC_SOWL_PLL_DIV
);
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
);
2848 pll
|= SM(0xb, AR_RTC_PLL_DIV
);
2851 OS_REG_WRITE(ah
, AR_RTC_PLL_CONTROL
, pll
);
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.
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;
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
,
2930 OS_REG_RMW_FIELD(ah
, AR_PHY_EXT_CCA0
, AR_PHY_EXT_CCA0_THRESH62
,
2933 OS_REG_RMW_FIELD(ah
, AR_PHY_CCA
, AR_PHY_CCA_THRESH62
,
2935 OS_REG_RMW_FIELD(ah
, AR_PHY_EXT_CCA0
, AR_PHY_EXT_CCA_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
));
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]);
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.
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
;
3005 int16_t twiceLargestAntenna
;
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
, ¢ers
);
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]);
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]);
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
)) {
3065 scaledPower
-= pEepData
->modalHeader
[IS_CHAN_2GHZ(chan
)].pwrDecreaseFor2Chain
;
3068 scaledPower
-= pEepData
->modalHeader
[IS_CHAN_2GHZ(chan
)].pwrDecreaseFor3Chain
;
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
);
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
;
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
);
3158 twiceMaxEdgePower
= twiceMinEdgePower
;
3163 minCtlPower
= (uint8_t)AH_MIN(twiceMaxEdgePower
, scaledPower
);
3164 /* Apply ctl mode to correct target power set */
3165 switch(pCtlMode
[ctlMode
]) {
3167 for (i
= 0; i
< N(targetPowerCck
.tPow2x
); i
++) {
3168 targetPowerCck
.tPow2x
[i
] = (uint8_t)AH_MIN(targetPowerCck
.tPow2x
[i
], minCtlPower
);
3173 for (i
= 0; i
< N(targetPowerOfdm
.tPow2x
); i
++) {
3174 targetPowerOfdm
.tPow2x
[i
] = (uint8_t)AH_MIN(targetPowerOfdm
.tPow2x
[i
], minCtlPower
);
3179 for (i
= 0; i
< N(targetPowerHt20
.tPow2x
); i
++) {
3180 targetPowerHt20
.tPow2x
[i
] = (uint8_t)AH_MIN(targetPowerHt20
.tPow2x
[i
], minCtlPower
);
3184 targetPowerCckExt
.tPow2x
[0] = (uint8_t)AH_MIN(targetPowerCckExt
.tPow2x
[0], minCtlPower
);
3188 targetPowerOfdmExt
.tPow2x
[0] = (uint8_t)AH_MIN(targetPowerOfdmExt
.tPow2x
[0], minCtlPower
);
3192 for (i
= 0; i
< N(targetPowerHt40
.tPow2x
); i
++) {
3193 targetPowerHt40
.tPow2x
[i
] = (uint8_t)AH_MIN(targetPowerHt40
.tPow2x
[i
], minCtlPower
);
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];
3235 #undef SUB_NUM_CTL_MODES_AT_5G_40
3236 #undef SUB_NUM_CTL_MODES_AT_2G_40
3240 /**************************************************************************
3243 * Get channel value from binary representation held in eeprom
3244 * RETURNS: the frequency in MHz
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
) {
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
3266 ar5416GetMaxEdgePower(uint16_t freq
, CAL_CTL_EDGES
*pRdEdgesPower
, HAL_BOOL is2GHz
)
3268 uint16_t twiceMaxEdgePower
= AR5416_MAX_RATE_POWER
;
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
);
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 */
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
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
)
3306 int matchIndex
= -1, lowIndex
= -1;
3308 CHAN_CENTERS centers
;
3310 ar5416GetChannelCenters(ah
, chan
, ¢ers
);
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
))) {
3317 for (i
= 0; (i
< numChannels
) && (powInfo
[i
].bChannel
!= AR5416_BCHAN_UNUSED
); i
++) {
3318 if (freq
== fbin2freq(powInfo
[i
].bChannel
, IS_CHAN_2GHZ(chan
))) {
3321 } else if ((freq
< fbin2freq(powInfo
[i
].bChannel
, IS_CHAN_2GHZ(chan
))) &&
3322 (freq
> fbin2freq(powInfo
[i
- 1].bChannel
, IS_CHAN_2GHZ(chan
))))
3328 if ((matchIndex
== -1) && (lowIndex
== -1)) {
3329 HALASSERT(freq
> fbin2freq(powInfo
[i
- 1].bChannel
, IS_CHAN_2GHZ(chan
)));
3334 if (matchIndex
!= -1) {
3335 OS_MEMCPY(pNewPower
, &powInfo
[matchIndex
], sizeof(*pNewPower
));
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
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
)
3366 int matchIndex
= -1, lowIndex
= -1;
3368 CHAN_CENTERS centers
;
3370 ar5416GetChannelCenters(ah
, chan
, ¢ers
);
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
))) {
3377 for (i
= 0; (i
< numChannels
) && (powInfo
[i
].bChannel
!= AR5416_BCHAN_UNUSED
); i
++) {
3378 if (freq
== fbin2freq(powInfo
[i
].bChannel
, IS_CHAN_2GHZ(chan
))) {
3381 } else if ((freq
< fbin2freq(powInfo
[i
].bChannel
, IS_CHAN_2GHZ(chan
))) &&
3382 (freq
> fbin2freq(powInfo
[i
- 1].bChannel
, IS_CHAN_2GHZ(chan
))))
3388 if ((matchIndex
== -1) && (lowIndex
== -1)) {
3389 HALASSERT(freq
> fbin2freq(powInfo
[i
- 1].bChannel
, IS_CHAN_2GHZ(chan
)));
3394 if (matchIndex
!= -1) {
3395 OS_MEMCPY(pNewPower
, &powInfo
[matchIndex
], sizeof(*pNewPower
));
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.
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
;
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
;
3447 pCalBChans
= pEepData
->calFreqPier5G
;
3448 numPiers
= AR5416_NUM_5G_CAL_PIERS
;
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
) {
3459 xpdGainValues
[numXpdGain
] = (uint16_t)(AR5416_PD_GAINS_IN_MASK
- i
);
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;
3479 regChainOffset
= i
* 0x1000;
3482 if (pEepData
->baseEepHeader
.txMask
& (1 << i
)) {
3483 if (IS_CHAN_2GHZ(chan
)) {
3484 pRawDataset
= pEepData
->calPierData2G
[i
];
3486 pRawDataset
= pEepData
->calPierData5G
[i
];
3489 ar5416GetGainBoundariesAndPdadcs(ah
, chan
, pRawDataset
,
3490 pCalBChans
, numPiers
,
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
);
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]);
3532 *pTxPowerIndexOffset
= 0;
3537 /**************************************************************
3538 * ar5416GetGainBoundariesAndPdadcs
3540 * Uses the data points read from EEPROM to reconstruct the pdadc power table
3541 * Called by ar5416SetPowerCalTable only.
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
)
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
];
3569 uint16_t sizeCurrVpdTable
, maxIndex
, tgtIndex
;
3571 int16_t minDelta
= 0;
3572 CHAN_CENTERS centers
;
3574 ar5416GetChannelCenters(ah
, chan
, ¢ers
);
3576 /* Trim numPiers for the number of populated channel Piers */
3577 for (numPiers
= 0; numPiers
< availPiers
; numPiers
++) {
3578 if (bChans
[numPiers
] == AR5416_BCHAN_UNUSED
) {
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
);
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
]);
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);
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;
3645 /* Find starting index for this pdGain */
3647 ss
= 0; /* for the first pdGain, start from index 0 */
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
);
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
);
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];
3693 while (k
< AR5416_NUM_PDADC_VALUES
) {
3694 pPDADCValues
[k
] = pPDADCValues
[k
-1];
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.
3710 getLowerUpperIndex(uint8_t target
, uint8_t *pList
, uint16_t listSize
,
3711 uint16_t *indexL
, uint16_t *indexR
)
3716 * Check first and last elements for beyond ordered array cases.
3718 if (target
<= pList
[0]) {
3719 *indexL
= *indexR
= 0;
3722 if (target
>= pList
[listSize
-1]) {
3723 *indexL
= *indexR
= (uint16_t)(listSize
- 1);
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
;
3738 * Look for value being between current value and next value
3739 * if so return these 2 values
3741 if (target
< pList
[i
+ 1]) {
3743 *indexR
= (uint16_t)(i
+ 1);
3751 /**************************************************************
3752 * ar5416FillVpdTable
3754 * Fill the Vpdlist for indices Pmax-Pmin
3755 * Note: pwrMin, pwrMax and Vpdlist are all in dBm * 4
3758 ar5416FillVpdTable(uint8_t pwrMin
, uint8_t pwrMax
, uint8_t *pPwrList
,
3759 uint8_t *pVpdList
, uint16_t numIntercepts
, uint8_t *pRetVpdList
)
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
,
3770 idxR
= 1; /* extrapolate below */
3771 if (idxL
== numIntercepts
- 1)
3772 idxL
= (uint16_t)(numIntercepts
- 2); /* extrapolate above */
3773 if (pPwrList
[idxL
] == pPwrList
[idxR
])
3776 k
= (uint16_t)( ((currPwr
- pPwrList
[idxL
]) * pVpdList
[idxR
] + (pPwrList
[idxR
] - currPwr
) * pVpdList
[idxL
]) /
3777 (pPwrList
[idxR
] - pPwrList
[idxL
]) );
3779 pRetVpdList
[i
] = (uint8_t)k
;
3780 currPwr
+= 2; /* half dB steps */
3786 /**************************************************************************
3789 * Returns signed interpolated or the scaled up interpolated value
3792 interpolate(uint16_t target
, uint16_t srcLeft
, uint16_t srcRight
,
3793 int16_t targetLeft
, int16_t targetRight
)
3797 if (srcRight
== srcLeft
) {
3800 rv
= (int16_t)( ((target
- srcLeft
) * targetRight
+
3801 (srcRight
- target
) * targetLeft
) / (srcRight
- srcLeft
) );
3807 ar5416Set11nRegs(struct ath_hal
*ah
, HAL_CHANNEL
*chan
)
3810 HAL_HT_MACMODE macmode
; /* MAC - 20/40 mode */
3812 if (!IS_CHAN_HT(chan
))
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
;
3827 /* Configure 20/25 spacing */
3828 if (ht
->ht_extprotspacing
== HAL_HT_EXTPROTSPACING_25
)
3829 phymode
|= AR_PHY_FC_DYN2040_EXT_CH
;
3831 macmode
= HAL_HT_MACMODE_2040
;
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
);
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
;
3867 centers
->ext_center
= chan
->channel
;
3870 #endif /* AH_SUPPORT_AR5416 */