2 * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
3 * Copyright (c) 2002-2008 Atheros Communications, Inc.
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 * $Id: ar5416_reset.c,v 1.2 2009/01/06 06:03:57 mrg Exp $
22 #include "ah_internal.h"
25 #include "ah_eeprom_v14.h"
27 #include "ar5416/ar5416.h"
28 #include "ar5416/ar5416reg.h"
29 #include "ar5416/ar5416phy.h"
30 #ifdef AH_SUPPORT_AR9280
31 #include "ar5416/ar9280.h"
34 /* Eeprom versioning macros. Returns true if the version is equal or newer than the ver specified */
35 #define EEP_MINOR(_ah) \
36 (AH_PRIVATE(_ah)->ah_eeversion & AR5416_EEP_VER_MINOR_MASK)
37 #define IS_EEP_MINOR_V2(_ah) (EEP_MINOR(_ah) >= AR5416_EEP_MINOR_VER_2)
38 #define IS_EEP_MINOR_V3(_ah) (EEP_MINOR(_ah) >= AR5416_EEP_MINOR_VER_3)
40 /* Additional Time delay to wait after activiting the Base band */
41 #define BASE_ACTIVATE_DELAY 100 /* 100 usec */
42 #define PLL_SETTLE_DELAY 300 /* 300 usec */
43 #define RTC_PLL_SETTLE_DELAY 1000 /* 1 ms */
45 static void ar5416InitDMA(struct ath_hal
*ah
);
46 static void ar5416InitBB(struct ath_hal
*ah
, HAL_CHANNEL
*chan
);
47 static void ar5416InitIMR(struct ath_hal
*ah
, HAL_OPMODE opmode
);
48 static void ar5416InitQoS(struct ath_hal
*ah
);
49 static void ar5416InitUserSettings(struct ath_hal
*ah
);
51 static HAL_BOOL
ar5416SetTransmitPower(struct ath_hal
*ah
,
52 HAL_CHANNEL_INTERNAL
*chan
, uint16_t *rfXpdGain
);
55 static HAL_BOOL
ar5416ChannelChange(struct ath_hal
*, HAL_CHANNEL
*);
57 static void ar5416SetDeltaSlope(struct ath_hal
*, HAL_CHANNEL_INTERNAL
*);
58 static void ar5416SpurMitigate(struct ath_hal
*ah
, HAL_CHANNEL_INTERNAL
*chan
);
59 #ifdef AH_SUPPORT_AR9280
60 static void ar9280SpurMitigate(struct ath_hal
*ah
, HAL_CHANNEL_INTERNAL
*chan
);
63 static HAL_BOOL
ar5416SetResetPowerOn(struct ath_hal
*ah
);
64 static HAL_BOOL
ar5416SetReset(struct ath_hal
*ah
, int type
);
65 static void ar5416InitPLL(struct ath_hal
*ah
, HAL_CHANNEL
*chan
);
66 static HAL_BOOL
ar5416SetBoardValues(struct ath_hal
*, HAL_CHANNEL_INTERNAL
*);
67 static HAL_BOOL
ar5416SetPowerPerRateTable(struct ath_hal
*ah
,
68 struct ar5416eeprom
*pEepData
,
69 HAL_CHANNEL_INTERNAL
*chan
, int16_t *ratesArray
,
70 uint16_t cfgCtl
, uint16_t AntennaReduction
,
71 uint16_t twiceMaxRegulatoryPower
,
73 static HAL_BOOL
ar5416SetPowerCalTable(struct ath_hal
*ah
,
74 struct ar5416eeprom
*pEepData
,
75 HAL_CHANNEL_INTERNAL
*chan
,
76 int16_t *pTxPowerIndexOffset
);
77 static uint16_t ar5416GetMaxEdgePower(uint16_t freq
,
78 CAL_CTL_EDGES
*pRdEdgesPower
, HAL_BOOL is2GHz
);
79 static void ar5416GetTargetPowers(struct ath_hal
*ah
,
80 HAL_CHANNEL_INTERNAL
*chan
, CAL_TARGET_POWER_HT
*powInfo
,
81 uint16_t numChannels
, CAL_TARGET_POWER_HT
*pNewPower
,
82 uint16_t numRates
, HAL_BOOL isHt40Target
);
83 static void ar5416GetTargetPowersLeg(struct ath_hal
*ah
,
84 HAL_CHANNEL_INTERNAL
*chan
, CAL_TARGET_POWER_LEG
*powInfo
,
85 uint16_t numChannels
, CAL_TARGET_POWER_LEG
*pNewPower
,
86 uint16_t numRates
, HAL_BOOL isExtTarget
);
88 static int16_t interpolate(uint16_t target
, uint16_t srcLeft
,
89 uint16_t srcRight
, int16_t targetLeft
, int16_t targetRight
);
90 static void ar5416Set11nRegs(struct ath_hal
*ah
, HAL_CHANNEL
*chan
);
91 static void ar5416GetGainBoundariesAndPdadcs(struct ath_hal
*ah
,
92 HAL_CHANNEL_INTERNAL
*chan
, CAL_DATA_PER_FREQ
*pRawDataSet
,
93 uint8_t * bChans
, uint16_t availPiers
,
94 uint16_t tPdGainOverlap
, int16_t *pMinCalPower
,
95 uint16_t * pPdGainBoundaries
, uint8_t * pPDADCValues
,
96 uint16_t numXpdGains
);
97 static HAL_BOOL
getLowerUpperIndex(uint8_t target
, uint8_t *pList
,
98 uint16_t listSize
, uint16_t *indexL
, uint16_t *indexR
);
99 static HAL_BOOL
ar5416FillVpdTable(uint8_t pwrMin
, uint8_t pwrMax
,
100 uint8_t *pPwrList
, uint8_t *pVpdList
,
101 uint16_t numIntercepts
, uint8_t *pRetVpdList
);
104 * Places the device in and out of reset and then places sane
105 * values in the registers based on EEPROM config, initialization
106 * vectors (as determined by the mode), and station configuration
108 * bChannelChange is used to preserve DMA/PCU registers across
109 * a HW Reset during channel change.
112 ar5416Reset(struct ath_hal
*ah
, HAL_OPMODE opmode
,
113 HAL_CHANNEL
*chan
, HAL_BOOL bChannelChange
, HAL_STATUS
*status
)
115 #define N(a) (sizeof (a) / sizeof (a[0]))
116 #define FAIL(_code) do { ecode = _code; goto bad; } while (0)
117 struct ath_hal_5212
*ahp
= AH5212(ah
);
118 HAL_CHANNEL_INTERNAL
*ichan
;
120 uint32_t saveDefAntenna
, saveLedState
;
122 uint16_t rfXpdGain
[2];
123 u_int modesIndex
, freqIndex
;
125 int i
, regWrites
= 0;
126 uint32_t powerVal
, rssiThrReg
;
127 uint32_t ackTpcPow
, ctsTpcPow
, chirpTpcPow
;
129 OS_MARK(ah
, AH_MARK_RESET
, bChannelChange
);
130 #define IS(_c,_f) (((_c)->channelFlags & _f) || 0)
131 if ((IS(chan
, CHANNEL_2GHZ
) ^ IS(chan
, CHANNEL_5GHZ
)) == 0) {
132 HALDEBUG(ah
, HAL_DEBUG_ANY
,
133 "%s: invalid channel %u/0x%x; not marked as 2GHz or 5GHz\n",
134 __func__
, chan
->channel
, chan
->channelFlags
);
137 if ((IS(chan
, CHANNEL_OFDM
) ^ IS(chan
, CHANNEL_CCK
)) == 0) {
138 HALDEBUG(ah
, HAL_DEBUG_ANY
,
139 "%s: invalid channel %u/0x%x; not marked as OFDM or CCK\n",
140 __func__
, chan
->channel
, chan
->channelFlags
);
145 /* Bring out of sleep mode */
146 if (!ar5416SetPowerMode(ah
, HAL_PM_AWAKE
, AH_TRUE
)) {
147 HALDEBUG(ah
, HAL_DEBUG_ANY
, "%s: chip did not wakeup\n",
153 * Map public channel to private.
155 ichan
= ath_hal_checkchannel(ah
, chan
);
156 if (ichan
== AH_NULL
) {
157 HALDEBUG(ah
, HAL_DEBUG_ANY
,
158 "%s: invalid channel %u/0x%x; no mapping\n",
159 __func__
, chan
->channel
, chan
->channelFlags
);
162 HALDEBUG(ah
, HAL_DEBUG_RESET
,
163 "%s: Ch=%u Max=%d Min=%d\n",__func__
,
164 ichan
->channel
, ichan
->maxTxPower
, ichan
->minTxPower
);
173 HALDEBUG(ah
, HAL_DEBUG_ANY
, "%s: invalid operating mode %u\n",
178 HALASSERT(AH_PRIVATE(ah
)->ah_eeversion
>= AR_EEPROM_VER14_1
);
180 /* XXX Turn on fast channel change for 5416 */
182 * Preserve the bmiss rssi threshold and count threshold
185 rssiThrReg
= OS_REG_READ(ah
, AR_RSSI_THR
);
186 /* If reg is zero, first time thru set to default val */
188 rssiThrReg
= INIT_RSSI_THR
;
191 * Preserve the antenna on a channel change
193 saveDefAntenna
= OS_REG_READ(ah
, AR_DEF_ANTENNA
);
194 if (saveDefAntenna
== 0) /* XXX magic constants */
197 /* Save hardware flag before chip reset clears the register */
198 macStaId1
= OS_REG_READ(ah
, AR_STA_ID1
) &
199 (AR_STA_ID1_BASE_RATE_11B
| AR_STA_ID1_USE_DEFANT
);
201 /* Save led state from pci config register */
202 saveLedState
= OS_REG_READ(ah
, AR_MAC_LED
) &
203 (AR_MAC_LED_ASSOC
| AR_MAC_LED_MODE
|
204 AR_MAC_LED_BLINK_THRESH_SEL
| AR_MAC_LED_BLINK_SLOW
);
205 softLedCfg
= OS_REG_READ(ah
, AR_GPIO_INTR_OUT
);
208 * Adjust gain parameters before reset if
209 * there's an outstanding gain updated.
211 (void) ar5416GetRfgain(ah
);
213 if (!ar5416ChipReset(ah
, chan
)) {
214 HALDEBUG(ah
, HAL_DEBUG_ANY
, "%s: chip reset failed\n", __func__
);
218 /* Restore bmiss rssi & count thresholds */
219 OS_REG_WRITE(ah
, AR_RSSI_THR
, rssiThrReg
);
221 /* Setup the indices for the next set of register array writes */
222 /* XXX Ignore 11n dynamic mode on the AR5416 for the moment */
223 switch (chan
->channelFlags
& CHANNEL_ALL
) {
230 case CHANNEL_A_HT40PLUS
:
231 case CHANNEL_A_HT40MINUS
:
237 case CHANNEL_B
: /* treat as channel G , no B mode suport in owl */
241 case CHANNEL_G_HT40PLUS
:
242 case CHANNEL_G_HT40MINUS
:
251 HALDEBUG(ah
, HAL_DEBUG_ANY
, "%s: invalid channel flags 0x%x\n",
252 __func__
, chan
->channelFlags
);
256 OS_MARK(ah
, AH_MARK_RESET_LINE
, __LINE__
);
258 /* Set correct Baseband to analog shift setting to access analog chips. */
259 OS_REG_WRITE(ah
, AR_PHY(0), 0x00000007);
264 OS_REG_WRITE(ah
, AR_PHY_ADC_SERIAL_CTL
, AR_PHY_SEL_EXTERNAL_RADIO
);
266 /* NB: only required for Sowl */
267 ar5416EepromSetAddac(ah
, ichan
);
269 regWrites
= ath_hal_ini_write(ah
, &AH5416(ah
)->ah_ini_addac
, 1,
271 OS_REG_WRITE(ah
, AR_PHY_ADC_SERIAL_CTL
, AR_PHY_SEL_INTERNAL_ADDAC
);
273 /* XXX Merlin ini fixups */
274 /* XXX Merlin 100us delay for shift registers */
275 regWrites
= ath_hal_ini_write(ah
, &ahp
->ah_ini_modes
, modesIndex
,
277 #ifdef AH_SUPPORT_AR9280
278 if (AR_SREV_MERLIN_20_OR_LATER(ah
)) {
279 regWrites
= ath_hal_ini_write(ah
, &AH9280(ah
)->ah_ini_rxgain
,
280 modesIndex
, regWrites
);
281 regWrites
= ath_hal_ini_write(ah
, &AH9280(ah
)->ah_ini_txgain
,
282 modesIndex
, regWrites
);
285 /* XXX Merlin 100us delay for shift registers */
286 regWrites
= ath_hal_ini_write(ah
, &ahp
->ah_ini_common
, 1, regWrites
);
287 /* Setup 11n MAC/Phy mode registers */
288 ar5416Set11nRegs(ah
,chan
);
289 /* XXX updated regWrites? */
290 ahp
->ah_rfHal
->writeRegs(ah
, modesIndex
, freqIndex
, regWrites
);
291 #ifdef AH_SUPPORT_AR9280
292 if (AR_SREV_MERLIN_20(ah
) && IS_5GHZ_FAST_CLOCK_EN(ah
, chan
)) {
293 /* 5GHz channels w/ Fast Clock use different modal values */
294 regWrites
= ath_hal_ini_write(ah
, &AH9280(ah
)->ah_ini_xmodes
,
295 modesIndex
, regWrites
);
299 OS_MARK(ah
, AH_MARK_RESET_LINE
, __LINE__
);
301 HALDEBUG(ah
, HAL_DEBUG_RESET
, ">>>2 %s: AR_PHY_DAG_CTRLCCK=0x%x\n",
302 __func__
, OS_REG_READ(ah
,AR_PHY_DAG_CTRLCCK
));
303 HALDEBUG(ah
, HAL_DEBUG_RESET
, ">>>2 %s: AR_PHY_ADC_CTL=0x%x\n",
304 __func__
, OS_REG_READ(ah
,AR_PHY_ADC_CTL
));
306 /* Set the mute mask to the correct default */
307 if (AH_PRIVATE(ah
)->ah_phyRev
>= AR_PHY_CHIP_ID_REV_2
)
308 OS_REG_WRITE(ah
, AR_SEQ_MASK
, 0x0000000F);
310 if (AH_PRIVATE(ah
)->ah_phyRev
>= AR_PHY_CHIP_ID_REV_3
) {
311 /* Clear reg to alllow RX_CLEAR line debug */
312 OS_REG_WRITE(ah
, AR_PHY_BLUETOOTH
, 0);
314 if (AH_PRIVATE(ah
)->ah_phyRev
>= AR_PHY_CHIP_ID_REV_4
) {
316 /* Enable burst prefetch for the data queues */
317 OS_REG_RMW_FIELD(ah
, AR_D_FPCTL
, ... );
318 /* Enable double-buffering */
319 OS_REG_CLR_BIT(ah
, AR_TXCFG
, AR_TXCFG_DBL_BUF_DIS
);
323 /* Set ADC/DAC select values */
324 OS_REG_WRITE(ah
, AR_PHY_SLEEP_SCAL
, 0x0e);
326 if (AH5416(ah
)->ah_rx_chainmask
== 0x5 ||
327 AH5416(ah
)->ah_tx_chainmask
== 0x5)
328 OS_REG_WRITE(ah
, AR_PHY_ANALOG_SWAP
, AR_PHY_SWAP_ALT_CHAIN
);
329 /* Setup Chain Masks */
330 OS_REG_WRITE(ah
, AR_PHY_RX_CHAINMASK
, AH5416(ah
)->ah_rx_chainmask
);
331 OS_REG_WRITE(ah
, AR_PHY_CAL_CHAINMASK
, AH5416(ah
)->ah_rx_chainmask
);
332 OS_REG_WRITE(ah
, AR_SELFGEN_MASK
, AH5416(ah
)->ah_tx_chainmask
);
334 /* Setup the transmit power values. */
335 if (!ar5416SetTransmitPower(ah
, ichan
, rfXpdGain
)) {
336 HALDEBUG(ah
, HAL_DEBUG_ANY
,
337 "%s: error init'ing transmit power\n", __func__
);
341 /* Write the analog registers */
342 if (!ahp
->ah_rfHal
->setRfRegs(ah
, ichan
, freqIndex
, rfXpdGain
)) {
343 HALDEBUG(ah
, HAL_DEBUG_ANY
,
344 "%s: ar5212SetRfRegs failed\n", __func__
);
348 /* Write delta slope for OFDM enabled modes (A, G, Turbo) */
349 if (IS_CHAN_OFDM(chan
)|| IS_CHAN_HT(chan
))
350 ar5416SetDeltaSlope(ah
, ichan
);
352 #ifdef AH_SUPPORT_AR9280
353 if (AR_SREV_MERLIN_10_OR_LATER(ah
))
354 ar9280SpurMitigate(ah
, ichan
);
357 ar5416SpurMitigate(ah
, ichan
);
359 /* Setup board specific options for EEPROM version 3 */
360 if (!ar5416SetBoardValues(ah
, ichan
)) {
361 HALDEBUG(ah
, HAL_DEBUG_ANY
,
362 "%s: error setting board options\n", __func__
);
366 OS_MARK(ah
, AH_MARK_RESET_LINE
, __LINE__
);
368 OS_REG_WRITE(ah
, AR_STA_ID0
, LE_READ_4(ahp
->ah_macaddr
));
369 OS_REG_WRITE(ah
, AR_STA_ID1
, LE_READ_2(ahp
->ah_macaddr
+ 4)
371 | AR_STA_ID1_RTS_USE_DEF
372 | ahp
->ah_staId1Defaults
374 ar5212SetOperatingMode(ah
, opmode
);
376 /* Set Venice BSSID mask according to current state */
377 OS_REG_WRITE(ah
, AR_BSSMSKL
, LE_READ_4(ahp
->ah_bssidmask
));
378 OS_REG_WRITE(ah
, AR_BSSMSKU
, LE_READ_2(ahp
->ah_bssidmask
+ 4));
380 /* Restore previous led state */
381 OS_REG_WRITE(ah
, AR_MAC_LED
, OS_REG_READ(ah
, AR_MAC_LED
) | saveLedState
);
382 /* Restore soft Led state to GPIO */
383 OS_REG_WRITE(ah
, AR_GPIO_INTR_OUT
, softLedCfg
);
385 /* Restore previous antenna */
386 OS_REG_WRITE(ah
, AR_DEF_ANTENNA
, saveDefAntenna
);
389 OS_REG_WRITE(ah
, AR_BSS_ID0
, LE_READ_4(ahp
->ah_bssid
));
390 OS_REG_WRITE(ah
, AR_BSS_ID1
, LE_READ_2(ahp
->ah_bssid
+ 4));
392 /* Restore bmiss rssi & count thresholds */
393 OS_REG_WRITE(ah
, AR_RSSI_THR
, ahp
->ah_rssiThr
);
395 OS_REG_WRITE(ah
, AR_ISR
, ~0); /* cleared on write */
397 if (!ar5212SetChannel(ah
, ichan
))
400 OS_MARK(ah
, AH_MARK_RESET_LINE
, __LINE__
);
402 /* Set 1:1 QCU to DCU mapping for all queues */
403 for (i
= 0; i
< AR_NUM_DCU
; i
++)
404 OS_REG_WRITE(ah
, AR_DQCUMASK(i
), 1 << i
);
406 ahp
->ah_intrTxqs
= 0;
407 for (i
= 0; i
< AH_PRIVATE(ah
)->ah_caps
.halTotalQueues
; i
++)
408 ar5212ResetTxQueue(ah
, i
);
410 ar5416InitIMR(ah
, opmode
);
411 ar5212SetCoverageClass(ah
, AH_PRIVATE(ah
)->ah_coverageClass
, 1);
413 ar5416InitUserSettings(ah
);
416 * disable seq number generation in hw
418 OS_REG_WRITE(ah
, AR_STA_ID1
,
419 OS_REG_READ(ah
, AR_STA_ID1
) | AR_STA_ID1_PRESERVE_SEQNUM
);
424 * program OBS bus to see MAC interrupts
426 OS_REG_WRITE(ah
, AR_OBS
, 8);
428 #ifdef AR5416_INT_MITIGATION
429 OS_REG_WRITE(ah
, AR_MIRT
, 0);
430 OS_REG_RMW_FIELD(ah
, AR_RIMT
, AR_RIMT_LAST
, 500);
431 OS_REG_RMW_FIELD(ah
, AR_RIMT
, AR_RIMT_FIRST
, 2000);
434 ar5416InitBB(ah
, chan
);
436 /* Setup compression registers */
437 ar5212SetCompRegs(ah
); /* XXX not needed? */
440 * 5416 baseband will check the per rate power table
441 * and select the lower of the two
446 powerVal
= SM(ackTpcPow
, AR_TPC_ACK
) |
447 SM(ctsTpcPow
, AR_TPC_CTS
) |
448 SM(chirpTpcPow
, AR_TPC_CHIRP
);
449 OS_REG_WRITE(ah
, AR_TPC
, powerVal
);
451 if (!ar5416InitCal(ah
, chan
))
454 AH_PRIVATE(ah
)->ah_opmode
= opmode
; /* record operating mode */
456 if (bChannelChange
) {
457 if (!(ichan
->privFlags
& CHANNEL_DFS
))
458 ichan
->privFlags
&= ~CHANNEL_INTERFERENCE
;
459 chan
->channelFlags
= ichan
->channelFlags
;
460 chan
->privFlags
= ichan
->privFlags
;
461 chan
->maxRegTxPower
= ichan
->maxRegTxPower
;
462 chan
->maxTxPower
= ichan
->maxTxPower
;
463 chan
->minTxPower
= ichan
->minTxPower
;
466 HALDEBUG(ah
, HAL_DEBUG_RESET
, "%s: done\n", __func__
);
468 OS_MARK(ah
, AH_MARK_RESET_DONE
, 0);
472 OS_MARK(ah
, AH_MARK_RESET_DONE
, ecode
);
482 * This channel change evaluates whether the selected hardware can
483 * perform a synthesizer-only channel change (no reset). If the
484 * TX is not stopped, or the RFBus cannot be granted in the given
485 * time, the function returns false as a reset is necessary
488 ar5416ChannelChange(struct ath_hal
*ah
, HAL_CHANNEL
*chan
)
491 uint32_t data
, synthDelay
, qnum
;
492 uint16_t rfXpdGain
[4];
493 struct ath_hal_5212
*ahp
= AH5212(ah
);
494 HAL_CHANNEL_INTERNAL
*ichan
;
497 * Map public channel to private.
499 ichan
= ath_hal_checkchannel(ah
, chan
);
501 /* TX must be stopped or RF Bus grant will not work */
502 for (qnum
= 0; qnum
< AH_PRIVATE(ah
)->ah_caps
.halTotalQueues
; qnum
++) {
503 if (ar5212NumTxPending(ah
, qnum
)) {
504 HALDEBUG(ah
, HAL_DEBUG_ANY
,
505 "%s: frames pending on queue %d\n", __func__
, qnum
);
511 * Kill last Baseband Rx Frame - Request analog bus grant
513 OS_REG_WRITE(ah
, AR_PHY_RFBUS_REQ
, AR_PHY_RFBUS_REQ_REQUEST
);
514 if (!ath_hal_wait(ah
, AR_PHY_RFBUS_GNT
, AR_PHY_RFBUS_GRANT_EN
, AR_PHY_RFBUS_GRANT_EN
)) {
515 HALDEBUG(ah
, HAL_DEBUG_ANY
, "%s: could not kill baseband rx\n",
520 ar5416Set11nRegs(ah
, chan
); /* NB: setup 5416-specific regs */
522 /* Change the synth */
523 if (!ar5212SetChannel(ah
, ichan
))
526 /* Setup the transmit power values. */
527 if (!ar5416SetTransmitPower(ah
, ichan
, rfXpdGain
)) {
528 HALDEBUG(ah
, HAL_DEBUG_ANY
,
529 "%s: error init'ing transmit power\n", __func__
);
534 * Wait for the frequency synth to settle (synth goes on
535 * via PHY_ACTIVE_EN). Read the phy active delay register.
536 * Value is in 100ns increments.
538 data
= OS_REG_READ(ah
, AR_PHY_RX_DELAY
) & AR_PHY_RX_DELAY_DELAY
;
539 if (IS_CHAN_CCK(ichan
)) {
540 synthDelay
= (4 * data
) / 22;
542 synthDelay
= data
/ 10;
545 OS_DELAY(synthDelay
+ BASE_ACTIVATE_DELAY
);
547 /* Release the RFBus Grant */
548 OS_REG_WRITE(ah
, AR_PHY_RFBUS_REQ
, 0);
550 /* Write delta slope for OFDM enabled modes (A, G, Turbo) */
551 if (IS_CHAN_OFDM(ichan
)|| IS_CHAN_HT(chan
)) {
552 if (ahp
->ah_eeprom
.ee_version
>= AR_EEPROM_VER5_3
&&
554 ar5212SetSpurMitigation(ah
, ichan
);
555 ar5416SetDeltaSlope(ah
, ichan
);
558 /* XXX spur mitigation for Melin */
560 /* Copy over internal channel flags to public hal channel */
562 if (!(ichan
->privFlags
& CHANNEL_DFS
))
563 ichan
->privFlags
&= ~CHANNEL_INTERFERENCE
;
564 chan
->channelFlags
= ichan
->channelFlags
;
565 chan
->privFlags
= ichan
->privFlags
;
566 chan
->maxRegTxPower
= ichan
->maxRegTxPower
;
567 chan
->maxTxPower
= ichan
->maxTxPower
;
568 chan
->minTxPower
= ichan
->minTxPower
;
569 AH_PRIVATE(ah
)->ah_curchan
->ah_channel_time
=0;
570 AH_PRIVATE(ah
)->ah_curchan
->ah_tsf_last
= ar5212GetTsf64(ah
);
571 ar5212TxEnable(ah
,AH_TRUE
);
577 ar5416InitDMA(struct ath_hal
*ah
)
581 * set AHB_MODE not to do cacheline prefetches
583 OS_REG_SET_BIT(ah
, AR_AHB_MODE
, AR_AHB_PREFETCH_RD_EN
);
586 * let mac dma reads be in 128 byte chunks
588 OS_REG_WRITE(ah
, AR_TXCFG
,
589 (OS_REG_READ(ah
, AR_TXCFG
) & ~AR_TXCFG_DMASZ_MASK
) | AR_TXCFG_DMASZ_128B
);
592 * let mac dma writes be in 128 byte chunks
594 OS_REG_WRITE(ah
, AR_RXCFG
,
595 (OS_REG_READ(ah
, AR_RXCFG
) & ~AR_RXCFG_DMASZ_MASK
) | AR_RXCFG_DMASZ_128B
);
597 /* XXX restore TX trigger level */
600 * Setup receive FIFO threshold to hold off TX activities
602 OS_REG_WRITE(ah
, AR_RXFIFO_CFG
, 0x200);
605 * reduce the number of usable entries in PCU TXBUF to avoid
608 OS_REG_WRITE(ah
, AR_PCU_TXBUF_CTRL
, AR_PCU_TXBUF_CTRL_USABLE_SIZE
);
612 ar5416InitBB(struct ath_hal
*ah
, HAL_CHANNEL
*chan
)
617 * Wait for the frequency synth to settle (synth goes on
618 * via AR_PHY_ACTIVE_EN). Read the phy active delay register.
619 * Value is in 100ns increments.
621 synthDelay
= OS_REG_READ(ah
, AR_PHY_RX_DELAY
) & AR_PHY_RX_DELAY_DELAY
;
622 if (IS_CHAN_CCK(chan
)) {
623 synthDelay
= (4 * synthDelay
) / 22;
628 /* Turn on PLL on 5416 */
629 HALDEBUG(ah
, HAL_DEBUG_RESET
, "%s %s channel\n",
630 __func__
, IS_CHAN_5GHZ(chan
) ? "5GHz" : "2GHz");
631 ar5416InitPLL(ah
, chan
);
633 /* Activate the PHY (includes baseband activate and synthesizer on) */
634 OS_REG_WRITE(ah
, AR_PHY_ACTIVE
, AR_PHY_ACTIVE_EN
);
637 * If the AP starts the calibration before the base band timeout
638 * completes we could get rx_clear false triggering. Add an
639 * extra BASE_ACTIVATE_DELAY usecs to ensure this condition
642 if (IS_CHAN_HALF_RATE(AH_PRIVATE(ah
)->ah_curchan
)) {
643 OS_DELAY((synthDelay
<< 1) + BASE_ACTIVATE_DELAY
);
644 } else if (IS_CHAN_QUARTER_RATE(AH_PRIVATE(ah
)->ah_curchan
)) {
645 OS_DELAY((synthDelay
<< 2) + BASE_ACTIVATE_DELAY
);
647 OS_DELAY(synthDelay
+ BASE_ACTIVATE_DELAY
);
652 ar5416InitIMR(struct ath_hal
*ah
, HAL_OPMODE opmode
)
654 struct ath_hal_5212
*ahp
= AH5212(ah
);
657 * Setup interrupt handling. Note that ar5212ResetTxQueue
658 * manipulates the secondary IMR's as queues are enabled
659 * and disabled. This is done with RMW ops to insure the
660 * settings we make here are preserved.
662 ahp
->ah_maskReg
= AR_IMR_TXERR
| AR_IMR_TXURN
663 | AR_IMR_RXERR
| AR_IMR_RXORN
666 #ifdef AR5416_INT_MITIGATION
667 ahp
->ah_maskReg
|= AR_IMR_TXINTM
| AR_IMR_RXINTM
668 | AR_IMR_TXMINTR
| AR_IMR_RXMINTR
;
670 ahp
->ah_maskReg
|= AR_IMR_TXOK
| AR_IMR_RXOK
;
672 if (opmode
== HAL_M_HOSTAP
)
673 ahp
->ah_maskReg
|= AR_IMR_MIB
;
674 OS_REG_WRITE(ah
, AR_IMR
, ahp
->ah_maskReg
);
675 /* Enable bus errors that are OR'd to set the HIUERR bit */
678 OS_REG_WRITE(ah
, AR_IMR_S2
,
679 OS_REG_READ(ah
, AR_IMR_S2
) | AR_IMR_S2_GTT
| AR_IMR_S2_CST
);
684 ar5416InitQoS(struct ath_hal
*ah
)
687 OS_REG_WRITE(ah
, AR_QOS_CONTROL
, 0x100aa); /* XXX magic */
688 OS_REG_WRITE(ah
, AR_QOS_SELECT
, 0x3210); /* XXX magic */
690 /* Turn on NOACK Support for QoS packets */
691 OS_REG_WRITE(ah
, AR_NOACK
,
692 SM(2, AR_NOACK_2BIT_VALUE
) |
693 SM(5, AR_NOACK_BIT_OFFSET
) |
694 SM(0, AR_NOACK_BYTE_OFFSET
));
697 * initialize TXOP for all TIDs
699 OS_REG_WRITE(ah
, AR_TXOP_X
, AR_TXOP_X_VAL
);
700 OS_REG_WRITE(ah
, AR_TXOP_0_3
, 0xFFFFFFFF);
701 OS_REG_WRITE(ah
, AR_TXOP_4_7
, 0xFFFFFFFF);
702 OS_REG_WRITE(ah
, AR_TXOP_8_11
, 0xFFFFFFFF);
703 OS_REG_WRITE(ah
, AR_TXOP_12_15
, 0xFFFFFFFF);
707 ar5416InitUserSettings(struct ath_hal
*ah
)
709 struct ath_hal_5212
*ahp
= AH5212(ah
);
711 /* Restore user-specified settings */
712 if (ahp
->ah_miscMode
!= 0)
713 OS_REG_WRITE(ah
, AR_MISC_MODE
, ahp
->ah_miscMode
);
714 if (ahp
->ah_sifstime
!= (u_int
) -1)
715 ar5212SetSifsTime(ah
, ahp
->ah_sifstime
);
716 if (ahp
->ah_slottime
!= (u_int
) -1)
717 ar5212SetSlotTime(ah
, ahp
->ah_slottime
);
718 if (ahp
->ah_acktimeout
!= (u_int
) -1)
719 ar5212SetAckTimeout(ah
, ahp
->ah_acktimeout
);
720 if (ahp
->ah_ctstimeout
!= (u_int
) -1)
721 ar5212SetCTSTimeout(ah
, ahp
->ah_ctstimeout
);
722 if (AH_PRIVATE(ah
)->ah_diagreg
!= 0)
723 OS_REG_WRITE(ah
, AR_DIAG_SW
, AH_PRIVATE(ah
)->ah_diagreg
);
725 if (ahp
->ah_globaltxtimeout
!= (u_int
) -1)
726 ar5416SetGlobalTxTimeout(ah
, ahp
->ah_globaltxtimeout
);
731 * Places the hardware into reset and then pulls it out of reset
734 ar5416ChipReset(struct ath_hal
*ah
, HAL_CHANNEL
*chan
)
738 OS_MARK(ah
, AH_MARK_CHIPRESET
, chan
? chan
->channel
: 0);
740 * Warm reset is optimistic.
742 if (AR_SREV_MERLIN_20_OR_LATER(ah
) &&
743 ath_hal_eepromGetFlag(ah
, AR_EEP_OL_PWRCTRL
)) {
744 if (!ar5416SetResetReg(ah
, HAL_RESET_POWER_ON
))
747 if (!ar5416SetResetReg(ah
, HAL_RESET_WARM
))
751 /* Bring out of sleep mode (AGAIN) */
752 if (!ar5416SetPowerMode(ah
, HAL_PM_AWAKE
, AH_TRUE
))
755 ar5416InitPLL(ah
, chan
);
758 * Perform warm reset before the mode/PLL/turbo registers
759 * are changed in order to deactivate the radio. Mode changes
760 * with an active radio can result in corrupted shifts to the
763 if (chan
!= AH_NULL
) {
764 /* treat channel B as channel G , no B mode suport in owl */
765 rfMode
|= (IS_CHAN_G(chan
) || IS_CHAN_B(chan
)) ?
766 AR_PHY_MODE_DYNAMIC
: AR_PHY_MODE_OFDM
;
767 if (AR_SREV_MERLIN_20(ah
) && IS_5GHZ_FAST_CLOCK_EN(ah
, chan
)) {
768 /* phy mode bits for 5GHz channels require Fast Clock */
769 rfMode
|= AR_PHY_MODE_DYNAMIC
770 | AR_PHY_MODE_DYN_CCK_DISABLE
;
771 } else if (!AR_SREV_MERLIN_10_OR_LATER(ah
)) {
772 rfMode
|= (IS_CHAN_5GHZ(chan
)) ?
773 AR_PHY_MODE_RF5GHZ
: AR_PHY_MODE_RF2GHZ
;
775 OS_REG_WRITE(ah
, AR_PHY_MODE
, rfMode
);
781 * Delta slope coefficient computation.
782 * Required for OFDM operation.
785 ar5416GetDeltaSlopeValues(struct ath_hal
*ah
, uint32_t coef_scaled
,
786 uint32_t *coef_mantissa
, uint32_t *coef_exponent
)
788 #define COEF_SCALE_S 24
789 uint32_t coef_exp
, coef_man
;
791 * ALGO -> coef_exp = 14-floor(log2(coef));
792 * floor(log2(x)) is the highest set bit position
794 for (coef_exp
= 31; coef_exp
> 0; coef_exp
--)
795 if ((coef_scaled
>> coef_exp
) & 0x1)
797 /* A coef_exp of 0 is a legal bit position but an unexpected coef_exp */
799 coef_exp
= 14 - (coef_exp
- COEF_SCALE_S
);
802 * ALGO -> coef_man = floor(coef* 2^coef_exp+0.5);
803 * The coefficient is already shifted up for scaling
805 coef_man
= coef_scaled
+ (1 << (COEF_SCALE_S
- coef_exp
- 1));
807 *coef_mantissa
= coef_man
>> (COEF_SCALE_S
- coef_exp
);
808 *coef_exponent
= coef_exp
- 16;
814 ar5416SetDeltaSlope(struct ath_hal
*ah
, HAL_CHANNEL_INTERNAL
*chan
)
816 #define INIT_CLOCKMHZSCALED 0x64000000
817 uint32_t coef_scaled
, ds_coef_exp
, ds_coef_man
;
818 uint32_t clockMhzScaled
= INIT_CLOCKMHZSCALED
;
820 CHAN_CENTERS centers
;
822 if (IS_CHAN_TURBO(chan
))
824 /* half and quarter rate can divide the scaled clock by 2 or 4 respectively */
825 /* scale for selected channel bandwidth */
826 if (IS_CHAN_HALF_RATE(chan
)) {
827 clockMhzScaled
= clockMhzScaled
>> 1;
828 } else if (IS_CHAN_QUARTER_RATE(chan
)) {
829 clockMhzScaled
= clockMhzScaled
>> 2;
833 * ALGO -> coef = 1e8/fcarrier*fclock/40;
834 * scaled coef to provide precision for this floating calculation
836 ar5416GetChannelCenters(ah
, chan
, ¢ers
);
837 coef_scaled
= clockMhzScaled
/ centers
.synth_center
;
839 ar5416GetDeltaSlopeValues(ah
, coef_scaled
, &ds_coef_man
, &ds_coef_exp
);
841 OS_REG_RMW_FIELD(ah
, AR_PHY_TIMING3
,
842 AR_PHY_TIMING3_DSC_MAN
, ds_coef_man
);
843 OS_REG_RMW_FIELD(ah
, AR_PHY_TIMING3
,
844 AR_PHY_TIMING3_DSC_EXP
, ds_coef_exp
);
848 * scaled coeff is 9/10 that of normal coeff
850 coef_scaled
= (9 * coef_scaled
)/10;
852 ar5416GetDeltaSlopeValues(ah
, coef_scaled
, &ds_coef_man
, &ds_coef_exp
);
855 OS_REG_RMW_FIELD(ah
, AR_PHY_HALFGI
,
856 AR_PHY_HALFGI_DSC_MAN
, ds_coef_man
);
857 OS_REG_RMW_FIELD(ah
, AR_PHY_HALFGI
,
858 AR_PHY_HALFGI_DSC_EXP
, ds_coef_exp
);
859 #undef INIT_CLOCKMHZSCALED
863 * Convert to baseband spur frequency given input channel frequency
864 * and compute register settings below.
866 #define SPUR_RSSI_THRESH 40
869 ar5416SpurMitigate(struct ath_hal
*ah
, HAL_CHANNEL_INTERNAL
*chan
)
871 static const int pilot_mask_reg
[4] = { AR_PHY_TIMING7
, AR_PHY_TIMING8
,
872 AR_PHY_PILOT_MASK_01_30
, AR_PHY_PILOT_MASK_31_60
};
873 static const int chan_mask_reg
[4] = { AR_PHY_TIMING9
, AR_PHY_TIMING10
,
874 AR_PHY_CHANNEL_MASK_01_30
, AR_PHY_CHANNEL_MASK_31_60
};
875 static const int inc
[4] = { 0, 100, 0, 0 };
877 int bb_spur
= AR_NO_SPUR
;
880 int spur_delta_phase
;
882 int upper
, lower
, cur_vit_mask
;
891 HAL_BOOL is2GHz
= IS_CHAN_2GHZ(chan
);
893 OS_MEMZERO(mask_m
, sizeof(mask_m
));
894 OS_MEMZERO(mask_p
, sizeof(mask_p
));
897 * Need to verify range +/- 9.5 for static ht20, otherwise spur
898 * is out-of-band and can be ignored.
900 for (i
= 0; i
< AR5416_EEPROM_MODAL_SPURS
; i
++) {
901 cur_bb_spur
= ath_hal_getSpurChan(ah
, i
, is2GHz
);
902 if (AR_NO_SPUR
== cur_bb_spur
)
904 cur_bb_spur
= cur_bb_spur
- (chan
->channel
* 10);
905 if ((cur_bb_spur
> -95) && (cur_bb_spur
< 95)) {
906 bb_spur
= cur_bb_spur
;
910 if (AR_NO_SPUR
== bb_spur
)
915 tmp
= OS_REG_READ(ah
, AR_PHY_TIMING_CTRL4_CHAIN(0));
916 new = tmp
| (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI
|
917 AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER
|
918 AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK
|
919 AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK
);
921 OS_REG_WRITE(ah
, AR_PHY_TIMING_CTRL4_CHAIN(0), new);
923 new = (AR_PHY_SPUR_REG_MASK_RATE_CNTL
|
924 AR_PHY_SPUR_REG_ENABLE_MASK_PPM
|
925 AR_PHY_SPUR_REG_MASK_RATE_SELECT
|
926 AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI
|
927 SM(SPUR_RSSI_THRESH
, AR_PHY_SPUR_REG_SPUR_RSSI_THRESH
));
928 OS_REG_WRITE(ah
, AR_PHY_SPUR_REG
, new);
930 * Should offset bb_spur by +/- 10 MHz for dynamic 2040 MHz
931 * config, no offset for HT20.
932 * spur_delta_phase = bb_spur/40 * 2**21 for static ht20,
935 spur_delta_phase
= ((bb_spur
* 524288) / 100) &
936 AR_PHY_TIMING11_SPUR_DELTA_PHASE
;
938 * in 11A mode the denominator of spur_freq_sd should be 40 and
939 * it should be 44 in 11G
941 denominator
= IS_CHAN_2GHZ(chan
) ? 440 : 400;
942 spur_freq_sd
= ((bb_spur
* 2048) / denominator
) & 0x3ff;
944 new = (AR_PHY_TIMING11_USE_SPUR_IN_AGC
|
945 SM(spur_freq_sd
, AR_PHY_TIMING11_SPUR_FREQ_SD
) |
946 SM(spur_delta_phase
, AR_PHY_TIMING11_SPUR_DELTA_PHASE
));
947 OS_REG_WRITE(ah
, AR_PHY_TIMING11
, new);
951 * ============================================
952 * pilot mask 1 [31:0] = +6..-26, no 0 bin
953 * pilot mask 2 [19:0] = +26..+7
955 * channel mask 1 [31:0] = +6..-26, no 0 bin
956 * channel mask 2 [19:0] = +26..+7
963 for (i
= 0; i
< 4; i
++) {
967 for (bp
= 0; bp
< 30; bp
++) {
968 if ((cur_bin
> lower
) && (cur_bin
< upper
)) {
969 pilot_mask
= pilot_mask
| 0x1 << bp
;
970 chan_mask
= chan_mask
| 0x1 << bp
;
975 OS_REG_WRITE(ah
, pilot_mask_reg
[i
], pilot_mask
);
976 OS_REG_WRITE(ah
, chan_mask_reg
[i
], chan_mask
);
979 /* =================================================
980 * viterbi mask 1 based on channel magnitude
982 * - mask (-27 to 27) (reg 64,0x9900 to 67,0x990c)
983 * [1 2 2 1] for -9.6 or [1 2 1] for +16
984 * - enable_mask_ppm, all bins move with freq
986 * - mask_select, 8 bits for rates (reg 67,0x990c)
987 * - mask_rate_cntl, 8 bits for rates (reg 67,0x990c)
988 * choose which mask to use mask or mask2
992 * viterbi mask 2 2nd set for per data rate puncturing
994 * - mask_select, 8 bits for rates (reg 67)
995 * - mask (-27 to 27) (reg 98,0x9988 to 101,0x9994)
996 * [1 2 2 1] for -9.6 or [1 2 1] for +16
1002 for (i
= 0; i
< 123; i
++) {
1003 if ((cur_vit_mask
> lower
) && (cur_vit_mask
< upper
)) {
1004 if ((abs(cur_vit_mask
- bin
)) < 75) {
1009 if (cur_vit_mask
< 0) {
1010 mask_m
[abs(cur_vit_mask
/ 100)] = mask_amt
;
1012 mask_p
[cur_vit_mask
/ 100] = mask_amt
;
1015 cur_vit_mask
-= 100;
1018 tmp_mask
= (mask_m
[46] << 30) | (mask_m
[47] << 28)
1019 | (mask_m
[48] << 26) | (mask_m
[49] << 24)
1020 | (mask_m
[50] << 22) | (mask_m
[51] << 20)
1021 | (mask_m
[52] << 18) | (mask_m
[53] << 16)
1022 | (mask_m
[54] << 14) | (mask_m
[55] << 12)
1023 | (mask_m
[56] << 10) | (mask_m
[57] << 8)
1024 | (mask_m
[58] << 6) | (mask_m
[59] << 4)
1025 | (mask_m
[60] << 2) | (mask_m
[61] << 0);
1026 OS_REG_WRITE(ah
, AR_PHY_BIN_MASK_1
, tmp_mask
);
1027 OS_REG_WRITE(ah
, AR_PHY_VIT_MASK2_M_46_61
, tmp_mask
);
1029 tmp_mask
= (mask_m
[31] << 28)
1030 | (mask_m
[32] << 26) | (mask_m
[33] << 24)
1031 | (mask_m
[34] << 22) | (mask_m
[35] << 20)
1032 | (mask_m
[36] << 18) | (mask_m
[37] << 16)
1033 | (mask_m
[48] << 14) | (mask_m
[39] << 12)
1034 | (mask_m
[40] << 10) | (mask_m
[41] << 8)
1035 | (mask_m
[42] << 6) | (mask_m
[43] << 4)
1036 | (mask_m
[44] << 2) | (mask_m
[45] << 0);
1037 OS_REG_WRITE(ah
, AR_PHY_BIN_MASK_2
, tmp_mask
);
1038 OS_REG_WRITE(ah
, AR_PHY_MASK2_M_31_45
, tmp_mask
);
1040 tmp_mask
= (mask_m
[16] << 30) | (mask_m
[16] << 28)
1041 | (mask_m
[18] << 26) | (mask_m
[18] << 24)
1042 | (mask_m
[20] << 22) | (mask_m
[20] << 20)
1043 | (mask_m
[22] << 18) | (mask_m
[22] << 16)
1044 | (mask_m
[24] << 14) | (mask_m
[24] << 12)
1045 | (mask_m
[25] << 10) | (mask_m
[26] << 8)
1046 | (mask_m
[27] << 6) | (mask_m
[28] << 4)
1047 | (mask_m
[29] << 2) | (mask_m
[30] << 0);
1048 OS_REG_WRITE(ah
, AR_PHY_BIN_MASK_3
, tmp_mask
);
1049 OS_REG_WRITE(ah
, AR_PHY_MASK2_M_16_30
, tmp_mask
);
1051 tmp_mask
= (mask_m
[ 0] << 30) | (mask_m
[ 1] << 28)
1052 | (mask_m
[ 2] << 26) | (mask_m
[ 3] << 24)
1053 | (mask_m
[ 4] << 22) | (mask_m
[ 5] << 20)
1054 | (mask_m
[ 6] << 18) | (mask_m
[ 7] << 16)
1055 | (mask_m
[ 8] << 14) | (mask_m
[ 9] << 12)
1056 | (mask_m
[10] << 10) | (mask_m
[11] << 8)
1057 | (mask_m
[12] << 6) | (mask_m
[13] << 4)
1058 | (mask_m
[14] << 2) | (mask_m
[15] << 0);
1059 OS_REG_WRITE(ah
, AR_PHY_MASK_CTL
, tmp_mask
);
1060 OS_REG_WRITE(ah
, AR_PHY_MASK2_M_00_15
, tmp_mask
);
1062 tmp_mask
= (mask_p
[15] << 28)
1063 | (mask_p
[14] << 26) | (mask_p
[13] << 24)
1064 | (mask_p
[12] << 22) | (mask_p
[11] << 20)
1065 | (mask_p
[10] << 18) | (mask_p
[ 9] << 16)
1066 | (mask_p
[ 8] << 14) | (mask_p
[ 7] << 12)
1067 | (mask_p
[ 6] << 10) | (mask_p
[ 5] << 8)
1068 | (mask_p
[ 4] << 6) | (mask_p
[ 3] << 4)
1069 | (mask_p
[ 2] << 2) | (mask_p
[ 1] << 0);
1070 OS_REG_WRITE(ah
, AR_PHY_BIN_MASK2_1
, tmp_mask
);
1071 OS_REG_WRITE(ah
, AR_PHY_MASK2_P_15_01
, tmp_mask
);
1073 tmp_mask
= (mask_p
[30] << 28)
1074 | (mask_p
[29] << 26) | (mask_p
[28] << 24)
1075 | (mask_p
[27] << 22) | (mask_p
[26] << 20)
1076 | (mask_p
[25] << 18) | (mask_p
[24] << 16)
1077 | (mask_p
[23] << 14) | (mask_p
[22] << 12)
1078 | (mask_p
[21] << 10) | (mask_p
[20] << 8)
1079 | (mask_p
[19] << 6) | (mask_p
[18] << 4)
1080 | (mask_p
[17] << 2) | (mask_p
[16] << 0);
1081 OS_REG_WRITE(ah
, AR_PHY_BIN_MASK2_2
, tmp_mask
);
1082 OS_REG_WRITE(ah
, AR_PHY_MASK2_P_30_16
, tmp_mask
);
1084 tmp_mask
= (mask_p
[45] << 28)
1085 | (mask_p
[44] << 26) | (mask_p
[43] << 24)
1086 | (mask_p
[42] << 22) | (mask_p
[41] << 20)
1087 | (mask_p
[40] << 18) | (mask_p
[39] << 16)
1088 | (mask_p
[38] << 14) | (mask_p
[37] << 12)
1089 | (mask_p
[36] << 10) | (mask_p
[35] << 8)
1090 | (mask_p
[34] << 6) | (mask_p
[33] << 4)
1091 | (mask_p
[32] << 2) | (mask_p
[31] << 0);
1092 OS_REG_WRITE(ah
, AR_PHY_BIN_MASK2_3
, tmp_mask
);
1093 OS_REG_WRITE(ah
, AR_PHY_MASK2_P_45_31
, tmp_mask
);
1095 tmp_mask
= (mask_p
[61] << 30) | (mask_p
[60] << 28)
1096 | (mask_p
[59] << 26) | (mask_p
[58] << 24)
1097 | (mask_p
[57] << 22) | (mask_p
[56] << 20)
1098 | (mask_p
[55] << 18) | (mask_p
[54] << 16)
1099 | (mask_p
[53] << 14) | (mask_p
[52] << 12)
1100 | (mask_p
[51] << 10) | (mask_p
[50] << 8)
1101 | (mask_p
[49] << 6) | (mask_p
[48] << 4)
1102 | (mask_p
[47] << 2) | (mask_p
[46] << 0);
1103 OS_REG_WRITE(ah
, AR_PHY_BIN_MASK2_4
, tmp_mask
);
1104 OS_REG_WRITE(ah
, AR_PHY_MASK2_P_61_45
, tmp_mask
);
1107 #ifdef AH_SUPPORT_AR9280
1108 #define AR_BASE_FREQ_2GHZ 2300
1109 #define AR_BASE_FREQ_5GHZ 4900
1110 #define AR_SPUR_FEEQ_BOUND_HT40 19
1111 #define AR_SPUR_FEEQ_BOUND_HT20 10
1114 ar9280SpurMitigate(struct ath_hal
*ah
, HAL_CHANNEL_INTERNAL
*ichan
)
1116 static const int pilot_mask_reg
[4] = { AR_PHY_TIMING7
, AR_PHY_TIMING8
,
1117 AR_PHY_PILOT_MASK_01_30
, AR_PHY_PILOT_MASK_31_60
};
1118 static const int chan_mask_reg
[4] = { AR_PHY_TIMING9
, AR_PHY_TIMING10
,
1119 AR_PHY_CHANNEL_MASK_01_30
, AR_PHY_CHANNEL_MASK_31_60
};
1120 static int inc
[4] = { 0, 100, 0, 0 };
1122 int bb_spur
= AR_NO_SPUR
;
1125 int bb_spur_off
, spur_subchannel_sd
;
1127 int spur_delta_phase
;
1129 int upper
, lower
, cur_vit_mask
;
1132 CHAN_CENTERS centers
;
1139 HAL_BOOL is2GHz
= IS_CHAN_2GHZ(ichan
);
1141 OS_MEMZERO(&mask_m
, sizeof(int8_t) * 123);
1142 OS_MEMZERO(&mask_p
, sizeof(int8_t) * 123);
1144 ar5416GetChannelCenters(ah
, ichan
, ¢ers
);
1145 freq
= centers
.synth_center
;
1148 * Need to verify range +/- 9.38 for static ht20 and +/- 18.75 for ht40,
1149 * otherwise spur is out-of-band and can be ignored.
1151 for (i
= 0; i
< AR5416_EEPROM_MODAL_SPURS
; i
++) {
1152 cur_bb_spur
= ath_hal_getSpurChan(ah
, i
, is2GHz
);
1153 /* Get actual spur freq in MHz from EEPROM read value */
1155 cur_bb_spur
= (cur_bb_spur
/ 10) + AR_BASE_FREQ_2GHZ
;
1157 cur_bb_spur
= (cur_bb_spur
/ 10) + AR_BASE_FREQ_5GHZ
;
1160 if (AR_NO_SPUR
== cur_bb_spur
)
1162 cur_bb_spur
= cur_bb_spur
- freq
;
1164 if (IS_CHAN_HT40(ichan
)) {
1165 if ((cur_bb_spur
> -AR_SPUR_FEEQ_BOUND_HT40
) &&
1166 (cur_bb_spur
< AR_SPUR_FEEQ_BOUND_HT40
)) {
1167 bb_spur
= cur_bb_spur
;
1170 } else if ((cur_bb_spur
> -AR_SPUR_FEEQ_BOUND_HT20
) &&
1171 (cur_bb_spur
< AR_SPUR_FEEQ_BOUND_HT20
)) {
1172 bb_spur
= cur_bb_spur
;
1177 if (AR_NO_SPUR
== bb_spur
) {
1180 * MRC CCK can interfere with beacon detection and cause deaf/mute.
1181 * Disable MRC CCK for now.
1183 OS_REG_CLR_BIT(ah
, AR_PHY_FORCE_CLKEN_CCK
, AR_PHY_FORCE_CLKEN_CCK_MRC_MUX
);
1185 /* Enable MRC CCK if no spur is found in this channel. */
1186 OS_REG_SET_BIT(ah
, AR_PHY_FORCE_CLKEN_CCK
, AR_PHY_FORCE_CLKEN_CCK_MRC_MUX
);
1191 * For Merlin, spur can break CCK MRC algorithm. Disable CCK MRC if spur
1192 * is found in this channel.
1194 OS_REG_CLR_BIT(ah
, AR_PHY_FORCE_CLKEN_CCK
, AR_PHY_FORCE_CLKEN_CCK_MRC_MUX
);
1197 bin
= bb_spur
* 320;
1199 tmp
= OS_REG_READ(ah
, AR_PHY_TIMING_CTRL4_CHAIN(0));
1201 newVal
= tmp
| (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI
|
1202 AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER
|
1203 AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK
|
1204 AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK
);
1205 OS_REG_WRITE(ah
, AR_PHY_TIMING_CTRL4_CHAIN(0), newVal
);
1207 newVal
= (AR_PHY_SPUR_REG_MASK_RATE_CNTL
|
1208 AR_PHY_SPUR_REG_ENABLE_MASK_PPM
|
1209 AR_PHY_SPUR_REG_MASK_RATE_SELECT
|
1210 AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI
|
1211 SM(SPUR_RSSI_THRESH
, AR_PHY_SPUR_REG_SPUR_RSSI_THRESH
));
1212 OS_REG_WRITE(ah
, AR_PHY_SPUR_REG
, newVal
);
1214 /* Pick control or extn channel to cancel the spur */
1215 if (IS_CHAN_HT40(ichan
)) {
1217 spur_subchannel_sd
= 1;
1218 bb_spur_off
= bb_spur
+ 10;
1220 spur_subchannel_sd
= 0;
1221 bb_spur_off
= bb_spur
- 10;
1224 spur_subchannel_sd
= 0;
1225 bb_spur_off
= bb_spur
;
1229 * spur_delta_phase = bb_spur/40 * 2**21 for static ht20,
1232 if (IS_CHAN_HT40(ichan
))
1233 spur_delta_phase
= ((bb_spur
* 262144) / 10) & AR_PHY_TIMING11_SPUR_DELTA_PHASE
;
1235 spur_delta_phase
= ((bb_spur
* 524288) / 10) & AR_PHY_TIMING11_SPUR_DELTA_PHASE
;
1238 * in 11A mode the denominator of spur_freq_sd should be 40 and
1239 * it should be 44 in 11G
1241 denominator
= IS_CHAN_2GHZ(ichan
) ? 44 : 40;
1242 spur_freq_sd
= ((bb_spur_off
* 2048) / denominator
) & 0x3ff;
1244 newVal
= (AR_PHY_TIMING11_USE_SPUR_IN_AGC
|
1245 SM(spur_freq_sd
, AR_PHY_TIMING11_SPUR_FREQ_SD
) |
1246 SM(spur_delta_phase
, AR_PHY_TIMING11_SPUR_DELTA_PHASE
));
1247 OS_REG_WRITE(ah
, AR_PHY_TIMING11
, newVal
);
1249 /* Choose to cancel between control and extension channels */
1250 newVal
= spur_subchannel_sd
<< AR_PHY_SFCORR_SPUR_SUBCHNL_SD_S
;
1251 OS_REG_WRITE(ah
, AR_PHY_SFCORR_EXT
, newVal
);
1254 * ============================================
1255 * Set Pilot and Channel Masks
1257 * pilot mask 1 [31:0] = +6..-26, no 0 bin
1258 * pilot mask 2 [19:0] = +26..+7
1260 * channel mask 1 [31:0] = +6..-26, no 0 bin
1261 * channel mask 2 [19:0] = +26..+7
1267 for (i
= 0; i
< 4; i
++) {
1271 for (bp
= 0; bp
< 30; bp
++) {
1272 if ((cur_bin
> lower
) && (cur_bin
< upper
)) {
1273 pilot_mask
= pilot_mask
| 0x1 << bp
;
1274 chan_mask
= chan_mask
| 0x1 << bp
;
1279 OS_REG_WRITE(ah
, pilot_mask_reg
[i
], pilot_mask
);
1280 OS_REG_WRITE(ah
, chan_mask_reg
[i
], chan_mask
);
1283 /* =================================================
1284 * viterbi mask 1 based on channel magnitude
1286 * - mask (-27 to 27) (reg 64,0x9900 to 67,0x990c)
1287 * [1 2 2 1] for -9.6 or [1 2 1] for +16
1288 * - enable_mask_ppm, all bins move with freq
1290 * - mask_select, 8 bits for rates (reg 67,0x990c)
1291 * - mask_rate_cntl, 8 bits for rates (reg 67,0x990c)
1292 * choose which mask to use mask or mask2
1296 * viterbi mask 2 2nd set for per data rate puncturing
1298 * - mask_select, 8 bits for rates (reg 67)
1299 * - mask (-27 to 27) (reg 98,0x9988 to 101,0x9994)
1300 * [1 2 2 1] for -9.6 or [1 2 1] for +16
1302 cur_vit_mask
= 6100;
1306 for (i
= 0; i
< 123; i
++) {
1307 if ((cur_vit_mask
> lower
) && (cur_vit_mask
< upper
)) {
1308 if ((abs(cur_vit_mask
- bin
)) < 75) {
1313 if (cur_vit_mask
< 0) {
1314 mask_m
[abs(cur_vit_mask
/ 100)] = mask_amt
;
1316 mask_p
[cur_vit_mask
/ 100] = mask_amt
;
1319 cur_vit_mask
-= 100;
1322 tmp_mask
= (mask_m
[46] << 30) | (mask_m
[47] << 28)
1323 | (mask_m
[48] << 26) | (mask_m
[49] << 24)
1324 | (mask_m
[50] << 22) | (mask_m
[51] << 20)
1325 | (mask_m
[52] << 18) | (mask_m
[53] << 16)
1326 | (mask_m
[54] << 14) | (mask_m
[55] << 12)
1327 | (mask_m
[56] << 10) | (mask_m
[57] << 8)
1328 | (mask_m
[58] << 6) | (mask_m
[59] << 4)
1329 | (mask_m
[60] << 2) | (mask_m
[61] << 0);
1330 OS_REG_WRITE(ah
, AR_PHY_BIN_MASK_1
, tmp_mask
);
1331 OS_REG_WRITE(ah
, AR_PHY_VIT_MASK2_M_46_61
, tmp_mask
);
1333 tmp_mask
= (mask_m
[31] << 28)
1334 | (mask_m
[32] << 26) | (mask_m
[33] << 24)
1335 | (mask_m
[34] << 22) | (mask_m
[35] << 20)
1336 | (mask_m
[36] << 18) | (mask_m
[37] << 16)
1337 | (mask_m
[48] << 14) | (mask_m
[39] << 12)
1338 | (mask_m
[40] << 10) | (mask_m
[41] << 8)
1339 | (mask_m
[42] << 6) | (mask_m
[43] << 4)
1340 | (mask_m
[44] << 2) | (mask_m
[45] << 0);
1341 OS_REG_WRITE(ah
, AR_PHY_BIN_MASK_2
, tmp_mask
);
1342 OS_REG_WRITE(ah
, AR_PHY_MASK2_M_31_45
, tmp_mask
);
1344 tmp_mask
= (mask_m
[16] << 30) | (mask_m
[16] << 28)
1345 | (mask_m
[18] << 26) | (mask_m
[18] << 24)
1346 | (mask_m
[20] << 22) | (mask_m
[20] << 20)
1347 | (mask_m
[22] << 18) | (mask_m
[22] << 16)
1348 | (mask_m
[24] << 14) | (mask_m
[24] << 12)
1349 | (mask_m
[25] << 10) | (mask_m
[26] << 8)
1350 | (mask_m
[27] << 6) | (mask_m
[28] << 4)
1351 | (mask_m
[29] << 2) | (mask_m
[30] << 0);
1352 OS_REG_WRITE(ah
, AR_PHY_BIN_MASK_3
, tmp_mask
);
1353 OS_REG_WRITE(ah
, AR_PHY_MASK2_M_16_30
, tmp_mask
);
1355 tmp_mask
= (mask_m
[ 0] << 30) | (mask_m
[ 1] << 28)
1356 | (mask_m
[ 2] << 26) | (mask_m
[ 3] << 24)
1357 | (mask_m
[ 4] << 22) | (mask_m
[ 5] << 20)
1358 | (mask_m
[ 6] << 18) | (mask_m
[ 7] << 16)
1359 | (mask_m
[ 8] << 14) | (mask_m
[ 9] << 12)
1360 | (mask_m
[10] << 10) | (mask_m
[11] << 8)
1361 | (mask_m
[12] << 6) | (mask_m
[13] << 4)
1362 | (mask_m
[14] << 2) | (mask_m
[15] << 0);
1363 OS_REG_WRITE(ah
, AR_PHY_MASK_CTL
, tmp_mask
);
1364 OS_REG_WRITE(ah
, AR_PHY_MASK2_M_00_15
, tmp_mask
);
1366 tmp_mask
= (mask_p
[15] << 28)
1367 | (mask_p
[14] << 26) | (mask_p
[13] << 24)
1368 | (mask_p
[12] << 22) | (mask_p
[11] << 20)
1369 | (mask_p
[10] << 18) | (mask_p
[ 9] << 16)
1370 | (mask_p
[ 8] << 14) | (mask_p
[ 7] << 12)
1371 | (mask_p
[ 6] << 10) | (mask_p
[ 5] << 8)
1372 | (mask_p
[ 4] << 6) | (mask_p
[ 3] << 4)
1373 | (mask_p
[ 2] << 2) | (mask_p
[ 1] << 0);
1374 OS_REG_WRITE(ah
, AR_PHY_BIN_MASK2_1
, tmp_mask
);
1375 OS_REG_WRITE(ah
, AR_PHY_MASK2_P_15_01
, tmp_mask
);
1377 tmp_mask
= (mask_p
[30] << 28)
1378 | (mask_p
[29] << 26) | (mask_p
[28] << 24)
1379 | (mask_p
[27] << 22) | (mask_p
[26] << 20)
1380 | (mask_p
[25] << 18) | (mask_p
[24] << 16)
1381 | (mask_p
[23] << 14) | (mask_p
[22] << 12)
1382 | (mask_p
[21] << 10) | (mask_p
[20] << 8)
1383 | (mask_p
[19] << 6) | (mask_p
[18] << 4)
1384 | (mask_p
[17] << 2) | (mask_p
[16] << 0);
1385 OS_REG_WRITE(ah
, AR_PHY_BIN_MASK2_2
, tmp_mask
);
1386 OS_REG_WRITE(ah
, AR_PHY_MASK2_P_30_16
, tmp_mask
);
1388 tmp_mask
= (mask_p
[45] << 28)
1389 | (mask_p
[44] << 26) | (mask_p
[43] << 24)
1390 | (mask_p
[42] << 22) | (mask_p
[41] << 20)
1391 | (mask_p
[40] << 18) | (mask_p
[39] << 16)
1392 | (mask_p
[38] << 14) | (mask_p
[37] << 12)
1393 | (mask_p
[36] << 10) | (mask_p
[35] << 8)
1394 | (mask_p
[34] << 6) | (mask_p
[33] << 4)
1395 | (mask_p
[32] << 2) | (mask_p
[31] << 0);
1396 OS_REG_WRITE(ah
, AR_PHY_BIN_MASK2_3
, tmp_mask
);
1397 OS_REG_WRITE(ah
, AR_PHY_MASK2_P_45_31
, tmp_mask
);
1399 tmp_mask
= (mask_p
[61] << 30) | (mask_p
[60] << 28)
1400 | (mask_p
[59] << 26) | (mask_p
[58] << 24)
1401 | (mask_p
[57] << 22) | (mask_p
[56] << 20)
1402 | (mask_p
[55] << 18) | (mask_p
[54] << 16)
1403 | (mask_p
[53] << 14) | (mask_p
[52] << 12)
1404 | (mask_p
[51] << 10) | (mask_p
[50] << 8)
1405 | (mask_p
[49] << 6) | (mask_p
[48] << 4)
1406 | (mask_p
[47] << 2) | (mask_p
[46] << 0);
1407 OS_REG_WRITE(ah
, AR_PHY_BIN_MASK2_4
, tmp_mask
);
1408 OS_REG_WRITE(ah
, AR_PHY_MASK2_P_61_45
, tmp_mask
);
1410 #endif /* AH_SUPPORT_AR9280 */
1413 * Set a limit on the overall output power. Used for dynamic
1414 * transmit power control and the like.
1416 * NB: limit is in units of 0.5 dbM.
1419 ar5416SetTxPowerLimit(struct ath_hal
*ah
, uint32_t limit
)
1421 uint16_t dummyXpdGains
[2];
1423 AH_PRIVATE(ah
)->ah_powerLimit
= AH_MIN(limit
, MAX_RATE_POWER
);
1424 return ar5416SetTransmitPower(ah
, AH_PRIVATE(ah
)->ah_curchan
,
1429 ar5416GetChipPowerLimits(struct ath_hal
*ah
, HAL_CHANNEL
*chans
, uint32_t nchans
)
1431 struct ath_hal_5212
*ahp
= AH5212(ah
);
1432 int16_t minPower
, maxPower
;
1437 * Get Pier table max and min powers.
1439 for (i
= 0; i
< nchans
; i
++) {
1441 if (ahp
->ah_rfHal
->getChannelMaxMinPower(ah
, chan
, &maxPower
, &minPower
)) {
1442 /* NB: rf code returns 1/4 dBm units, convert */
1443 chan
->maxTxPower
= maxPower
/ 2;
1444 chan
->minTxPower
= minPower
/ 2;
1446 HALDEBUG(ah
, HAL_DEBUG_ANY
,
1447 "%s: no min/max power for %u/0x%x\n",
1448 __func__
, chan
->channel
, chan
->channelFlags
);
1449 chan
->maxTxPower
= AR5416_MAX_RATE_POWER
;
1450 chan
->minTxPower
= 0;
1454 for (i
=0; i
<nchans
; i
++) {
1455 HALDEBUG(ah
, HAL_DEBUG_RESET
,
1456 "Chan %d: MaxPow = %d MinPow = %d\n",
1457 chans
[i
].channel
,chans
[i
].maxTxPower
, chans
[i
].minTxPower
);
1463 /* XXX gag, this is sick */
1464 typedef enum Ar5416_Rates
{
1465 rate6mb
, rate9mb
, rate12mb
, rate18mb
,
1466 rate24mb
, rate36mb
, rate48mb
, rate54mb
,
1467 rate1l
, rate2l
, rate2s
, rate5_5l
,
1468 rate5_5s
, rate11l
, rate11s
, rateXr
,
1469 rateHt20_0
, rateHt20_1
, rateHt20_2
, rateHt20_3
,
1470 rateHt20_4
, rateHt20_5
, rateHt20_6
, rateHt20_7
,
1471 rateHt40_0
, rateHt40_1
, rateHt40_2
, rateHt40_3
,
1472 rateHt40_4
, rateHt40_5
, rateHt40_6
, rateHt40_7
,
1473 rateDupCck
, rateDupOfdm
, rateExtCck
, rateExtOfdm
,
1477 /**************************************************************
1478 * ar5416SetTransmitPower
1480 * Set the transmit power in the baseband for the given
1481 * operating channel and mode.
1484 ar5416SetTransmitPower(struct ath_hal
*ah
, HAL_CHANNEL_INTERNAL
*chan
, uint16_t *rfXpdGain
)
1486 #define POW_SM(_r, _s) (((_r) & 0x3f) << (_s))
1487 #define N(a) (sizeof (a) / sizeof (a[0]))
1489 MODAL_EEP_HEADER
*pModal
;
1490 struct ath_hal_5212
*ahp
= AH5212(ah
);
1491 int16_t ratesArray
[Ar5416RateSize
];
1492 int16_t txPowerIndexOffset
= 0;
1493 uint8_t ht40PowerIncForPdadc
= 2;
1497 uint16_t powerLimit
;
1498 uint16_t twiceAntennaReduction
;
1499 uint16_t twiceMaxRegulatoryPower
;
1501 HAL_EEPROM_v14
*ee
= AH_PRIVATE(ah
)->ah_eeprom
;
1502 struct ar5416eeprom
*pEepData
= &ee
->ee_base
;
1504 HALASSERT(AH_PRIVATE(ah
)->ah_eeversion
>= AR_EEPROM_VER14_1
);
1506 /* Setup info for the actual eeprom */
1507 ath_hal_memzero(ratesArray
, sizeof(ratesArray
));
1508 cfgCtl
= ath_hal_getctl(ah
, (HAL_CHANNEL
*)chan
);
1509 powerLimit
= chan
->maxRegTxPower
* 2;
1510 twiceAntennaReduction
= chan
->antennaMax
;
1511 twiceMaxRegulatoryPower
= AH_MIN(MAX_RATE_POWER
, AH_PRIVATE(ah
)->ah_powerLimit
);
1512 pModal
= &pEepData
->modalHeader
[IS_CHAN_2GHZ(chan
)];
1513 HALDEBUG(ah
, HAL_DEBUG_RESET
, "%s Channel=%u CfgCtl=%u\n",
1514 __func__
,chan
->channel
, cfgCtl
);
1516 if (IS_EEP_MINOR_V2(ah
)) {
1517 ht40PowerIncForPdadc
= pModal
->ht40PowerIncForPdadc
;
1520 if (!ar5416SetPowerPerRateTable(ah
, pEepData
, chan
,
1521 &ratesArray
[0],cfgCtl
,
1522 twiceAntennaReduction
,
1523 twiceMaxRegulatoryPower
, powerLimit
)) {
1524 HALDEBUG(ah
, HAL_DEBUG_ANY
,
1525 "%s: unable to set tx power per rate table\n", __func__
);
1529 if (!ar5416SetPowerCalTable(ah
, pEepData
, chan
, &txPowerIndexOffset
)) {
1530 HALDEBUG(ah
, HAL_DEBUG_ANY
, "%s: unable to set power table\n",
1535 maxPower
= AH_MAX(ratesArray
[rate6mb
], ratesArray
[rateHt20_0
]);
1537 if (IS_CHAN_2GHZ(chan
)) {
1538 maxPower
= AH_MAX(maxPower
, ratesArray
[rate1l
]);
1541 if (IS_CHAN_HT40(chan
)) {
1542 maxPower
= AH_MAX(maxPower
, ratesArray
[rateHt40_0
]);
1545 ahp
->ah_tx6PowerInHalfDbm
= maxPower
;
1546 AH_PRIVATE(ah
)->ah_maxPowerLevel
= maxPower
;
1547 ahp
->ah_txPowerIndexOffset
= txPowerIndexOffset
;
1550 * txPowerIndexOffset is set by the SetPowerTable() call -
1551 * adjust the rate table (0 offset if rates EEPROM not loaded)
1553 for (i
= 0; i
< N(ratesArray
); i
++) {
1554 ratesArray
[i
] = (int16_t)(txPowerIndexOffset
+ ratesArray
[i
]);
1555 if (ratesArray
[i
] > AR5416_MAX_RATE_POWER
)
1556 ratesArray
[i
] = AR5416_MAX_RATE_POWER
;
1559 #ifdef AH_EEPROM_DUMP
1560 ar5416PrintPowerPerRate(ah
, ratesArray
);
1563 /* Write the OFDM power per rate set */
1564 OS_REG_WRITE(ah
, AR_PHY_POWER_TX_RATE1
,
1565 POW_SM(ratesArray
[rate18mb
], 24)
1566 | POW_SM(ratesArray
[rate12mb
], 16)
1567 | POW_SM(ratesArray
[rate9mb
], 8)
1568 | POW_SM(ratesArray
[rate6mb
], 0)
1570 OS_REG_WRITE(ah
, AR_PHY_POWER_TX_RATE2
,
1571 POW_SM(ratesArray
[rate54mb
], 24)
1572 | POW_SM(ratesArray
[rate48mb
], 16)
1573 | POW_SM(ratesArray
[rate36mb
], 8)
1574 | POW_SM(ratesArray
[rate24mb
], 0)
1577 if (IS_CHAN_2GHZ(chan
)) {
1578 /* Write the CCK power per rate set */
1579 OS_REG_WRITE(ah
, AR_PHY_POWER_TX_RATE3
,
1580 POW_SM(ratesArray
[rate2s
], 24)
1581 | POW_SM(ratesArray
[rate2l
], 16)
1582 | POW_SM(ratesArray
[rateXr
], 8) /* XR target power */
1583 | POW_SM(ratesArray
[rate1l
], 0)
1585 OS_REG_WRITE(ah
, AR_PHY_POWER_TX_RATE4
,
1586 POW_SM(ratesArray
[rate11s
], 24)
1587 | POW_SM(ratesArray
[rate11l
], 16)
1588 | POW_SM(ratesArray
[rate5_5s
], 8)
1589 | POW_SM(ratesArray
[rate5_5l
], 0)
1591 HALDEBUG(ah
, HAL_DEBUG_RESET
,
1592 "%s AR_PHY_POWER_TX_RATE3=0x%x AR_PHY_POWER_TX_RATE4=0x%x\n",
1593 __func__
, OS_REG_READ(ah
,AR_PHY_POWER_TX_RATE3
),
1594 OS_REG_READ(ah
,AR_PHY_POWER_TX_RATE4
));
1597 /* Write the HT20 power per rate set */
1598 OS_REG_WRITE(ah
, AR_PHY_POWER_TX_RATE5
,
1599 POW_SM(ratesArray
[rateHt20_3
], 24)
1600 | POW_SM(ratesArray
[rateHt20_2
], 16)
1601 | POW_SM(ratesArray
[rateHt20_1
], 8)
1602 | POW_SM(ratesArray
[rateHt20_0
], 0)
1604 OS_REG_WRITE(ah
, AR_PHY_POWER_TX_RATE6
,
1605 POW_SM(ratesArray
[rateHt20_7
], 24)
1606 | POW_SM(ratesArray
[rateHt20_6
], 16)
1607 | POW_SM(ratesArray
[rateHt20_5
], 8)
1608 | POW_SM(ratesArray
[rateHt20_4
], 0)
1611 if (IS_CHAN_HT40(chan
)) {
1612 /* Write the HT40 power per rate set */
1613 /* Correct PAR difference between HT40 and HT20/LEGACY */
1614 OS_REG_WRITE(ah
, AR_PHY_POWER_TX_RATE7
,
1615 POW_SM(ratesArray
[rateHt40_3
] + ht40PowerIncForPdadc
, 24)
1616 | POW_SM(ratesArray
[rateHt40_2
] + ht40PowerIncForPdadc
, 16)
1617 | POW_SM(ratesArray
[rateHt40_1
] + ht40PowerIncForPdadc
, 8)
1618 | POW_SM(ratesArray
[rateHt40_0
] + ht40PowerIncForPdadc
, 0)
1620 OS_REG_WRITE(ah
, AR_PHY_POWER_TX_RATE8
,
1621 POW_SM(ratesArray
[rateHt40_7
] + ht40PowerIncForPdadc
, 24)
1622 | POW_SM(ratesArray
[rateHt40_6
] + ht40PowerIncForPdadc
, 16)
1623 | POW_SM(ratesArray
[rateHt40_5
] + ht40PowerIncForPdadc
, 8)
1624 | POW_SM(ratesArray
[rateHt40_4
] + ht40PowerIncForPdadc
, 0)
1626 /* Write the Dup/Ext 40 power per rate set */
1627 OS_REG_WRITE(ah
, AR_PHY_POWER_TX_RATE9
,
1628 POW_SM(ratesArray
[rateExtOfdm
], 24)
1629 | POW_SM(ratesArray
[rateExtCck
], 16)
1630 | POW_SM(ratesArray
[rateDupOfdm
], 8)
1631 | POW_SM(ratesArray
[rateDupCck
], 0)
1635 /* Write the Power subtraction for dynamic chain changing, for per-packet powertx */
1636 OS_REG_WRITE(ah
, AR_PHY_POWER_TX_SUB
,
1637 POW_SM(pModal
->pwrDecreaseFor3Chain
, 6)
1638 | POW_SM(pModal
->pwrDecreaseFor2Chain
, 0)
1646 * Exported call to check for a recent gain reading and return
1647 * the current state of the thermal calibration gain engine.
1650 ar5416GetRfgain(struct ath_hal
*ah
)
1652 return HAL_RFGAIN_INACTIVE
;
1656 * Places all of hardware into reset
1659 ar5416Disable(struct ath_hal
*ah
)
1661 if (!ar5212SetPowerMode(ah
, HAL_PM_AWAKE
, AH_TRUE
))
1663 return ar5416SetResetReg(ah
, HAL_RESET_COLD
);
1667 * Places the PHY and Radio chips into reset. A full reset
1668 * must be called to leave this state. The PCI/MAC/PCU are
1669 * not placed into reset as we must receive interrupt to
1670 * re-enable the hardware.
1673 ar5416PhyDisable(struct ath_hal
*ah
)
1675 return ar5416SetResetReg(ah
, HAL_RESET_WARM
);
1679 * Write the given reset bit mask into the reset register
1682 ar5416SetResetReg(struct ath_hal
*ah
, uint32_t type
)
1687 OS_REG_WRITE(ah
, AR_RTC_FORCE_WAKE
,
1688 AR_RTC_FORCE_WAKE_EN
| AR_RTC_FORCE_WAKE_ON_INT
);
1691 case HAL_RESET_POWER_ON
:
1692 return ar5416SetResetPowerOn(ah
);
1694 case HAL_RESET_WARM
:
1695 case HAL_RESET_COLD
:
1696 return ar5416SetReset(ah
, type
);
1704 ar5416SetResetPowerOn(struct ath_hal
*ah
)
1706 /* Power On Reset (Hard Reset) */
1711 * If the MAC was running, previously calling
1712 * reset will wake up the MAC but it may go back to sleep
1713 * before we can start polling.
1714 * Set force wake stops that
1715 * This must be called before initiating a hard reset.
1717 OS_REG_WRITE(ah
, AR_RTC_FORCE_WAKE
,
1718 AR_RTC_FORCE_WAKE_EN
| AR_RTC_FORCE_WAKE_ON_INT
);
1721 * RTC reset and clear
1723 OS_REG_WRITE(ah
, AR_RTC_RESET
, 0);
1725 OS_REG_WRITE(ah
, AR_RTC_RESET
, 1);
1728 * Poll till RTC is ON
1730 if (!ath_hal_wait(ah
, AR_RTC_STATUS
, AR_RTC_PM_STATUS_M
, AR_RTC_STATUS_ON
)) {
1731 HALDEBUG(ah
, HAL_DEBUG_ANY
, "%s: RTC not waking up\n", __func__
);
1735 return ar5416SetReset(ah
, HAL_RESET_COLD
);
1739 ar5416SetReset(struct ath_hal
*ah
, int type
)
1746 OS_REG_WRITE(ah
, AR_RTC_FORCE_WAKE
,
1747 AR_RTC_FORCE_WAKE_EN
| AR_RTC_FORCE_WAKE_ON_INT
);
1752 tmpReg
= OS_REG_READ(ah
, AR_INTR_SYNC_CAUSE
);
1753 if (tmpReg
& (AR_INTR_SYNC_LOCAL_TIMEOUT
|AR_INTR_SYNC_RADM_CPL_TIMEOUT
)) {
1754 OS_REG_WRITE(ah
, AR_INTR_SYNC_ENABLE
, 0);
1755 OS_REG_WRITE(ah
, AR_RC
, AR_RC_AHB
|AR_RC_HOSTIF
);
1757 OS_REG_WRITE(ah
, AR_RC
, AR_RC_AHB
);
1761 * Set Mac(BB,Phy) Warm Reset
1764 case HAL_RESET_WARM
:
1765 OS_REG_WRITE(ah
, AR_RTC_RC
, AR_RTC_RC_MAC_WARM
);
1767 case HAL_RESET_COLD
:
1768 OS_REG_WRITE(ah
, AR_RTC_RC
, AR_RTC_RC_MAC_WARM
|AR_RTC_RC_MAC_COLD
);
1776 * Clear resets and force wakeup
1778 OS_REG_WRITE(ah
, AR_RTC_RC
, 0);
1779 if (!ath_hal_wait(ah
, AR_RTC_RC
, AR_RTC_RC_M
, 0)) {
1780 HALDEBUG(ah
, HAL_DEBUG_ANY
, "%s: RTC stuck in MAC reset\n", __func__
);
1784 /* Clear AHB reset */
1785 OS_REG_WRITE(ah
, AR_RC
, 0);
1787 /* Set register and descriptor swapping on
1788 * Bigendian platforms on cold reset
1790 #ifdef __BIG_ENDIAN__
1791 if (type
== HAL_RESET_COLD
) {
1794 HALDEBUG(ah
, HAL_DEBUG_RESET
,
1795 "%s Applying descriptor swap\n", __func__
);
1797 mask
= INIT_CONFIG_STATUS
| AR_CFG_SWRD
| AR_CFG_SWRG
;
1798 #ifndef AH_NEED_DESC_SWAP
1799 mask
|= AR_CFG_SWTD
;
1801 OS_REG_WRITE(ah
, AR_CFG
, LE_READ_4(&mask
));
1805 ar5416InitPLL(ah
, AH_NULL
);
1810 #ifndef IS_5GHZ_FAST_CLOCK_EN
1811 #define IS_5GHZ_FAST_CLOCK_EN(ah, chan) AH_FALSE
1815 ar5416InitPLL(struct ath_hal
*ah
, HAL_CHANNEL
*chan
)
1819 if (AR_SREV_MERLIN_10_OR_LATER(ah
)) {
1820 pll
= SM(0x5, AR_RTC_SOWL_PLL_REFDIV
);
1822 if (chan
!= AH_NULL
&& IS_CHAN_HALF_RATE(chan
)) {
1823 pll
|= SM(0x1, AR_RTC_SOWL_PLL_CLKSEL
);
1824 } else if (chan
&& IS_CHAN_QUARTER_RATE(chan
)) {
1825 pll
|= SM(0x2, AR_RTC_SOWL_PLL_CLKSEL
);
1827 if (chan
!= AH_NULL
&& IS_CHAN_5GHZ(chan
)) {
1828 pll
|= SM(0x28, AR_RTC_SOWL_PLL_DIV
);
1831 * PLL WAR for Merlin 2.0/2.1
1832 * When doing fast clock, set PLL to 0x142c
1833 * Else, set PLL to 0x2850 to prevent reset-to-reset variation
1835 if (AR_SREV_MERLIN_20(ah
)) {
1836 if (IS_5GHZ_FAST_CLOCK_EN(ah
, chan
)) {
1843 pll
|= SM(0x2c, AR_RTC_SOWL_PLL_DIV
);
1845 } else if (AR_SREV_SOWL_10_OR_LATER(ah
)) {
1846 pll
= SM(0x5, AR_RTC_SOWL_PLL_REFDIV
);
1848 if (chan
!= AH_NULL
&& IS_CHAN_HALF_RATE(chan
)) {
1849 pll
|= SM(0x1, AR_RTC_SOWL_PLL_CLKSEL
);
1850 } else if (chan
&& IS_CHAN_QUARTER_RATE(chan
)) {
1851 pll
|= SM(0x2, AR_RTC_SOWL_PLL_CLKSEL
);
1853 if (chan
!= AH_NULL
&& IS_CHAN_5GHZ(chan
)) {
1854 pll
|= SM(0x50, AR_RTC_SOWL_PLL_DIV
);
1856 pll
|= SM(0x58, AR_RTC_SOWL_PLL_DIV
);
1859 pll
= AR_RTC_PLL_REFDIV_5
| AR_RTC_PLL_DIV2
;
1861 if (chan
!= AH_NULL
&& IS_CHAN_HALF_RATE(chan
)) {
1862 pll
|= SM(0x1, AR_RTC_PLL_CLKSEL
);
1863 } else if (chan
!= AH_NULL
&& IS_CHAN_QUARTER_RATE(chan
)) {
1864 pll
|= SM(0x2, AR_RTC_PLL_CLKSEL
);
1866 if (chan
!= AH_NULL
&& IS_CHAN_5GHZ(chan
)) {
1867 pll
|= SM(0xa, AR_RTC_PLL_DIV
);
1869 pll
|= SM(0xb, AR_RTC_PLL_DIV
);
1872 OS_REG_WRITE(ah
, AR_RTC_PLL_CONTROL
, pll
);
1875 * For multi-band owl, switch between bands by reiniting the PLL.
1878 OS_DELAY(RTC_PLL_SETTLE_DELAY
);
1880 OS_REG_WRITE(ah
, AR_RTC_SLEEP_CLK
, AR_RTC_SLEEP_DERIVED_CLK
);
1884 * Read EEPROM header info and program the device for correct operation
1885 * given the channel value.
1888 ar5416SetBoardValues(struct ath_hal
*ah
, HAL_CHANNEL_INTERNAL
*chan
)
1890 const HAL_EEPROM_v14
*ee
= AH_PRIVATE(ah
)->ah_eeprom
;
1891 const struct ar5416eeprom
*eep
= &ee
->ee_base
;
1892 const MODAL_EEP_HEADER
*pModal
;
1893 int i
, regChainOffset
;
1894 uint8_t txRxAttenLocal
; /* workaround for eeprom versions <= 14.2 */
1896 HALASSERT(AH_PRIVATE(ah
)->ah_eeversion
>= AR_EEPROM_VER14_1
);
1897 pModal
= &(eep
->modalHeader
[IS_CHAN_2GHZ(chan
)]);
1899 txRxAttenLocal
= IS_CHAN_2GHZ(chan
) ? 23 : 44; /* workaround for eeprom versions <= 14.2 */
1901 OS_REG_WRITE(ah
, AR_PHY_SWITCH_COM
, pModal
->antCtrlCommon
);
1902 for (i
= 0; i
< AR5416_MAX_CHAINS
; i
++) {
1903 if (AR_SREV_MERLIN(ah
)) {
1906 if (AR_SREV_OWL_20_OR_LATER(ah
) &&
1907 (AH5416(ah
)->ah_rx_chainmask
== 0x5 ||
1908 AH5416(ah
)->ah_tx_chainmask
== 0x5) && i
!= 0) {
1909 /* Regs are swapped from chain 2 to 1 for 5416 2_0 with
1910 * only chains 0 and 2 populated
1912 regChainOffset
= (i
== 1) ? 0x2000 : 0x1000;
1914 regChainOffset
= i
* 0x1000;
1917 OS_REG_WRITE(ah
, AR_PHY_SWITCH_CHAIN_0
+ regChainOffset
, pModal
->antCtrlChain
[i
]);
1918 OS_REG_WRITE(ah
, AR_PHY_TIMING_CTRL4
+ regChainOffset
,
1919 (OS_REG_READ(ah
, AR_PHY_TIMING_CTRL4
+ regChainOffset
) &
1920 ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF
| AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF
)) |
1921 SM(pModal
->iqCalICh
[i
], AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF
) |
1922 SM(pModal
->iqCalQCh
[i
], AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF
));
1925 * Large signal upgrade.
1929 if ((i
== 0) || AR_SREV_OWL_20_OR_LATER(ah
)) {
1930 OS_REG_WRITE(ah
, AR_PHY_RXGAIN
+ regChainOffset
,
1931 (OS_REG_READ(ah
, AR_PHY_RXGAIN
+ regChainOffset
) & ~AR_PHY_RXGAIN_TXRX_ATTEN
) |
1932 SM(IS_EEP_MINOR_V3(ah
) ? pModal
->txRxAttenCh
[i
] : txRxAttenLocal
,
1933 AR_PHY_RXGAIN_TXRX_ATTEN
));
1935 OS_REG_WRITE(ah
, AR_PHY_GAIN_2GHZ
+ regChainOffset
,
1936 (OS_REG_READ(ah
, AR_PHY_GAIN_2GHZ
+ regChainOffset
) & ~AR_PHY_GAIN_2GHZ_RXTX_MARGIN
) |
1937 SM(pModal
->rxTxMarginCh
[i
], AR_PHY_GAIN_2GHZ_RXTX_MARGIN
));
1941 OS_REG_RMW_FIELD(ah
, AR_PHY_SETTLING
, AR_PHY_SETTLING_SWITCH
, pModal
->switchSettling
);
1942 OS_REG_RMW_FIELD(ah
, AR_PHY_DESIRED_SZ
, AR_PHY_DESIRED_SZ_ADC
, pModal
->adcDesiredSize
);
1943 OS_REG_RMW_FIELD(ah
, AR_PHY_DESIRED_SZ
, AR_PHY_DESIRED_SZ_PGA
, pModal
->pgaDesiredSize
);
1944 OS_REG_WRITE(ah
, AR_PHY_RF_CTL4
,
1945 SM(pModal
->txEndToXpaOff
, AR_PHY_RF_CTL4_TX_END_XPAA_OFF
)
1946 | SM(pModal
->txEndToXpaOff
, AR_PHY_RF_CTL4_TX_END_XPAB_OFF
)
1947 | SM(pModal
->txFrameToXpaOn
, AR_PHY_RF_CTL4_FRAME_XPAA_ON
)
1948 | SM(pModal
->txFrameToXpaOn
, AR_PHY_RF_CTL4_FRAME_XPAB_ON
));
1950 OS_REG_RMW_FIELD(ah
, AR_PHY_RF_CTL3
, AR_PHY_TX_END_TO_A2_RX_ON
, pModal
->txEndToRxOn
);
1952 if (AR_SREV_MERLIN_10_OR_LATER(ah
)) {
1953 OS_REG_RMW_FIELD(ah
, AR_PHY_CCA
, AR9280_PHY_CCA_THRESH62
,
1955 OS_REG_RMW_FIELD(ah
, AR_PHY_EXT_CCA0
, AR_PHY_EXT_CCA0_THRESH62
,
1958 OS_REG_RMW_FIELD(ah
, AR_PHY_CCA
, AR_PHY_CCA_THRESH62
,
1960 OS_REG_RMW_FIELD(ah
, AR_PHY_EXT_CCA0
, AR_PHY_EXT_CCA_THRESH62
,
1964 /* Minor Version Specific application */
1965 if (IS_EEP_MINOR_V2(ah
)) {
1966 OS_REG_RMW_FIELD(ah
, AR_PHY_RF_CTL2
, AR_PHY_TX_FRAME_TO_DATA_START
, pModal
->txFrameToDataStart
);
1967 OS_REG_RMW_FIELD(ah
, AR_PHY_RF_CTL2
, AR_PHY_TX_FRAME_TO_PA_ON
, pModal
->txFrameToPaOn
);
1970 if (IS_EEP_MINOR_V3(ah
)) {
1971 if (IS_CHAN_HT40(chan
)) {
1972 /* Overwrite switch settling with HT40 value */
1973 OS_REG_RMW_FIELD(ah
, AR_PHY_SETTLING
, AR_PHY_SETTLING_SWITCH
, pModal
->swSettleHt40
);
1976 if ((AR_SREV_OWL_20_OR_LATER(ah
)) &&
1977 ( AH5416(ah
)->ah_rx_chainmask
== 0x5 || AH5416(ah
)->ah_tx_chainmask
== 0x5)){
1978 /* Reg Offsets are swapped for logical mapping */
1979 OS_REG_WRITE(ah
, AR_PHY_GAIN_2GHZ
+ 0x1000, (OS_REG_READ(ah
, AR_PHY_GAIN_2GHZ
+ 0x1000) & ~AR_PHY_GAIN_2GHZ_BSW_MARGIN
) |
1980 SM(pModal
->bswMargin
[2], AR_PHY_GAIN_2GHZ_BSW_MARGIN
));
1981 OS_REG_WRITE(ah
, AR_PHY_GAIN_2GHZ
+ 0x1000, (OS_REG_READ(ah
, AR_PHY_GAIN_2GHZ
+ 0x1000) & ~AR_PHY_GAIN_2GHZ_BSW_ATTEN
) |
1982 SM(pModal
->bswAtten
[2], AR_PHY_GAIN_2GHZ_BSW_ATTEN
));
1983 OS_REG_WRITE(ah
, AR_PHY_GAIN_2GHZ
+ 0x2000, (OS_REG_READ(ah
, AR_PHY_GAIN_2GHZ
+ 0x2000) & ~AR_PHY_GAIN_2GHZ_BSW_MARGIN
) |
1984 SM(pModal
->bswMargin
[1], AR_PHY_GAIN_2GHZ_BSW_MARGIN
));
1985 OS_REG_WRITE(ah
, AR_PHY_GAIN_2GHZ
+ 0x2000, (OS_REG_READ(ah
, AR_PHY_GAIN_2GHZ
+ 0x2000) & ~AR_PHY_GAIN_2GHZ_BSW_ATTEN
) |
1986 SM(pModal
->bswAtten
[1], AR_PHY_GAIN_2GHZ_BSW_ATTEN
));
1988 OS_REG_WRITE(ah
, AR_PHY_GAIN_2GHZ
+ 0x1000, (OS_REG_READ(ah
, AR_PHY_GAIN_2GHZ
+ 0x1000) & ~AR_PHY_GAIN_2GHZ_BSW_MARGIN
) |
1989 SM(pModal
->bswMargin
[1], AR_PHY_GAIN_2GHZ_BSW_MARGIN
));
1990 OS_REG_WRITE(ah
, AR_PHY_GAIN_2GHZ
+ 0x1000, (OS_REG_READ(ah
, AR_PHY_GAIN_2GHZ
+ 0x1000) & ~AR_PHY_GAIN_2GHZ_BSW_ATTEN
) |
1991 SM(pModal
->bswAtten
[1], AR_PHY_GAIN_2GHZ_BSW_ATTEN
));
1992 OS_REG_WRITE(ah
, AR_PHY_GAIN_2GHZ
+ 0x2000, (OS_REG_READ(ah
, AR_PHY_GAIN_2GHZ
+ 0x2000) & ~AR_PHY_GAIN_2GHZ_BSW_MARGIN
) |
1993 SM(pModal
->bswMargin
[2],AR_PHY_GAIN_2GHZ_BSW_MARGIN
));
1994 OS_REG_WRITE(ah
, AR_PHY_GAIN_2GHZ
+ 0x2000, (OS_REG_READ(ah
, AR_PHY_GAIN_2GHZ
+ 0x2000) & ~AR_PHY_GAIN_2GHZ_BSW_ATTEN
) |
1995 SM(pModal
->bswAtten
[2], AR_PHY_GAIN_2GHZ_BSW_ATTEN
));
1997 OS_REG_RMW_FIELD(ah
, AR_PHY_GAIN_2GHZ
, AR_PHY_GAIN_2GHZ_BSW_MARGIN
, pModal
->bswMargin
[0]);
1998 OS_REG_RMW_FIELD(ah
, AR_PHY_GAIN_2GHZ
, AR_PHY_GAIN_2GHZ_BSW_ATTEN
, pModal
->bswAtten
[0]);
2004 * Helper functions common for AP/CB/XB
2008 * ar5416SetPowerPerRateTable
2010 * Sets the transmit power in the baseband for the given
2011 * operating channel and mode.
2014 ar5416SetPowerPerRateTable(struct ath_hal
*ah
, struct ar5416eeprom
*pEepData
,
2015 HAL_CHANNEL_INTERNAL
*chan
,
2016 int16_t *ratesArray
, uint16_t cfgCtl
,
2017 uint16_t AntennaReduction
,
2018 uint16_t twiceMaxRegulatoryPower
,
2019 uint16_t powerLimit
)
2021 #define N(a) (sizeof(a)/sizeof(a[0]))
2022 /* Local defines to distinguish between extension and control CTL's */
2023 #define EXT_ADDITIVE (0x8000)
2024 #define CTL_11A_EXT (CTL_11A | EXT_ADDITIVE)
2025 #define CTL_11G_EXT (CTL_11G | EXT_ADDITIVE)
2026 #define CTL_11B_EXT (CTL_11B | EXT_ADDITIVE)
2028 uint16_t twiceMaxEdgePower
= AR5416_MAX_RATE_POWER
;
2030 int16_t twiceLargestAntenna
;
2032 CAL_TARGET_POWER_LEG targetPowerOfdm
, targetPowerCck
= {0, {0, 0, 0, 0}};
2033 CAL_TARGET_POWER_LEG targetPowerOfdmExt
= {0, {0, 0, 0, 0}}, targetPowerCckExt
= {0, {0, 0, 0, 0}};
2034 CAL_TARGET_POWER_HT targetPowerHt20
, targetPowerHt40
= {0, {0, 0, 0, 0}};
2035 int16_t scaledPower
, minCtlPower
;
2037 #define SUB_NUM_CTL_MODES_AT_5G_40 2 /* excluding HT40, EXT-OFDM */
2038 #define SUB_NUM_CTL_MODES_AT_2G_40 3 /* excluding HT40, EXT-OFDM, EXT-CCK */
2039 static const uint16_t ctlModesFor11a
[] = {
2040 CTL_11A
, CTL_5GHT20
, CTL_11A_EXT
, CTL_5GHT40
2042 static const uint16_t ctlModesFor11g
[] = {
2043 CTL_11B
, CTL_11G
, CTL_2GHT20
, CTL_11B_EXT
, CTL_11G_EXT
, CTL_2GHT40
2045 const uint16_t *pCtlMode
;
2046 uint16_t numCtlModes
, ctlMode
, freq
;
2047 CHAN_CENTERS centers
;
2049 ar5416GetChannelCenters(ah
, chan
, ¢ers
);
2051 /* Compute TxPower reduction due to Antenna Gain */
2053 twiceLargestAntenna
= AH_MAX(AH_MAX(pEepData
->modalHeader
[IS_CHAN_2GHZ(chan
)].antennaGainCh
[0],
2054 pEepData
->modalHeader
[IS_CHAN_2GHZ(chan
)].antennaGainCh
[1]),
2055 pEepData
->modalHeader
[IS_CHAN_2GHZ(chan
)].antennaGainCh
[2]);
2057 /* Turn it back on if we need to calculate per chain antenna gain reduction */
2058 /* Use only if the expected gain > 6dbi */
2059 /* Chain 0 is always used */
2060 twiceLargestAntenna
= pEepData
->modalHeader
[IS_CHAN_2GHZ(chan
)].antennaGainCh
[0];
2062 /* Look at antenna gains of Chains 1 and 2 if the TX mask is set */
2063 if (ahp
->ah_tx_chainmask
& 0x2)
2064 twiceLargestAntenna
= AH_MAX(twiceLargestAntenna
,
2065 pEepData
->modalHeader
[IS_CHAN_2GHZ(chan
)].antennaGainCh
[1]);
2067 if (ahp
->ah_tx_chainmask
& 0x4)
2068 twiceLargestAntenna
= AH_MAX(twiceLargestAntenna
,
2069 pEepData
->modalHeader
[IS_CHAN_2GHZ(chan
)].antennaGainCh
[2]);
2071 twiceLargestAntenna
= (int16_t)AH_MIN((AntennaReduction
) - twiceLargestAntenna
, 0);
2073 /* XXX setup for 5212 use (really used?) */
2074 ath_hal_eepromSet(ah
,
2075 IS_CHAN_2GHZ(chan
) ? AR_EEP_ANTGAINMAX_2
: AR_EEP_ANTGAINMAX_5
,
2076 twiceLargestAntenna
);
2079 * scaledPower is the minimum of the user input power level and
2080 * the regulatory allowed power level
2082 scaledPower
= AH_MIN(powerLimit
, twiceMaxRegulatoryPower
+ twiceLargestAntenna
);
2084 /* Reduce scaled Power by number of chains active to get to per chain tx power level */
2085 /* TODO: better value than these? */
2086 switch (owl_get_ntxchains(AH5416(ah
)->ah_tx_chainmask
)) {
2090 scaledPower
-= pEepData
->modalHeader
[IS_CHAN_2GHZ(chan
)].pwrDecreaseFor2Chain
;
2093 scaledPower
-= pEepData
->modalHeader
[IS_CHAN_2GHZ(chan
)].pwrDecreaseFor3Chain
;
2096 return AH_FALSE
; /* Unsupported number of chains */
2099 scaledPower
= AH_MAX(0, scaledPower
);
2101 /* Get target powers from EEPROM - our baseline for TX Power */
2102 if (IS_CHAN_2GHZ(chan
)) {
2103 /* Setup for CTL modes */
2104 numCtlModes
= N(ctlModesFor11g
) - SUB_NUM_CTL_MODES_AT_2G_40
; /* CTL_11B, CTL_11G, CTL_2GHT20 */
2105 pCtlMode
= ctlModesFor11g
;
2107 ar5416GetTargetPowersLeg(ah
, chan
, pEepData
->calTargetPowerCck
,
2108 AR5416_NUM_2G_CCK_TARGET_POWERS
, &targetPowerCck
, 4, AH_FALSE
);
2109 ar5416GetTargetPowersLeg(ah
, chan
, pEepData
->calTargetPower2G
,
2110 AR5416_NUM_2G_20_TARGET_POWERS
, &targetPowerOfdm
, 4, AH_FALSE
);
2111 ar5416GetTargetPowers(ah
, chan
, pEepData
->calTargetPower2GHT20
,
2112 AR5416_NUM_2G_20_TARGET_POWERS
, &targetPowerHt20
, 8, AH_FALSE
);
2114 if (IS_CHAN_HT40(chan
)) {
2115 numCtlModes
= N(ctlModesFor11g
); /* All 2G CTL's */
2117 ar5416GetTargetPowers(ah
, chan
, pEepData
->calTargetPower2GHT40
,
2118 AR5416_NUM_2G_40_TARGET_POWERS
, &targetPowerHt40
, 8, AH_TRUE
);
2119 /* Get target powers for extension channels */
2120 ar5416GetTargetPowersLeg(ah
, chan
, pEepData
->calTargetPowerCck
,
2121 AR5416_NUM_2G_CCK_TARGET_POWERS
, &targetPowerCckExt
, 4, AH_TRUE
);
2122 ar5416GetTargetPowersLeg(ah
, chan
, pEepData
->calTargetPower2G
,
2123 AR5416_NUM_2G_20_TARGET_POWERS
, &targetPowerOfdmExt
, 4, AH_TRUE
);
2126 /* Setup for CTL modes */
2127 numCtlModes
= N(ctlModesFor11a
) - SUB_NUM_CTL_MODES_AT_5G_40
; /* CTL_11A, CTL_5GHT20 */
2128 pCtlMode
= ctlModesFor11a
;
2130 ar5416GetTargetPowersLeg(ah
, chan
, pEepData
->calTargetPower5G
,
2131 AR5416_NUM_5G_20_TARGET_POWERS
, &targetPowerOfdm
, 4, AH_FALSE
);
2132 ar5416GetTargetPowers(ah
, chan
, pEepData
->calTargetPower5GHT20
,
2133 AR5416_NUM_5G_20_TARGET_POWERS
, &targetPowerHt20
, 8, AH_FALSE
);
2135 if (IS_CHAN_HT40(chan
)) {
2136 numCtlModes
= N(ctlModesFor11a
); /* All 5G CTL's */
2138 ar5416GetTargetPowers(ah
, chan
, pEepData
->calTargetPower5GHT40
,
2139 AR5416_NUM_5G_40_TARGET_POWERS
, &targetPowerHt40
, 8, AH_TRUE
);
2140 ar5416GetTargetPowersLeg(ah
, chan
, pEepData
->calTargetPower5G
,
2141 AR5416_NUM_5G_20_TARGET_POWERS
, &targetPowerOfdmExt
, 4, AH_TRUE
);
2146 * For MIMO, need to apply regulatory caps individually across dynamically
2147 * running modes: CCK, OFDM, HT20, HT40
2149 * The outer loop walks through each possible applicable runtime mode.
2150 * The inner loop walks through each ctlIndex entry in EEPROM.
2151 * The ctl value is encoded as [7:4] == test group, [3:0] == test mode.
2154 for (ctlMode
= 0; ctlMode
< numCtlModes
; ctlMode
++) {
2156 HAL_BOOL isHt40CtlMode
= (pCtlMode
[ctlMode
] == CTL_5GHT40
) ||
2157 (pCtlMode
[ctlMode
] == CTL_2GHT40
);
2158 if (isHt40CtlMode
) {
2159 freq
= centers
.ctl_center
;
2160 } else if (pCtlMode
[ctlMode
] & EXT_ADDITIVE
) {
2161 freq
= centers
.ext_center
;
2163 freq
= centers
.ctl_center
;
2166 /* walk through each CTL index stored in EEPROM */
2167 for (i
= 0; (i
< AR5416_NUM_CTLS
) && pEepData
->ctlIndex
[i
]; i
++) {
2168 uint16_t twiceMinEdgePower
;
2170 /* compare test group from regulatory channel list with test mode from pCtlMode list */
2171 if ((((cfgCtl
& ~CTL_MODE_M
) | (pCtlMode
[ctlMode
] & CTL_MODE_M
)) == pEepData
->ctlIndex
[i
]) ||
2172 (((cfgCtl
& ~CTL_MODE_M
) | (pCtlMode
[ctlMode
] & CTL_MODE_M
)) ==
2173 ((pEepData
->ctlIndex
[i
] & CTL_MODE_M
) | SD_NO_CTL
))) {
2174 rep
= &(pEepData
->ctlData
[i
]);
2175 twiceMinEdgePower
= ar5416GetMaxEdgePower(freq
,
2176 rep
->ctlEdges
[owl_get_ntxchains(AH5416(ah
)->ah_tx_chainmask
) - 1],
2177 IS_CHAN_2GHZ(chan
));
2178 if ((cfgCtl
& ~CTL_MODE_M
) == SD_NO_CTL
) {
2179 /* Find the minimum of all CTL edge powers that apply to this channel */
2180 twiceMaxEdgePower
= AH_MIN(twiceMaxEdgePower
, twiceMinEdgePower
);
2183 twiceMaxEdgePower
= twiceMinEdgePower
;
2188 minCtlPower
= (uint8_t)AH_MIN(twiceMaxEdgePower
, scaledPower
);
2189 /* Apply ctl mode to correct target power set */
2190 switch(pCtlMode
[ctlMode
]) {
2192 for (i
= 0; i
< N(targetPowerCck
.tPow2x
); i
++) {
2193 targetPowerCck
.tPow2x
[i
] = (uint8_t)AH_MIN(targetPowerCck
.tPow2x
[i
], minCtlPower
);
2198 for (i
= 0; i
< N(targetPowerOfdm
.tPow2x
); i
++) {
2199 targetPowerOfdm
.tPow2x
[i
] = (uint8_t)AH_MIN(targetPowerOfdm
.tPow2x
[i
], minCtlPower
);
2204 for (i
= 0; i
< N(targetPowerHt20
.tPow2x
); i
++) {
2205 targetPowerHt20
.tPow2x
[i
] = (uint8_t)AH_MIN(targetPowerHt20
.tPow2x
[i
], minCtlPower
);
2209 targetPowerCckExt
.tPow2x
[0] = (uint8_t)AH_MIN(targetPowerCckExt
.tPow2x
[0], minCtlPower
);
2213 targetPowerOfdmExt
.tPow2x
[0] = (uint8_t)AH_MIN(targetPowerOfdmExt
.tPow2x
[0], minCtlPower
);
2217 for (i
= 0; i
< N(targetPowerHt40
.tPow2x
); i
++) {
2218 targetPowerHt40
.tPow2x
[i
] = (uint8_t)AH_MIN(targetPowerHt40
.tPow2x
[i
], minCtlPower
);
2225 } /* end ctl mode checking */
2227 /* Set rates Array from collected data */
2228 ratesArray
[rate6mb
] = ratesArray
[rate9mb
] = ratesArray
[rate12mb
] = ratesArray
[rate18mb
] = ratesArray
[rate24mb
] = targetPowerOfdm
.tPow2x
[0];
2229 ratesArray
[rate36mb
] = targetPowerOfdm
.tPow2x
[1];
2230 ratesArray
[rate48mb
] = targetPowerOfdm
.tPow2x
[2];
2231 ratesArray
[rate54mb
] = targetPowerOfdm
.tPow2x
[3];
2232 ratesArray
[rateXr
] = targetPowerOfdm
.tPow2x
[0];
2234 for (i
= 0; i
< N(targetPowerHt20
.tPow2x
); i
++) {
2235 ratesArray
[rateHt20_0
+ i
] = targetPowerHt20
.tPow2x
[i
];
2238 if (IS_CHAN_2GHZ(chan
)) {
2239 ratesArray
[rate1l
] = targetPowerCck
.tPow2x
[0];
2240 ratesArray
[rate2s
] = ratesArray
[rate2l
] = targetPowerCck
.tPow2x
[1];
2241 ratesArray
[rate5_5s
] = ratesArray
[rate5_5l
] = targetPowerCck
.tPow2x
[2];
2242 ratesArray
[rate11s
] = ratesArray
[rate11l
] = targetPowerCck
.tPow2x
[3];
2244 if (IS_CHAN_HT40(chan
)) {
2245 for (i
= 0; i
< N(targetPowerHt40
.tPow2x
); i
++) {
2246 ratesArray
[rateHt40_0
+ i
] = targetPowerHt40
.tPow2x
[i
];
2248 ratesArray
[rateDupOfdm
] = targetPowerHt40
.tPow2x
[0];
2249 ratesArray
[rateDupCck
] = targetPowerHt40
.tPow2x
[0];
2250 ratesArray
[rateExtOfdm
] = targetPowerOfdmExt
.tPow2x
[0];
2251 if (IS_CHAN_2GHZ(chan
)) {
2252 ratesArray
[rateExtCck
] = targetPowerCckExt
.tPow2x
[0];
2260 #undef SUB_NUM_CTL_MODES_AT_5G_40
2261 #undef SUB_NUM_CTL_MODES_AT_2G_40
2265 /**************************************************************************
2268 * Get channel value from binary representation held in eeprom
2269 * RETURNS: the frequency in MHz
2272 fbin2freq(uint8_t fbin
, HAL_BOOL is2GHz
)
2275 * Reserved value 0xFF provides an empty definition both as
2276 * an fbin and as a frequency - do not convert
2278 if (fbin
== AR5416_BCHAN_UNUSED
) {
2282 return (uint16_t)((is2GHz
) ? (2300 + fbin
) : (4800 + 5 * fbin
));
2286 * ar5416GetMaxEdgePower
2288 * Find the maximum conformance test limit for the given channel and CTL info
2291 ar5416GetMaxEdgePower(uint16_t freq
, CAL_CTL_EDGES
*pRdEdgesPower
, HAL_BOOL is2GHz
)
2293 uint16_t twiceMaxEdgePower
= AR5416_MAX_RATE_POWER
;
2296 /* Get the edge power */
2297 for (i
= 0; (i
< AR5416_NUM_BAND_EDGES
) && (pRdEdgesPower
[i
].bChannel
!= AR5416_BCHAN_UNUSED
) ; i
++) {
2299 * If there's an exact channel match or an inband flag set
2300 * on the lower channel use the given rdEdgePower
2302 if (freq
== fbin2freq(pRdEdgesPower
[i
].bChannel
, is2GHz
)) {
2303 twiceMaxEdgePower
= MS(pRdEdgesPower
[i
].tPowerFlag
, CAL_CTL_EDGES_POWER
);
2305 } else if ((i
> 0) && (freq
< fbin2freq(pRdEdgesPower
[i
].bChannel
, is2GHz
))) {
2306 if (fbin2freq(pRdEdgesPower
[i
- 1].bChannel
, is2GHz
) < freq
&& (pRdEdgesPower
[i
- 1].tPowerFlag
& CAL_CTL_EDGES_FLAG
) != 0) {
2307 twiceMaxEdgePower
= MS(pRdEdgesPower
[i
- 1].tPowerFlag
, CAL_CTL_EDGES_POWER
);
2309 /* Leave loop - no more affecting edges possible in this monotonic increasing list */
2313 HALASSERT(twiceMaxEdgePower
> 0);
2314 return twiceMaxEdgePower
;
2317 /**************************************************************
2318 * ar5416GetTargetPowers
2320 * Return the rates of target power for the given target power table
2321 * channel, and number of channels
2324 ar5416GetTargetPowers(struct ath_hal
*ah
, HAL_CHANNEL_INTERNAL
*chan
,
2325 CAL_TARGET_POWER_HT
*powInfo
, uint16_t numChannels
,
2326 CAL_TARGET_POWER_HT
*pNewPower
, uint16_t numRates
,
2327 HAL_BOOL isHt40Target
)
2331 int matchIndex
= -1, lowIndex
= -1;
2333 CHAN_CENTERS centers
;
2335 ar5416GetChannelCenters(ah
, chan
, ¢ers
);
2336 freq
= isHt40Target
? centers
.synth_center
: centers
.ctl_center
;
2338 /* Copy the target powers into the temp channel list */
2339 if (freq
<= fbin2freq(powInfo
[0].bChannel
, IS_CHAN_2GHZ(chan
))) {
2342 for (i
= 0; (i
< numChannels
) && (powInfo
[i
].bChannel
!= AR5416_BCHAN_UNUSED
); i
++) {
2343 if (freq
== fbin2freq(powInfo
[i
].bChannel
, IS_CHAN_2GHZ(chan
))) {
2346 } else if ((freq
< fbin2freq(powInfo
[i
].bChannel
, IS_CHAN_2GHZ(chan
))) &&
2347 (freq
> fbin2freq(powInfo
[i
- 1].bChannel
, IS_CHAN_2GHZ(chan
))))
2353 if ((matchIndex
== -1) && (lowIndex
== -1)) {
2354 HALASSERT(freq
> fbin2freq(powInfo
[i
- 1].bChannel
, IS_CHAN_2GHZ(chan
)));
2359 if (matchIndex
!= -1) {
2360 OS_MEMCPY(pNewPower
, &powInfo
[matchIndex
], sizeof(*pNewPower
));
2362 HALASSERT(lowIndex
!= -1);
2364 * Get the lower and upper channels, target powers,
2365 * and interpolate between them.
2367 clo
= fbin2freq(powInfo
[lowIndex
].bChannel
, IS_CHAN_2GHZ(chan
));
2368 chi
= fbin2freq(powInfo
[lowIndex
+ 1].bChannel
, IS_CHAN_2GHZ(chan
));
2370 for (i
= 0; i
< numRates
; i
++) {
2371 pNewPower
->tPow2x
[i
] = (uint8_t)interpolate(freq
, clo
, chi
,
2372 powInfo
[lowIndex
].tPow2x
[i
], powInfo
[lowIndex
+ 1].tPow2x
[i
]);
2376 /**************************************************************
2377 * ar5416GetTargetPowersLeg
2379 * Return the four rates of target power for the given target power table
2380 * channel, and number of channels
2383 ar5416GetTargetPowersLeg(struct ath_hal
*ah
,
2384 HAL_CHANNEL_INTERNAL
*chan
,
2385 CAL_TARGET_POWER_LEG
*powInfo
, uint16_t numChannels
,
2386 CAL_TARGET_POWER_LEG
*pNewPower
, uint16_t numRates
,
2387 HAL_BOOL isExtTarget
)
2391 int matchIndex
= -1, lowIndex
= -1;
2393 CHAN_CENTERS centers
;
2395 ar5416GetChannelCenters(ah
, chan
, ¢ers
);
2396 freq
= (isExtTarget
) ? centers
.ext_center
:centers
.ctl_center
;
2398 /* Copy the target powers into the temp channel list */
2399 if (freq
<= fbin2freq(powInfo
[0].bChannel
, IS_CHAN_2GHZ(chan
))) {
2402 for (i
= 0; (i
< numChannels
) && (powInfo
[i
].bChannel
!= AR5416_BCHAN_UNUSED
); i
++) {
2403 if (freq
== fbin2freq(powInfo
[i
].bChannel
, IS_CHAN_2GHZ(chan
))) {
2406 } else if ((freq
< fbin2freq(powInfo
[i
].bChannel
, IS_CHAN_2GHZ(chan
))) &&
2407 (freq
> fbin2freq(powInfo
[i
- 1].bChannel
, IS_CHAN_2GHZ(chan
))))
2413 if ((matchIndex
== -1) && (lowIndex
== -1)) {
2414 HALASSERT(freq
> fbin2freq(powInfo
[i
- 1].bChannel
, IS_CHAN_2GHZ(chan
)));
2419 if (matchIndex
!= -1) {
2420 OS_MEMCPY(pNewPower
, &powInfo
[matchIndex
], sizeof(*pNewPower
));
2422 HALASSERT(lowIndex
!= -1);
2424 * Get the lower and upper channels, target powers,
2425 * and interpolate between them.
2427 clo
= fbin2freq(powInfo
[lowIndex
].bChannel
, IS_CHAN_2GHZ(chan
));
2428 chi
= fbin2freq(powInfo
[lowIndex
+ 1].bChannel
, IS_CHAN_2GHZ(chan
));
2430 for (i
= 0; i
< numRates
; i
++) {
2431 pNewPower
->tPow2x
[i
] = (uint8_t)interpolate(freq
, clo
, chi
,
2432 powInfo
[lowIndex
].tPow2x
[i
], powInfo
[lowIndex
+ 1].tPow2x
[i
]);
2437 /**************************************************************
2438 * ar5416SetPowerCalTable
2440 * Pull the PDADC piers from cal data and interpolate them across the given
2441 * points as well as from the nearest pier(s) to get a power detector
2442 * linear voltage to power level table.
2445 ar5416SetPowerCalTable(struct ath_hal
*ah
, struct ar5416eeprom
*pEepData
, HAL_CHANNEL_INTERNAL
*chan
, int16_t *pTxPowerIndexOffset
)
2447 CAL_DATA_PER_FREQ
*pRawDataset
;
2448 uint8_t *pCalBChans
= AH_NULL
;
2449 uint16_t pdGainOverlap_t2
;
2450 static uint8_t pdadcValues
[AR5416_NUM_PDADC_VALUES
];
2451 uint16_t gainBoundaries
[AR5416_PD_GAINS_IN_MASK
];
2452 uint16_t numPiers
, i
, j
;
2453 int16_t tMinCalPower
;
2454 uint16_t numXpdGain
, xpdMask
;
2455 uint16_t xpdGainValues
[AR5416_NUM_PD_GAINS
];
2456 uint32_t reg32
, regOffset
, regChainOffset
;
2458 ath_hal_memzero(xpdGainValues
, sizeof(xpdGainValues
));
2460 xpdMask
= pEepData
->modalHeader
[IS_CHAN_2GHZ(chan
)].xpdGain
;
2462 if (IS_EEP_MINOR_V2(ah
)) {
2463 pdGainOverlap_t2
= pEepData
->modalHeader
[IS_CHAN_2GHZ(chan
)].pdGainOverlap
;
2465 pdGainOverlap_t2
= (uint16_t)(MS(OS_REG_READ(ah
, AR_PHY_TPCRG5
), AR_PHY_TPCRG5_PD_GAIN_OVERLAP
));
2468 if (IS_CHAN_2GHZ(chan
)) {
2469 pCalBChans
= pEepData
->calFreqPier2G
;
2470 numPiers
= AR5416_NUM_2G_CAL_PIERS
;
2472 pCalBChans
= pEepData
->calFreqPier5G
;
2473 numPiers
= AR5416_NUM_5G_CAL_PIERS
;
2477 /* Calculate the value of xpdgains from the xpdGain Mask */
2478 for (i
= 1; i
<= AR5416_PD_GAINS_IN_MASK
; i
++) {
2479 if ((xpdMask
>> (AR5416_PD_GAINS_IN_MASK
- i
)) & 1) {
2480 if (numXpdGain
>= AR5416_NUM_PD_GAINS
) {
2484 xpdGainValues
[numXpdGain
] = (uint16_t)(AR5416_PD_GAINS_IN_MASK
- i
);
2489 /* Write the detector gain biases and their number */
2490 OS_REG_WRITE(ah
, AR_PHY_TPCRG1
, (OS_REG_READ(ah
, AR_PHY_TPCRG1
) &
2491 ~(AR_PHY_TPCRG1_NUM_PD_GAIN
| AR_PHY_TPCRG1_PD_GAIN_1
| AR_PHY_TPCRG1_PD_GAIN_2
| AR_PHY_TPCRG1_PD_GAIN_3
)) |
2492 SM(numXpdGain
- 1, AR_PHY_TPCRG1_NUM_PD_GAIN
) | SM(xpdGainValues
[0], AR_PHY_TPCRG1_PD_GAIN_1
) |
2493 SM(xpdGainValues
[1], AR_PHY_TPCRG1_PD_GAIN_2
) | SM(xpdGainValues
[2], AR_PHY_TPCRG1_PD_GAIN_3
));
2495 for (i
= 0; i
< AR5416_MAX_CHAINS
; i
++) {
2497 if (AR_SREV_OWL_20_OR_LATER(ah
) &&
2498 ( AH5416(ah
)->ah_rx_chainmask
== 0x5 || AH5416(ah
)->ah_tx_chainmask
== 0x5) && (i
!= 0)) {
2499 /* Regs are swapped from chain 2 to 1 for 5416 2_0 with
2500 * only chains 0 and 2 populated
2502 regChainOffset
= (i
== 1) ? 0x2000 : 0x1000;
2504 regChainOffset
= i
* 0x1000;
2507 if (pEepData
->baseEepHeader
.txMask
& (1 << i
)) {
2508 if (IS_CHAN_2GHZ(chan
)) {
2509 pRawDataset
= pEepData
->calPierData2G
[i
];
2511 pRawDataset
= pEepData
->calPierData5G
[i
];
2514 ar5416GetGainBoundariesAndPdadcs(ah
, chan
, pRawDataset
,
2515 pCalBChans
, numPiers
,
2517 &tMinCalPower
, gainBoundaries
,
2518 pdadcValues
, numXpdGain
);
2520 if ((i
== 0) || AR_SREV_OWL_20_OR_LATER(ah
)) {
2522 * Note the pdadc table may not start at 0 dBm power, could be
2523 * negative or greater than 0. Need to offset the power
2524 * values by the amount of minPower for griffin
2527 OS_REG_WRITE(ah
, AR_PHY_TPCRG5
+ regChainOffset
,
2528 SM(pdGainOverlap_t2
, AR_PHY_TPCRG5_PD_GAIN_OVERLAP
) |
2529 SM(gainBoundaries
[0], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1
) |
2530 SM(gainBoundaries
[1], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2
) |
2531 SM(gainBoundaries
[2], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3
) |
2532 SM(gainBoundaries
[3], AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4
));
2535 /* Write the power values into the baseband power table */
2536 regOffset
= AR_PHY_BASE
+ (672 << 2) + regChainOffset
;
2538 for (j
= 0; j
< 32; j
++) {
2539 reg32
= ((pdadcValues
[4*j
+ 0] & 0xFF) << 0) |
2540 ((pdadcValues
[4*j
+ 1] & 0xFF) << 8) |
2541 ((pdadcValues
[4*j
+ 2] & 0xFF) << 16) |
2542 ((pdadcValues
[4*j
+ 3] & 0xFF) << 24) ;
2543 OS_REG_WRITE(ah
, regOffset
, reg32
);
2546 ath_hal_printf(ah
, "PDADC: Chain %d | PDADC %3d Value %3d | PDADC %3d Value %3d | PDADC %3d Value %3d | PDADC %3d Value %3d |\n",
2548 4*j
, pdadcValues
[4*j
],
2549 4*j
+1, pdadcValues
[4*j
+ 1],
2550 4*j
+2, pdadcValues
[4*j
+ 2],
2551 4*j
+3, pdadcValues
[4*j
+ 3]);
2557 *pTxPowerIndexOffset
= 0;
2562 /**************************************************************
2563 * ar5416GetGainBoundariesAndPdadcs
2565 * Uses the data points read from EEPROM to reconstruct the pdadc power table
2566 * Called by ar5416SetPowerCalTable only.
2569 ar5416GetGainBoundariesAndPdadcs(struct ath_hal
*ah
,
2570 HAL_CHANNEL_INTERNAL
*chan
, CAL_DATA_PER_FREQ
*pRawDataSet
,
2571 uint8_t * bChans
, uint16_t availPiers
,
2572 uint16_t tPdGainOverlap
, int16_t *pMinCalPower
, uint16_t * pPdGainBoundaries
,
2573 uint8_t * pPDADCValues
, uint16_t numXpdGains
)
2577 int16_t ss
; /* potentially -ve index for taking care of pdGainOverlap */
2578 uint16_t idxL
= 0, idxR
= 0, numPiers
; /* Pier indexes */
2580 /* filled out Vpd table for all pdGains (chanL) */
2581 static uint8_t vpdTableL
[AR5416_NUM_PD_GAINS
][AR5416_MAX_PWR_RANGE_IN_HALF_DB
];
2583 /* filled out Vpd table for all pdGains (chanR) */
2584 static uint8_t vpdTableR
[AR5416_NUM_PD_GAINS
][AR5416_MAX_PWR_RANGE_IN_HALF_DB
];
2586 /* filled out Vpd table for all pdGains (interpolated) */
2587 static uint8_t vpdTableI
[AR5416_NUM_PD_GAINS
][AR5416_MAX_PWR_RANGE_IN_HALF_DB
];
2589 uint8_t *pVpdL
, *pVpdR
, *pPwrL
, *pPwrR
;
2590 uint8_t minPwrT4
[AR5416_NUM_PD_GAINS
];
2591 uint8_t maxPwrT4
[AR5416_NUM_PD_GAINS
];
2594 uint16_t sizeCurrVpdTable
, maxIndex
, tgtIndex
;
2596 int16_t minDelta
= 0;
2597 CHAN_CENTERS centers
;
2599 ar5416GetChannelCenters(ah
, chan
, ¢ers
);
2601 /* Trim numPiers for the number of populated channel Piers */
2602 for (numPiers
= 0; numPiers
< availPiers
; numPiers
++) {
2603 if (bChans
[numPiers
] == AR5416_BCHAN_UNUSED
) {
2608 /* Find pier indexes around the current channel */
2609 match
= getLowerUpperIndex((uint8_t)FREQ2FBIN(centers
.synth_center
, IS_CHAN_2GHZ(chan
)),
2610 bChans
, numPiers
, &idxL
, &idxR
);
2613 /* Directly fill both vpd tables from the matching index */
2614 for (i
= 0; i
< numXpdGains
; i
++) {
2615 minPwrT4
[i
] = pRawDataSet
[idxL
].pwrPdg
[i
][0];
2616 maxPwrT4
[i
] = pRawDataSet
[idxL
].pwrPdg
[i
][4];
2617 ar5416FillVpdTable(minPwrT4
[i
], maxPwrT4
[i
], pRawDataSet
[idxL
].pwrPdg
[i
],
2618 pRawDataSet
[idxL
].vpdPdg
[i
], AR5416_PD_GAIN_ICEPTS
, vpdTableI
[i
]);
2621 for (i
= 0; i
< numXpdGains
; i
++) {
2622 pVpdL
= pRawDataSet
[idxL
].vpdPdg
[i
];
2623 pPwrL
= pRawDataSet
[idxL
].pwrPdg
[i
];
2624 pVpdR
= pRawDataSet
[idxR
].vpdPdg
[i
];
2625 pPwrR
= pRawDataSet
[idxR
].pwrPdg
[i
];
2627 /* Start Vpd interpolation from the max of the minimum powers */
2628 minPwrT4
[i
] = AH_MAX(pPwrL
[0], pPwrR
[0]);
2630 /* End Vpd interpolation from the min of the max powers */
2631 maxPwrT4
[i
] = AH_MIN(pPwrL
[AR5416_PD_GAIN_ICEPTS
- 1], pPwrR
[AR5416_PD_GAIN_ICEPTS
- 1]);
2632 HALASSERT(maxPwrT4
[i
] > minPwrT4
[i
]);
2634 /* Fill pier Vpds */
2635 ar5416FillVpdTable(minPwrT4
[i
], maxPwrT4
[i
], pPwrL
, pVpdL
, AR5416_PD_GAIN_ICEPTS
, vpdTableL
[i
]);
2636 ar5416FillVpdTable(minPwrT4
[i
], maxPwrT4
[i
], pPwrR
, pVpdR
, AR5416_PD_GAIN_ICEPTS
, vpdTableR
[i
]);
2638 /* Interpolate the final vpd */
2639 for (j
= 0; j
<= (maxPwrT4
[i
] - minPwrT4
[i
]) / 2; j
++) {
2640 vpdTableI
[i
][j
] = (uint8_t)(interpolate((uint16_t)FREQ2FBIN(centers
.synth_center
, IS_CHAN_2GHZ(chan
)),
2641 bChans
[idxL
], bChans
[idxR
], vpdTableL
[i
][j
], vpdTableR
[i
][j
]));
2645 *pMinCalPower
= (int16_t)(minPwrT4
[0] / 2);
2647 k
= 0; /* index for the final table */
2648 for (i
= 0; i
< numXpdGains
; i
++) {
2649 if (i
== (numXpdGains
- 1)) {
2650 pPdGainBoundaries
[i
] = (uint16_t)(maxPwrT4
[i
] / 2);
2652 pPdGainBoundaries
[i
] = (uint16_t)((maxPwrT4
[i
] + minPwrT4
[i
+1]) / 4);
2655 pPdGainBoundaries
[i
] = (uint16_t)AH_MIN(AR5416_MAX_RATE_POWER
, pPdGainBoundaries
[i
]);
2657 /* NB: only applies to owl 1.0 */
2658 if ((i
== 0) && !AR_SREV_OWL_20_OR_LATER(ah
) ) {
2660 * fix the gain delta, but get a delta that can be applied to min to
2661 * keep the upper power values accurate, don't think max needs to
2662 * be adjusted because should not be at that area of the table?
2664 minDelta
= pPdGainBoundaries
[0] - 23;
2665 pPdGainBoundaries
[0] = 23;
2671 /* Find starting index for this pdGain */
2673 ss
= 0; /* for the first pdGain, start from index 0 */
2675 /* need overlap entries extrapolated below. */
2676 ss
= (int16_t)((pPdGainBoundaries
[i
-1] - (minPwrT4
[i
] / 2)) - tPdGainOverlap
+ 1 + minDelta
);
2678 vpdStep
= (int16_t)(vpdTableI
[i
][1] - vpdTableI
[i
][0]);
2679 vpdStep
= (int16_t)((vpdStep
< 1) ? 1 : vpdStep
);
2681 *-ve ss indicates need to extrapolate data below for this pdGain
2683 while ((ss
< 0) && (k
< (AR5416_NUM_PDADC_VALUES
- 1))) {
2684 tmpVal
= (int16_t)(vpdTableI
[i
][0] + ss
* vpdStep
);
2685 pPDADCValues
[k
++] = (uint8_t)((tmpVal
< 0) ? 0 : tmpVal
);
2689 sizeCurrVpdTable
= (uint8_t)((maxPwrT4
[i
] - minPwrT4
[i
]) / 2 +1);
2690 tgtIndex
= (uint8_t)(pPdGainBoundaries
[i
] + tPdGainOverlap
- (minPwrT4
[i
] / 2));
2691 maxIndex
= (tgtIndex
< sizeCurrVpdTable
) ? tgtIndex
: sizeCurrVpdTable
;
2693 while ((ss
< maxIndex
) && (k
< (AR5416_NUM_PDADC_VALUES
- 1))) {
2694 pPDADCValues
[k
++] = vpdTableI
[i
][ss
++];
2697 vpdStep
= (int16_t)(vpdTableI
[i
][sizeCurrVpdTable
- 1] - vpdTableI
[i
][sizeCurrVpdTable
- 2]);
2698 vpdStep
= (int16_t)((vpdStep
< 1) ? 1 : vpdStep
);
2700 * for last gain, pdGainBoundary == Pmax_t2, so will
2701 * have to extrapolate
2703 if (tgtIndex
> maxIndex
) { /* need to extrapolate above */
2704 while ((ss
<= tgtIndex
) && (k
< (AR5416_NUM_PDADC_VALUES
- 1))) {
2705 tmpVal
= (int16_t)((vpdTableI
[i
][sizeCurrVpdTable
- 1] +
2706 (ss
- maxIndex
+1) * vpdStep
));
2707 pPDADCValues
[k
++] = (uint8_t)((tmpVal
> 255) ? 255 : tmpVal
);
2710 } /* extrapolated above */
2711 } /* for all pdGainUsed */
2713 /* Fill out pdGainBoundaries - only up to 2 allowed here, but hardware allows up to 4 */
2714 while (i
< AR5416_PD_GAINS_IN_MASK
) {
2715 pPdGainBoundaries
[i
] = pPdGainBoundaries
[i
-1];
2719 while (k
< AR5416_NUM_PDADC_VALUES
) {
2720 pPDADCValues
[k
] = pPDADCValues
[k
-1];
2726 /**************************************************************
2727 * getLowerUppderIndex
2729 * Return indices surrounding the value in sorted integer lists.
2730 * Requirement: the input list must be monotonically increasing
2731 * and populated up to the list size
2732 * Returns: match is set if an index in the array matches exactly
2733 * or a the target is before or after the range of the array.
2736 getLowerUpperIndex(uint8_t target
, uint8_t *pList
, uint16_t listSize
,
2737 uint16_t *indexL
, uint16_t *indexR
)
2742 * Check first and last elements for beyond ordered array cases.
2744 if (target
<= pList
[0]) {
2745 *indexL
= *indexR
= 0;
2748 if (target
>= pList
[listSize
-1]) {
2749 *indexL
= *indexR
= (uint16_t)(listSize
- 1);
2753 /* look for value being near or between 2 values in list */
2754 for (i
= 0; i
< listSize
- 1; i
++) {
2756 * If value is close to the current value of the list
2757 * then target is not between values, it is one of the values
2759 if (pList
[i
] == target
) {
2760 *indexL
= *indexR
= i
;
2764 * Look for value being between current value and next value
2765 * if so return these 2 values
2767 if (target
< pList
[i
+ 1]) {
2769 *indexR
= (uint16_t)(i
+ 1);
2777 /**************************************************************
2778 * ar5416FillVpdTable
2780 * Fill the Vpdlist for indices Pmax-Pmin
2781 * Note: pwrMin, pwrMax and Vpdlist are all in dBm * 4
2784 ar5416FillVpdTable(uint8_t pwrMin
, uint8_t pwrMax
, uint8_t *pPwrList
,
2785 uint8_t *pVpdList
, uint16_t numIntercepts
, uint8_t *pRetVpdList
)
2788 uint8_t currPwr
= pwrMin
;
2789 uint16_t idxL
= 0, idxR
= 0;
2791 HALASSERT(pwrMax
> pwrMin
);
2792 for (i
= 0; i
<= (pwrMax
- pwrMin
) / 2; i
++) {
2793 getLowerUpperIndex(currPwr
, pPwrList
, numIntercepts
,
2796 idxR
= 1; /* extrapolate below */
2797 if (idxL
== numIntercepts
- 1)
2798 idxL
= (uint16_t)(numIntercepts
- 2); /* extrapolate above */
2799 if (pPwrList
[idxL
] == pPwrList
[idxR
])
2802 k
= (uint16_t)( ((currPwr
- pPwrList
[idxL
]) * pVpdList
[idxR
] + (pPwrList
[idxR
] - currPwr
) * pVpdList
[idxL
]) /
2803 (pPwrList
[idxR
] - pPwrList
[idxL
]) );
2805 pRetVpdList
[i
] = (uint8_t)k
;
2806 currPwr
+= 2; /* half dB steps */
2812 /**************************************************************************
2815 * Returns signed interpolated or the scaled up interpolated value
2818 interpolate(uint16_t target
, uint16_t srcLeft
, uint16_t srcRight
,
2819 int16_t targetLeft
, int16_t targetRight
)
2823 if (srcRight
== srcLeft
) {
2826 rv
= (int16_t)( ((target
- srcLeft
) * targetRight
+
2827 (srcRight
- target
) * targetLeft
) / (srcRight
- srcLeft
) );
2833 ar5416Set11nRegs(struct ath_hal
*ah
, HAL_CHANNEL
*chan
)
2836 HAL_HT_MACMODE macmode
; /* MAC - 20/40 mode */
2838 if (!IS_CHAN_HT(chan
))
2841 /* Enable 11n HT, 20 MHz */
2842 phymode
= AR_PHY_FC_HT_EN
| AR_PHY_FC_SHORT_GI_40
2843 | AR_PHY_FC_SINGLE_HT_LTF1
| AR_PHY_FC_WALSH
;
2845 /* Configure baseband for dynamic 20/40 operation */
2846 if (IS_CHAN_HT40(chan
)) {
2847 phymode
|= AR_PHY_FC_DYN2040_EN
| AR_PHY_FC_SHORT_GI_40
;
2849 /* Configure control (primary) channel at +-10MHz */
2850 if ((chan
->channelFlags
& CHANNEL_HT40PLUS
))
2851 phymode
|= AR_PHY_FC_DYN2040_PRI_CH
;
2853 /* Configure 20/25 spacing */
2854 if (ht
->ht_extprotspacing
== HAL_HT_EXTPROTSPACING_25
)
2855 phymode
|= AR_PHY_FC_DYN2040_EXT_CH
;
2857 macmode
= HAL_HT_MACMODE_2040
;
2859 macmode
= HAL_HT_MACMODE_20
;
2860 OS_REG_WRITE(ah
, AR_PHY_TURBO
, phymode
);
2862 /* Configure MAC for 20/40 operation */
2863 ar5416Set11nMac2040(ah
, macmode
);
2865 /* global transmit timeout (25 TUs default)*/
2866 /* XXX - put this elsewhere??? */
2867 OS_REG_WRITE(ah
, AR_GTXTO
, 25 << AR_GTXTO_TIMEOUT_LIMIT_S
) ;
2869 /* carrier sense timeout */
2870 OS_REG_SET_BIT(ah
, AR_GTTM
, AR_GTTM_CST_USEC
);
2871 OS_REG_WRITE(ah
, AR_CST
, 1 << AR_CST_TIMEOUT_LIMIT_S
);
2875 ar5416GetChannelCenters(struct ath_hal
*ah
,
2876 HAL_CHANNEL_INTERNAL
*chan
, CHAN_CENTERS
*centers
)
2878 centers
->ctl_center
= chan
->channel
;
2879 centers
->synth_center
= chan
->channel
;
2881 * In 20/40 phy mode, the center frequency is
2882 * "between" the control and extension channels.
2884 if (chan
->channelFlags
& CHANNEL_HT40PLUS
) {
2885 centers
->synth_center
+= HT40_CHANNEL_CENTER_SHIFT
;
2886 centers
->ext_center
=
2887 centers
->synth_center
+ HT40_CHANNEL_CENTER_SHIFT
;
2888 } else if (chan
->channelFlags
& CHANNEL_HT40MINUS
) {
2889 centers
->synth_center
-= HT40_CHANNEL_CENTER_SHIFT
;
2890 centers
->ext_center
=
2891 centers
->synth_center
- HT40_CHANNEL_CENTER_SHIFT
;
2893 centers
->ext_center
= chan
->channel
;