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: ar5212_reset.c,v 1.2 2009/01/06 06:03:57 mrg Exp $
22 #include "ah_internal.h"
25 #include "ar5212/ar5212.h"
26 #include "ar5212/ar5212reg.h"
27 #include "ar5212/ar5212phy.h"
29 #include "ah_eeprom_v3.h"
31 /* Additional Time delay to wait after activiting the Base band */
32 #define BASE_ACTIVATE_DELAY 100 /* 100 usec */
33 #define PLL_SETTLE_DELAY 300 /* 300 usec */
35 static HAL_BOOL
ar5212SetResetReg(struct ath_hal
*, uint32_t resetMask
);
36 /* NB: public for 5312 use */
37 HAL_BOOL
ar5212IsSpurChannel(struct ath_hal
*, HAL_CHANNEL
*);
38 HAL_BOOL
ar5212ChannelChange(struct ath_hal
*, HAL_CHANNEL
*);
39 int16_t ar5212GetNf(struct ath_hal
*, HAL_CHANNEL_INTERNAL
*);
40 HAL_BOOL
ar5212SetBoardValues(struct ath_hal
*, HAL_CHANNEL_INTERNAL
*);
41 void ar5212SetDeltaSlope(struct ath_hal
*, HAL_CHANNEL
*);
42 HAL_BOOL
ar5212SetTransmitPower(struct ath_hal
*ah
,
43 HAL_CHANNEL_INTERNAL
*chan
, uint16_t *rfXpdGain
);
44 static HAL_BOOL
ar5212SetRateTable(struct ath_hal
*,
45 HAL_CHANNEL
*, int16_t tpcScaleReduction
, int16_t powerLimit
,
46 HAL_BOOL commit
, int16_t *minPower
, int16_t *maxPower
);
47 static void ar5212CorrectGainDelta(struct ath_hal
*, int twiceOfdmCckDelta
);
48 static void ar5212GetTargetPowers(struct ath_hal
*, HAL_CHANNEL
*,
49 const TRGT_POWER_INFO
*pPowerInfo
, uint16_t numChannels
,
50 TRGT_POWER_INFO
*pNewPower
);
51 static uint16_t ar5212GetMaxEdgePower(uint16_t channel
,
52 const RD_EDGES_POWER
*pRdEdgesPower
);
53 void ar5212SetRateDurationTable(struct ath_hal
*, HAL_CHANNEL
*);
54 void ar5212SetIFSTiming(struct ath_hal
*, HAL_CHANNEL
*);
56 /* NB: public for RF backend use */
57 void ar5212GetLowerUpperValues(uint16_t value
,
58 uint16_t *pList
, uint16_t listSize
,
59 uint16_t *pLowerValue
, uint16_t *pUpperValue
);
60 void ar5212ModifyRfBuffer(uint32_t *rfBuf
, uint32_t reg32
,
61 uint32_t numBits
, uint32_t firstBit
, uint32_t column
);
64 write_common(struct ath_hal
*ah
, const HAL_INI_ARRAY
*ia
,
65 HAL_BOOL bChannelChange
, int writes
)
67 #define IS_NO_RESET_TIMER_ADDR(x) \
68 ( (((x) >= AR_BEACON) && ((x) <= AR_CFP_DUR)) || \
69 (((x) >= AR_SLEEP1) && ((x) <= AR_SLEEP3)))
70 #define V(r, c) (ia)->data[((r)*(ia)->cols) + (c)]
73 /* Write Common Array Parameters */
74 for (r
= 0; r
< ia
->rows
; r
++) {
75 uint32_t reg
= V(r
, 0);
76 /* XXX timer/beacon setup registers? */
77 /* On channel change, don't reset the PCU registers */
78 if (!(bChannelChange
&& IS_NO_RESET_TIMER_ADDR(reg
))) {
79 OS_REG_WRITE(ah
, reg
, V(r
, 1));
84 #undef IS_NO_RESET_TIMER_ADDR
88 #define IS_DISABLE_FAST_ADC_CHAN(x) (((x) == 2462) || ((x) == 2467))
91 * Places the device in and out of reset and then places sane
92 * values in the registers based on EEPROM config, initialization
93 * vectors (as determined by the mode), and station configuration
95 * bChannelChange is used to preserve DMA/PCU registers across
96 * a HW Reset during channel change.
99 ar5212Reset(struct ath_hal
*ah
, HAL_OPMODE opmode
,
100 HAL_CHANNEL
*chan
, HAL_BOOL bChannelChange
, HAL_STATUS
*status
)
102 #define N(a) (sizeof (a) / sizeof (a[0]))
103 #define FAIL(_code) do { ecode = _code; goto bad; } while (0)
104 struct ath_hal_5212
*ahp
= AH5212(ah
);
105 HAL_CHANNEL_INTERNAL
*ichan
= AH_NULL
;
106 const HAL_EEPROM
*ee
;
107 uint32_t softLedCfg
, softLedState
;
108 uint32_t saveFrameSeqCount
, saveDefAntenna
, saveLedState
;
109 uint32_t macStaId1
, synthDelay
, txFrm2TxDStart
;
110 uint16_t rfXpdGain
[MAX_NUM_PDGAINS_PER_CHANNEL
];
111 int16_t cckOfdmPwrDelta
= 0;
112 u_int modesIndex
, freqIndex
;
115 uint32_t testReg
, powerVal
;
116 int8_t twiceAntennaGain
, twiceAntennaReduction
;
117 uint32_t ackTpcPow
, ctsTpcPow
, chirpTpcPow
;
118 HAL_BOOL isBmode
= AH_FALSE
;
119 HAL_BOOL ichan_isBmode
= AH_FALSE
;
121 HALASSERT(ah
->ah_magic
== AR5212_MAGIC
);
122 ee
= AH_PRIVATE(ah
)->ah_eeprom
;
124 OS_MARK(ah
, AH_MARK_RESET
, bChannelChange
);
125 #define IS(_c,_f) (((_c)->channelFlags & _f) || 0)
126 if ((IS(chan
, CHANNEL_2GHZ
) ^ IS(chan
, CHANNEL_5GHZ
)) == 0) {
127 HALDEBUG(ah
, HAL_DEBUG_ANY
,
128 "%s: invalid channel %u/0x%x; not marked as 2GHz or 5GHz\n",
129 __func__
, chan
->channel
, chan
->channelFlags
);
132 if ((IS(chan
, CHANNEL_OFDM
) ^ IS(chan
, CHANNEL_CCK
)) == 0) {
133 HALDEBUG(ah
, HAL_DEBUG_ANY
,
134 "%s: invalid channel %u/0x%x; not marked as OFDM or CCK\n",
135 __func__
, chan
->channel
, chan
->channelFlags
);
140 /* Bring out of sleep mode */
141 if (!ar5212SetPowerMode(ah
, HAL_PM_AWAKE
, AH_TRUE
)) {
142 HALDEBUG(ah
, HAL_DEBUG_ANY
, "%s: chip did not wakeup\n",
148 * Map public channel to private.
150 ichan
= ath_hal_checkchannel(ah
, chan
);
151 if (ichan
== AH_NULL
) {
152 HALDEBUG(ah
, HAL_DEBUG_ANY
,
153 "%s: invalid channel %u/0x%x; no mapping\n",
154 __func__
, chan
->channel
, chan
->channelFlags
);
164 HALDEBUG(ah
, HAL_DEBUG_ANY
, "%s: invalid operating mode %u\n",
169 HALASSERT(AH_PRIVATE(ah
)->ah_eeversion
>= AR_EEPROM_VER3
);
171 SAVE_CCK(ah
, ichan
, ichan_isBmode
);
172 SAVE_CCK(ah
, chan
, isBmode
);
174 /* Preserve certain DMA hardware registers on a channel change */
175 if (bChannelChange
) {
177 * On Venice, the TSF is almost preserved across a reset;
178 * it requires doubling writes to the RESET_TSF
179 * bit in the AR_BEACON register; it also has the quirk
180 * of the TSF going back in time on the station (station
181 * latches onto the last beacon's tsf during a reset 50%
182 * of the times); the latter is not a problem for adhoc
183 * stations since as long as the TSF is behind, it will
184 * get resynchronized on receiving the next beacon; the
185 * TSF going backwards in time could be a problem for the
186 * sleep operation (supported on infrastructure stations
187 * only) - the best and most general fix for this situation
188 * is to resynchronize the various sleep/beacon timers on
189 * the receipt of the next beacon i.e. when the TSF itself
190 * gets resynchronized to the AP's TSF - power save is
191 * needed to be temporarily disabled until that time
193 * Need to save the sequence number to restore it after
196 saveFrameSeqCount
= OS_REG_READ(ah
, AR_D_SEQNUM
);
198 saveFrameSeqCount
= 0; /* NB: silence compiler */
201 * XXX disable for now; this appears to sometimes cause OFDM
202 * XXX timing error floods when ani is enabled and bg scanning
205 /* If the channel change is across the same mode - perform a fast channel change */
206 if (IS_2413(ah
) || IS_5413(ah
)) {
208 * Fast channel change can only be used when:
209 * -channel change requested - so it's not the initial reset.
210 * -it's not a change to the current channel -
211 * often called when switching modes on a channel
212 * -the modes of the previous and requested channel are the
214 * XXX opmode shouldn't change either?
216 if (bChannelChange
&&
217 (AH_PRIVATE(ah
)->ah_curchan
!= AH_NULL
) &&
218 (chan
->channel
!= AH_PRIVATE(ah
)->ah_curchan
->channel
) &&
219 ((chan
->channelFlags
& CHANNEL_ALL
) ==
220 (AH_PRIVATE(ah
)->ah_curchan
->channelFlags
& CHANNEL_ALL
))) {
221 if (ar5212ChannelChange(ah
, chan
)) {
222 /* If ChannelChange completed - skip the rest of reset */
230 * Preserve the antenna on a channel change
232 saveDefAntenna
= OS_REG_READ(ah
, AR_DEF_ANTENNA
);
233 if (saveDefAntenna
== 0) /* XXX magic constants */
236 /* Save hardware flag before chip reset clears the register */
237 macStaId1
= OS_REG_READ(ah
, AR_STA_ID1
) &
238 (AR_STA_ID1_BASE_RATE_11B
| AR_STA_ID1_USE_DEFANT
);
240 /* Save led state from pci config register */
241 saveLedState
= OS_REG_READ(ah
, AR_PCICFG
) &
242 (AR_PCICFG_LEDCTL
| AR_PCICFG_LEDMODE
| AR_PCICFG_LEDBLINK
|
244 softLedCfg
= OS_REG_READ(ah
, AR_GPIOCR
);
245 softLedState
= OS_REG_READ(ah
, AR_GPIODO
);
247 ar5212RestoreClock(ah
, opmode
); /* move to refclk operation */
250 * Adjust gain parameters before reset if
251 * there's an outstanding gain updated.
253 (void) ar5212GetRfgain(ah
);
255 if (!ar5212ChipReset(ah
, chan
)) {
256 HALDEBUG(ah
, HAL_DEBUG_ANY
, "%s: chip reset failed\n", __func__
);
260 /* Setup the indices for the next set of register array writes */
261 switch (chan
->channelFlags
& CHANNEL_ALL
) {
283 HALDEBUG(ah
, HAL_DEBUG_ANY
, "%s: invalid channel flags 0x%x\n",
284 __func__
, chan
->channelFlags
);
288 OS_MARK(ah
, AH_MARK_RESET_LINE
, __LINE__
);
290 /* Set correct Baseband to analog shift setting to access analog chips. */
291 OS_REG_WRITE(ah
, AR_PHY(0), 0x00000007);
293 regWrites
= ath_hal_ini_write(ah
, &ahp
->ah_ini_modes
, modesIndex
, 0);
294 regWrites
= write_common(ah
, &ahp
->ah_ini_common
, bChannelChange
,
296 ahp
->ah_rfHal
->writeRegs(ah
, modesIndex
, freqIndex
, regWrites
);
298 OS_MARK(ah
, AH_MARK_RESET_LINE
, __LINE__
);
300 if (IS_CHAN_HALF_RATE(chan
) || IS_CHAN_QUARTER_RATE(chan
)) {
301 ar5212SetIFSTiming(ah
, chan
);
304 * Force window_length for 1/2 and 1/4 rate channels,
305 * the ini file sets this to zero otherwise.
307 OS_REG_RMW_FIELD(ah
, AR_PHY_FRAME_CTL
,
308 AR_PHY_FRAME_CTL_WINLEN
, 3);
312 /* Overwrite INI values for revised chipsets */
313 if (AH_PRIVATE(ah
)->ah_phyRev
>= AR_PHY_CHIP_ID_REV_2
) {
315 OS_REG_WRITE(ah
, AR_PHY_ADC_CTL
,
316 SM(2, AR_PHY_ADC_CTL_OFF_INBUFGAIN
) |
317 SM(2, AR_PHY_ADC_CTL_ON_INBUFGAIN
) |
318 AR_PHY_ADC_CTL_OFF_PWDDAC
|
319 AR_PHY_ADC_CTL_OFF_PWDADC
);
322 if (chan
->channel
== 2484) {
323 cckOfdmPwrDelta
= SCALE_OC_DELTA(
324 ee
->ee_cckOfdmPwrDelta
-
325 ee
->ee_scaledCh14FilterCckDelta
);
327 cckOfdmPwrDelta
= SCALE_OC_DELTA(
328 ee
->ee_cckOfdmPwrDelta
);
331 if (IS_CHAN_G(chan
)) {
332 OS_REG_WRITE(ah
, AR_PHY_TXPWRADJ
,
333 SM((ee
->ee_cckOfdmPwrDelta
*-1),
334 AR_PHY_TXPWRADJ_CCK_GAIN_DELTA
) |
335 SM((cckOfdmPwrDelta
*-1),
336 AR_PHY_TXPWRADJ_CCK_PCDAC_INDEX
));
338 OS_REG_WRITE(ah
, AR_PHY_TXPWRADJ
, 0);
341 /* Add barker RSSI thresh enable as disabled */
342 OS_REG_CLR_BIT(ah
, AR_PHY_DAG_CTRLCCK
,
343 AR_PHY_DAG_CTRLCCK_EN_RSSI_THR
);
344 OS_REG_RMW_FIELD(ah
, AR_PHY_DAG_CTRLCCK
,
345 AR_PHY_DAG_CTRLCCK_RSSI_THR
, 2);
347 /* Set the mute mask to the correct default */
348 OS_REG_WRITE(ah
, AR_SEQ_MASK
, 0x0000000F);
351 if (AH_PRIVATE(ah
)->ah_phyRev
>= AR_PHY_CHIP_ID_REV_3
) {
352 /* Clear reg to alllow RX_CLEAR line debug */
353 OS_REG_WRITE(ah
, AR_PHY_BLUETOOTH
, 0);
355 if (AH_PRIVATE(ah
)->ah_phyRev
>= AR_PHY_CHIP_ID_REV_4
) {
357 /* Enable burst prefetch for the data queues */
358 OS_REG_RMW_FIELD(ah
, AR_D_FPCTL
, ... );
359 /* Enable double-buffering */
360 OS_REG_CLR_BIT(ah
, AR_TXCFG
, AR_TXCFG_DBL_BUF_DIS
);
364 /* Set ADC/DAC select values */
365 OS_REG_WRITE(ah
, AR_PHY_SLEEP_SCAL
, 0x0e);
367 if (IS_5413(ah
) || IS_2417(ah
)) {
369 if (IS_DISABLE_FAST_ADC_CHAN(chan
->channel
))
371 /* As it's a clock changing register, only write when the value needs to be changed */
372 if (OS_REG_READ(ah
, AR_PHY_FAST_ADC
) != newReg
)
373 OS_REG_WRITE(ah
, AR_PHY_FAST_ADC
, newReg
);
376 /* Setup the transmit power values. */
377 if (!ar5212SetTransmitPower(ah
, ichan
, rfXpdGain
)) {
378 HALDEBUG(ah
, HAL_DEBUG_ANY
,
379 "%s: error init'ing transmit power\n", __func__
);
383 /* Write the analog registers */
384 if (!ahp
->ah_rfHal
->setRfRegs(ah
, ichan
, modesIndex
, rfXpdGain
)) {
385 HALDEBUG(ah
, HAL_DEBUG_ANY
, "%s: ar5212SetRfRegs failed\n",
390 /* Write delta slope for OFDM enabled modes (A, G, Turbo) */
391 if (IS_CHAN_OFDM(chan
)) {
392 if ((IS_5413(ah
) || (AH_PRIVATE(ah
)->ah_eeversion
>= AR_EEPROM_VER5_3
)) &&
394 ar5212SetSpurMitigation(ah
, ichan
);
395 ar5212SetDeltaSlope(ah
, chan
);
398 /* Setup board specific options for EEPROM version 3 */
399 if (!ar5212SetBoardValues(ah
, ichan
)) {
400 HALDEBUG(ah
, HAL_DEBUG_ANY
,
401 "%s: error setting board options\n", __func__
);
405 /* Restore certain DMA hardware registers on a channel change */
407 OS_REG_WRITE(ah
, AR_D_SEQNUM
, saveFrameSeqCount
);
409 OS_MARK(ah
, AH_MARK_RESET_LINE
, __LINE__
);
411 OS_REG_WRITE(ah
, AR_STA_ID0
, LE_READ_4(ahp
->ah_macaddr
));
412 OS_REG_WRITE(ah
, AR_STA_ID1
, LE_READ_2(ahp
->ah_macaddr
+ 4)
414 | AR_STA_ID1_RTS_USE_DEF
415 | ahp
->ah_staId1Defaults
417 ar5212SetOperatingMode(ah
, opmode
);
419 /* Set Venice BSSID mask according to current state */
420 OS_REG_WRITE(ah
, AR_BSSMSKL
, LE_READ_4(ahp
->ah_bssidmask
));
421 OS_REG_WRITE(ah
, AR_BSSMSKU
, LE_READ_2(ahp
->ah_bssidmask
+ 4));
423 /* Restore previous led state */
424 OS_REG_WRITE(ah
, AR_PCICFG
, OS_REG_READ(ah
, AR_PCICFG
) | saveLedState
);
426 /* Restore soft Led state to GPIO */
427 OS_REG_WRITE(ah
, AR_GPIOCR
, softLedCfg
);
428 OS_REG_WRITE(ah
, AR_GPIODO
, softLedState
);
430 /* Restore previous antenna */
431 OS_REG_WRITE(ah
, AR_DEF_ANTENNA
, saveDefAntenna
);
434 OS_REG_WRITE(ah
, AR_BSS_ID0
, LE_READ_4(ahp
->ah_bssid
));
435 OS_REG_WRITE(ah
, AR_BSS_ID1
, LE_READ_2(ahp
->ah_bssid
+ 4));
437 /* Restore bmiss rssi & count thresholds */
438 OS_REG_WRITE(ah
, AR_RSSI_THR
, ahp
->ah_rssiThr
);
440 OS_REG_WRITE(ah
, AR_ISR
, ~0); /* cleared on write */
442 if (!ar5212SetChannel(ah
, ichan
))
445 OS_MARK(ah
, AH_MARK_RESET_LINE
, __LINE__
);
447 ar5212SetCoverageClass(ah
, AH_PRIVATE(ah
)->ah_coverageClass
, 1);
449 ar5212SetRateDurationTable(ah
, chan
);
451 /* Set Tx frame start to tx data start delay */
452 if (IS_RAD5112_ANY(ah
) &&
453 (IS_CHAN_HALF_RATE(AH_PRIVATE(ah
)->ah_curchan
) ||
454 IS_CHAN_QUARTER_RATE(AH_PRIVATE(ah
)->ah_curchan
))) {
456 (IS_CHAN_HALF_RATE(AH_PRIVATE(ah
)->ah_curchan
)) ?
457 TX_FRAME_D_START_HALF_RATE
:
458 TX_FRAME_D_START_QUARTER_RATE
;
459 OS_REG_RMW_FIELD(ah
, AR_PHY_TX_CTL
,
460 AR_PHY_TX_FRAME_TO_TX_DATA_START
, txFrm2TxDStart
);
464 * Setup fast diversity.
465 * Fast diversity can be enabled or disabled via regadd.txt.
466 * Default is enabled.
469 * 0x00009860 0x00009d18 (if 11a / 11g, else no change)
470 * 0x00009970 0x192bb514
471 * 0x0000a208 0xd03e4648
473 * Enable: 0x00009860 0x00009d10 (if 11a / 11g, else no change)
474 * 0x00009970 0x192fb514
475 * 0x0000a208 0xd03e6788
478 /* XXX Setup pre PHY ENABLE EAR additions */
480 * Wait for the frequency synth to settle (synth goes on
481 * via AR_PHY_ACTIVE_EN). Read the phy active delay register.
482 * Value is in 100ns increments.
484 synthDelay
= OS_REG_READ(ah
, AR_PHY_RX_DELAY
) & AR_PHY_RX_DELAY_DELAY
;
485 if (IS_CHAN_CCK(chan
)) {
486 synthDelay
= (4 * synthDelay
) / 22;
491 /* Activate the PHY (includes baseband activate and synthesizer on) */
492 OS_REG_WRITE(ah
, AR_PHY_ACTIVE
, AR_PHY_ACTIVE_EN
);
495 * There is an issue if the AP starts the calibration before
496 * the base band timeout completes. This could result in the
497 * rx_clear false triggering. As a workaround we add delay an
498 * extra BASE_ACTIVATE_DELAY usecs to ensure this condition
501 if (IS_CHAN_HALF_RATE(AH_PRIVATE(ah
)->ah_curchan
)) {
502 OS_DELAY((synthDelay
<< 1) + BASE_ACTIVATE_DELAY
);
503 } else if (IS_CHAN_QUARTER_RATE(AH_PRIVATE(ah
)->ah_curchan
)) {
504 OS_DELAY((synthDelay
<< 2) + BASE_ACTIVATE_DELAY
);
506 OS_DELAY(synthDelay
+ BASE_ACTIVATE_DELAY
);
510 * The udelay method is not reliable with notebooks.
511 * Need to check to see if the baseband is ready
513 testReg
= OS_REG_READ(ah
, AR_PHY_TESTCTRL
);
514 /* Selects the Tx hold */
515 OS_REG_WRITE(ah
, AR_PHY_TESTCTRL
, AR_PHY_TESTCTRL_TXHOLD
);
518 (OS_REG_READ(ah
, 0x9c24) & 0x10)) /* test if baseband not ready */ OS_DELAY(200);
519 OS_REG_WRITE(ah
, AR_PHY_TESTCTRL
, testReg
);
521 /* Calibrate the AGC and start a NF calculation */
522 OS_REG_WRITE(ah
, AR_PHY_AGC_CONTROL
,
523 OS_REG_READ(ah
, AR_PHY_AGC_CONTROL
)
524 | AR_PHY_AGC_CONTROL_CAL
525 | AR_PHY_AGC_CONTROL_NF
);
527 if (!IS_CHAN_B(chan
) && ahp
->ah_bIQCalibration
!= IQ_CAL_DONE
) {
528 /* Start IQ calibration w/ 2^(INIT_IQCAL_LOG_COUNT_MAX+1) samples */
529 OS_REG_RMW_FIELD(ah
, AR_PHY_TIMING_CTRL4
,
530 AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX
,
531 INIT_IQCAL_LOG_COUNT_MAX
);
532 OS_REG_SET_BIT(ah
, AR_PHY_TIMING_CTRL4
,
533 AR_PHY_TIMING_CTRL4_DO_IQCAL
);
534 ahp
->ah_bIQCalibration
= IQ_CAL_RUNNING
;
536 ahp
->ah_bIQCalibration
= IQ_CAL_INACTIVE
;
538 /* Setup compression registers */
539 ar5212SetCompRegs(ah
);
541 /* Set 1:1 QCU to DCU mapping for all queues */
542 for (i
= 0; i
< AR_NUM_DCU
; i
++)
543 OS_REG_WRITE(ah
, AR_DQCUMASK(i
), 1 << i
);
545 ahp
->ah_intrTxqs
= 0;
546 for (i
= 0; i
< AH_PRIVATE(ah
)->ah_caps
.halTotalQueues
; i
++)
547 ar5212ResetTxQueue(ah
, i
);
550 * Setup interrupt handling. Note that ar5212ResetTxQueue
551 * manipulates the secondary IMR's as queues are enabled
552 * and disabled. This is done with RMW ops to insure the
553 * settings we make here are preserved.
555 ahp
->ah_maskReg
= AR_IMR_TXOK
| AR_IMR_TXERR
| AR_IMR_TXURN
556 | AR_IMR_RXOK
| AR_IMR_RXERR
| AR_IMR_RXORN
559 if (opmode
== HAL_M_HOSTAP
)
560 ahp
->ah_maskReg
|= AR_IMR_MIB
;
561 OS_REG_WRITE(ah
, AR_IMR
, ahp
->ah_maskReg
);
562 /* Enable bus errors that are OR'd to set the HIUERR bit */
563 OS_REG_WRITE(ah
, AR_IMR_S2
,
564 OS_REG_READ(ah
, AR_IMR_S2
)
565 | AR_IMR_S2_MCABT
| AR_IMR_S2_SSERR
| AR_IMR_S2_DPERR
);
567 if (AH_PRIVATE(ah
)->ah_rfkillEnabled
)
568 ar5212EnableRfKill(ah
);
570 if (!ath_hal_wait(ah
, AR_PHY_AGC_CONTROL
, AR_PHY_AGC_CONTROL_CAL
, 0)) {
571 HALDEBUG(ah
, HAL_DEBUG_ANY
,
572 "%s: offset calibration failed to complete in 1ms;"
573 " noisy environment?\n", __func__
);
577 * Set clocks back to 32kHz if they had been using refClk, then
578 * use an external 32kHz crystal when sleeping, if one exists.
580 ar5212SetupClock(ah
, opmode
);
583 * Writing to AR_BEACON will start timers. Hence it should
584 * be the last register to be written. Do not reset tsf, do
585 * not enable beacons at this point, but preserve other values
586 * like beaconInterval.
588 OS_REG_WRITE(ah
, AR_BEACON
,
589 (OS_REG_READ(ah
, AR_BEACON
) &~ (AR_BEACON_EN
| AR_BEACON_RESET_TSF
)));
591 /* XXX Setup post reset EAR additions */
594 if (AH_PRIVATE(ah
)->ah_macVersion
> AR_SREV_VERSION_VENICE
||
595 (AH_PRIVATE(ah
)->ah_macVersion
== AR_SREV_VERSION_VENICE
&&
596 AH_PRIVATE(ah
)->ah_macRev
>= AR_SREV_GRIFFIN_LITE
)) {
597 OS_REG_WRITE(ah
, AR_QOS_CONTROL
, 0x100aa); /* XXX magic */
598 OS_REG_WRITE(ah
, AR_QOS_SELECT
, 0x3210); /* XXX magic */
601 /* Turn on NOACK Support for QoS packets */
602 OS_REG_WRITE(ah
, AR_NOACK
,
603 SM(2, AR_NOACK_2BIT_VALUE
) |
604 SM(5, AR_NOACK_BIT_OFFSET
) |
605 SM(0, AR_NOACK_BYTE_OFFSET
));
607 /* Get Antenna Gain reduction */
608 if (IS_CHAN_5GHZ(chan
)) {
609 ath_hal_eepromGet(ah
, AR_EEP_ANTGAINMAX_5
, &twiceAntennaGain
);
611 ath_hal_eepromGet(ah
, AR_EEP_ANTGAINMAX_2
, &twiceAntennaGain
);
613 twiceAntennaReduction
=
614 ath_hal_getantennareduction(ah
, chan
, twiceAntennaGain
);
616 /* TPC for self-generated frames */
618 ackTpcPow
= MS(ahp
->ah_macTPC
, AR_TPC_ACK
);
619 if ((ackTpcPow
-ahp
->ah_txPowerIndexOffset
) > ichan
->maxTxPower
)
620 ackTpcPow
= ichan
->maxTxPower
+ahp
->ah_txPowerIndexOffset
;
622 if (ackTpcPow
> (2*ichan
->maxRegTxPower
- twiceAntennaReduction
))
623 ackTpcPow
= (2*ichan
->maxRegTxPower
- twiceAntennaReduction
)
624 + ahp
->ah_txPowerIndexOffset
;
626 ctsTpcPow
= MS(ahp
->ah_macTPC
, AR_TPC_CTS
);
627 if ((ctsTpcPow
-ahp
->ah_txPowerIndexOffset
) > ichan
->maxTxPower
)
628 ctsTpcPow
= ichan
->maxTxPower
+ahp
->ah_txPowerIndexOffset
;
630 if (ctsTpcPow
> (2*ichan
->maxRegTxPower
- twiceAntennaReduction
))
631 ctsTpcPow
= (2*ichan
->maxRegTxPower
- twiceAntennaReduction
)
632 + ahp
->ah_txPowerIndexOffset
;
634 chirpTpcPow
= MS(ahp
->ah_macTPC
, AR_TPC_CHIRP
);
635 if ((chirpTpcPow
-ahp
->ah_txPowerIndexOffset
) > ichan
->maxTxPower
)
636 chirpTpcPow
= ichan
->maxTxPower
+ahp
->ah_txPowerIndexOffset
;
638 if (chirpTpcPow
> (2*ichan
->maxRegTxPower
- twiceAntennaReduction
))
639 chirpTpcPow
= (2*ichan
->maxRegTxPower
- twiceAntennaReduction
)
640 + ahp
->ah_txPowerIndexOffset
;
646 if (chirpTpcPow
> 63)
649 powerVal
= SM(ackTpcPow
, AR_TPC_ACK
) |
650 SM(ctsTpcPow
, AR_TPC_CTS
) |
651 SM(chirpTpcPow
, AR_TPC_CHIRP
);
653 OS_REG_WRITE(ah
, AR_TPC
, powerVal
);
655 /* Restore user-specified settings */
656 if (ahp
->ah_miscMode
!= 0)
657 OS_REG_WRITE(ah
, AR_MISC_MODE
, ahp
->ah_miscMode
);
658 if (ahp
->ah_sifstime
!= (u_int
) -1)
659 ar5212SetSifsTime(ah
, ahp
->ah_sifstime
);
660 if (ahp
->ah_slottime
!= (u_int
) -1)
661 ar5212SetSlotTime(ah
, ahp
->ah_slottime
);
662 if (ahp
->ah_acktimeout
!= (u_int
) -1)
663 ar5212SetAckTimeout(ah
, ahp
->ah_acktimeout
);
664 if (ahp
->ah_ctstimeout
!= (u_int
) -1)
665 ar5212SetCTSTimeout(ah
, ahp
->ah_ctstimeout
);
666 if (AH_PRIVATE(ah
)->ah_diagreg
!= 0)
667 OS_REG_WRITE(ah
, AR_DIAG_SW
, AH_PRIVATE(ah
)->ah_diagreg
);
669 AH_PRIVATE(ah
)->ah_opmode
= opmode
; /* record operating mode */
671 if (bChannelChange
) {
672 if (!(ichan
->privFlags
& CHANNEL_DFS
))
673 ichan
->privFlags
&= ~CHANNEL_INTERFERENCE
;
674 chan
->channelFlags
= ichan
->channelFlags
;
675 chan
->privFlags
= ichan
->privFlags
;
676 chan
->maxRegTxPower
= ichan
->maxRegTxPower
;
677 chan
->maxTxPower
= ichan
->maxTxPower
;
678 chan
->minTxPower
= ichan
->minTxPower
;
681 HALDEBUG(ah
, HAL_DEBUG_RESET
, "%s: done\n", __func__
);
683 RESTORE_CCK(ah
, ichan
, ichan_isBmode
);
684 RESTORE_CCK(ah
, chan
, isBmode
);
686 OS_MARK(ah
, AH_MARK_RESET_DONE
, 0);
690 if (ichan
!= AH_NULL
)
691 RESTORE_CCK(ah
, ichan
, ichan_isBmode
);
692 RESTORE_CCK(ah
, chan
, isBmode
);
694 OS_MARK(ah
, AH_MARK_RESET_DONE
, ecode
);
703 * Call the rf backend to change the channel.
706 ar5212SetChannel(struct ath_hal
*ah
, HAL_CHANNEL_INTERNAL
*chan
)
708 struct ath_hal_5212
*ahp
= AH5212(ah
);
710 /* Change the synth */
711 if (!ahp
->ah_rfHal
->setChannel(ah
, chan
))
717 * This channel change evaluates whether the selected hardware can
718 * perform a synthesizer-only channel change (no reset). If the
719 * TX is not stopped, or the RFBus cannot be granted in the given
720 * time, the function returns false as a reset is necessary
723 ar5212ChannelChange(struct ath_hal
*ah
, HAL_CHANNEL
*chan
)
726 uint32_t data
, synthDelay
, qnum
;
727 uint16_t rfXpdGain
[MAX_NUM_PDGAINS_PER_CHANNEL
];
728 HAL_BOOL txStopped
= AH_TRUE
;
729 HAL_CHANNEL_INTERNAL
*ichan
;
732 * Map public channel to private.
734 ichan
= ath_hal_checkchannel(ah
, chan
);
736 /* TX must be stopped or RF Bus grant will not work */
737 for (qnum
= 0; qnum
< AH_PRIVATE(ah
)->ah_caps
.halTotalQueues
; qnum
++) {
738 if (ar5212NumTxPending(ah
, qnum
)) {
739 txStopped
= AH_FALSE
;
746 /* Kill last Baseband Rx Frame */
747 OS_REG_WRITE(ah
, AR_PHY_RFBUS_REQ
, AR_PHY_RFBUS_REQ_REQUEST
); /* Request analog bus grant */
748 for (ulCount
= 0; ulCount
< 100; ulCount
++) {
749 if (OS_REG_READ(ah
, AR_PHY_RFBUS_GNT
))
756 /* Change the synth */
757 if (!ar5212SetChannel(ah
, ichan
))
761 * Wait for the frequency synth to settle (synth goes on via PHY_ACTIVE_EN).
762 * Read the phy active delay register. Value is in 100ns increments.
764 data
= OS_REG_READ(ah
, AR_PHY_RX_DELAY
) & AR_PHY_RX_DELAY_DELAY
;
765 if (IS_CHAN_CCK(ichan
)) {
766 synthDelay
= (4 * data
) / 22;
768 synthDelay
= data
/ 10;
770 OS_DELAY(synthDelay
+ BASE_ACTIVATE_DELAY
);
772 /* Setup the transmit power values. */
773 if (!ar5212SetTransmitPower(ah
, ichan
, rfXpdGain
)) {
774 HALDEBUG(ah
, HAL_DEBUG_ANY
,
775 "%s: error init'ing transmit power\n", __func__
);
779 /* Write delta slope for OFDM enabled modes (A, G, Turbo) */
780 if (IS_CHAN_OFDM(ichan
)) {
781 if ((IS_5413(ah
) || (AH_PRIVATE(ah
)->ah_eeversion
>= AR_EEPROM_VER5_3
)) &&
783 ar5212SetSpurMitigation(ah
, ichan
);
784 ar5212SetDeltaSlope(ah
, chan
);
787 /* Release the RFBus Grant */
788 OS_REG_WRITE(ah
, AR_PHY_RFBUS_REQ
, 0);
790 /* Start Noise Floor Cal */
791 OS_REG_SET_BIT(ah
, AR_PHY_AGC_CONTROL
, AR_PHY_AGC_CONTROL_NF
);
793 if (!(ichan
->privFlags
& CHANNEL_DFS
))
794 ichan
->privFlags
&= ~CHANNEL_INTERFERENCE
;
795 chan
->channelFlags
= ichan
->channelFlags
;
796 chan
->privFlags
= ichan
->privFlags
;
797 chan
->maxRegTxPower
= ichan
->maxRegTxPower
;
798 chan
->maxTxPower
= ichan
->maxTxPower
;
799 chan
->minTxPower
= ichan
->minTxPower
;
804 ar5212SetOperatingMode(struct ath_hal
*ah
, int opmode
)
808 val
= OS_REG_READ(ah
, AR_STA_ID1
);
809 val
&= ~(AR_STA_ID1_STA_AP
| AR_STA_ID1_ADHOC
);
812 OS_REG_WRITE(ah
, AR_STA_ID1
, val
| AR_STA_ID1_STA_AP
813 | AR_STA_ID1_KSRCH_MODE
);
814 OS_REG_CLR_BIT(ah
, AR_CFG
, AR_CFG_AP_ADHOC_INDICATION
);
817 OS_REG_WRITE(ah
, AR_STA_ID1
, val
| AR_STA_ID1_ADHOC
818 | AR_STA_ID1_KSRCH_MODE
);
819 OS_REG_SET_BIT(ah
, AR_CFG
, AR_CFG_AP_ADHOC_INDICATION
);
823 OS_REG_WRITE(ah
, AR_STA_ID1
, val
| AR_STA_ID1_KSRCH_MODE
);
829 * Places the PHY and Radio chips into reset. A full reset
830 * must be called to leave this state. The PCI/MAC/PCU are
831 * not placed into reset as we must receive interrupt to
832 * re-enable the hardware.
835 ar5212PhyDisable(struct ath_hal
*ah
)
837 return ar5212SetResetReg(ah
, AR_RC_BB
);
841 * Places all of hardware into reset
844 ar5212Disable(struct ath_hal
*ah
)
846 if (!ar5212SetPowerMode(ah
, HAL_PM_AWAKE
, AH_TRUE
))
849 * Reset the HW - PCI must be reset after the rest of the
850 * device has been reset.
852 return ar5212SetResetReg(ah
, AR_RC_MAC
| AR_RC_BB
| AR_RC_PCI
);
856 * Places the hardware into reset and then pulls it out of reset
858 * TODO: Only write the PLL if we're changing to or from CCK mode
860 * WARNING: The order of the PLL and mode registers must be correct.
863 ar5212ChipReset(struct ath_hal
*ah
, HAL_CHANNEL
*chan
)
866 OS_MARK(ah
, AH_MARK_CHIPRESET
, chan
? chan
->channel
: 0);
869 * Reset the HW - PCI must be reset after the rest of the
870 * device has been reset
872 if (!ar5212SetResetReg(ah
, AR_RC_MAC
| AR_RC_BB
| AR_RC_PCI
))
875 /* Bring out of sleep mode (AGAIN) */
876 if (!ar5212SetPowerMode(ah
, HAL_PM_AWAKE
, AH_TRUE
))
879 /* Clear warm reset register */
880 if (!ar5212SetResetReg(ah
, 0))
884 * Perform warm reset before the mode/PLL/turbo registers
885 * are changed in order to deactivate the radio. Mode changes
886 * with an active radio can result in corrupted shifts to the
891 * Set CCK and Turbo modes correctly.
893 if (chan
!= AH_NULL
) { /* NB: can be null during attach */
894 uint32_t rfMode
, phyPLL
= 0, curPhyPLL
, turbo
;
896 if (IS_5413(ah
)) { /* NB: =>'s 5424 also */
897 rfMode
= AR_PHY_MODE_AR5112
;
898 if (IS_CHAN_HALF_RATE(chan
))
899 rfMode
|= AR_PHY_MODE_HALF
;
900 else if (IS_CHAN_QUARTER_RATE(chan
))
901 rfMode
|= AR_PHY_MODE_QUARTER
;
903 if (IS_CHAN_CCK(chan
) || IS_CHAN_G(chan
))
904 phyPLL
= AR_PHY_PLL_CTL_44_5112
;
906 phyPLL
= AR_PHY_PLL_CTL_40_5413
;
907 } else if (IS_RAD5111(ah
)) {
908 rfMode
= AR_PHY_MODE_AR5111
;
909 if (IS_CHAN_CCK(chan
) || IS_CHAN_G(chan
))
910 phyPLL
= AR_PHY_PLL_CTL_44
;
912 phyPLL
= AR_PHY_PLL_CTL_40
;
913 if (IS_CHAN_HALF_RATE(chan
))
914 phyPLL
= AR_PHY_PLL_CTL_HALF
;
915 else if (IS_CHAN_QUARTER_RATE(chan
))
916 phyPLL
= AR_PHY_PLL_CTL_QUARTER
;
917 } else { /* 5112, 2413, 2316, 2317 */
918 rfMode
= AR_PHY_MODE_AR5112
;
919 if (IS_CHAN_CCK(chan
) || IS_CHAN_G(chan
))
920 phyPLL
= AR_PHY_PLL_CTL_44_5112
;
922 phyPLL
= AR_PHY_PLL_CTL_40_5112
;
923 if (IS_CHAN_HALF_RATE(chan
))
924 phyPLL
|= AR_PHY_PLL_CTL_HALF
;
925 else if (IS_CHAN_QUARTER_RATE(chan
))
926 phyPLL
|= AR_PHY_PLL_CTL_QUARTER
;
928 if (IS_CHAN_OFDM(chan
) && (IS_CHAN_CCK(chan
) ||
930 rfMode
|= AR_PHY_MODE_DYNAMIC
;
931 else if (IS_CHAN_OFDM(chan
))
932 rfMode
|= AR_PHY_MODE_OFDM
;
934 rfMode
|= AR_PHY_MODE_CCK
;
935 if (IS_CHAN_5GHZ(chan
))
936 rfMode
|= AR_PHY_MODE_RF5GHZ
;
938 rfMode
|= AR_PHY_MODE_RF2GHZ
;
939 turbo
= IS_CHAN_TURBO(chan
) ?
940 (AR_PHY_FC_TURBO_MODE
| AR_PHY_FC_TURBO_SHORT
) : 0;
941 curPhyPLL
= OS_REG_READ(ah
, AR_PHY_PLL_CTL
);
943 * PLL, Mode, and Turbo values must be written in the correct
945 * - The PLL cannot be set to 44 unless the CCK or DYNAMIC
947 * - Turbo cannot be set at the same time as CCK or DYNAMIC
949 if (IS_CHAN_CCK(chan
) || IS_CHAN_G(chan
)) {
950 OS_REG_WRITE(ah
, AR_PHY_TURBO
, turbo
);
951 OS_REG_WRITE(ah
, AR_PHY_MODE
, rfMode
);
952 if (curPhyPLL
!= phyPLL
) {
953 OS_REG_WRITE(ah
, AR_PHY_PLL_CTL
, phyPLL
);
954 /* Wait for the PLL to settle */
955 OS_DELAY(PLL_SETTLE_DELAY
);
958 if (curPhyPLL
!= phyPLL
) {
959 OS_REG_WRITE(ah
, AR_PHY_PLL_CTL
, phyPLL
);
960 /* Wait for the PLL to settle */
961 OS_DELAY(PLL_SETTLE_DELAY
);
963 OS_REG_WRITE(ah
, AR_PHY_TURBO
, turbo
);
964 OS_REG_WRITE(ah
, AR_PHY_MODE
, rfMode
);
971 * Recalibrate the lower PHY chips to account for temperature/environment
975 ar5212PerCalibrationN(struct ath_hal
*ah
, HAL_CHANNEL
*chan
, u_int chainMask
,
976 HAL_BOOL longCal
, HAL_BOOL
*isCalDone
)
978 #define IQ_CAL_TRIES 10
979 struct ath_hal_5212
*ahp
= AH5212(ah
);
980 HAL_CHANNEL_INTERNAL
*ichan
;
981 int32_t qCoff
, qCoffDenom
;
982 int32_t iqCorrMeas
, iCoff
, iCoffDenom
;
983 uint32_t powerMeasQ
, powerMeasI
;
984 HAL_BOOL ichan_isBmode
= AH_FALSE
;
985 HAL_BOOL isBmode
= AH_FALSE
;
987 OS_MARK(ah
, AH_MARK_PERCAL
, chan
->channel
);
988 *isCalDone
= AH_FALSE
;
989 ichan
= ath_hal_checkchannel(ah
, chan
);
990 if (ichan
== AH_NULL
) {
991 HALDEBUG(ah
, HAL_DEBUG_ANY
,
992 "%s: invalid channel %u/0x%x; no mapping\n",
993 __func__
, chan
->channel
, chan
->channelFlags
);
996 SAVE_CCK(ah
, ichan
, ichan_isBmode
);
997 SAVE_CCK(ah
, chan
, isBmode
);
999 if (ahp
->ah_bIQCalibration
== IQ_CAL_DONE
||
1000 ahp
->ah_bIQCalibration
== IQ_CAL_INACTIVE
)
1001 *isCalDone
= AH_TRUE
;
1003 /* IQ calibration in progress. Check to see if it has finished. */
1004 if (ahp
->ah_bIQCalibration
== IQ_CAL_RUNNING
&&
1005 !(OS_REG_READ(ah
, AR_PHY_TIMING_CTRL4
) & AR_PHY_TIMING_CTRL4_DO_IQCAL
)) {
1008 /* IQ Calibration has finished. */
1009 ahp
->ah_bIQCalibration
= IQ_CAL_INACTIVE
;
1010 *isCalDone
= AH_TRUE
;
1012 /* workaround for misgated IQ Cal results */
1015 /* Read calibration results. */
1016 powerMeasI
= OS_REG_READ(ah
, AR_PHY_IQCAL_RES_PWR_MEAS_I
);
1017 powerMeasQ
= OS_REG_READ(ah
, AR_PHY_IQCAL_RES_PWR_MEAS_Q
);
1018 iqCorrMeas
= OS_REG_READ(ah
, AR_PHY_IQCAL_RES_IQ_CORR_MEAS
);
1019 if (powerMeasI
&& powerMeasQ
)
1021 /* Do we really need this??? */
1022 OS_REG_WRITE (ah
, AR_PHY_TIMING_CTRL4
,
1023 OS_REG_READ(ah
, AR_PHY_TIMING_CTRL4
) |
1024 AR_PHY_TIMING_CTRL4_DO_IQCAL
);
1025 } while (++i
< IQ_CAL_TRIES
);
1028 * Prescale these values to remove 64-bit operation
1029 * requirement at the loss of a little precision.
1031 iCoffDenom
= (powerMeasI
/ 2 + powerMeasQ
/ 2) / 128;
1032 qCoffDenom
= powerMeasQ
/ 128;
1034 /* Protect against divide-by-0 and loss of sign bits. */
1035 if (iCoffDenom
!= 0 && qCoffDenom
>= 2) {
1036 iCoff
= (int8_t)(-iqCorrMeas
) / iCoffDenom
;
1037 /* IQCORR_Q_I_COFF is a signed 6 bit number */
1040 } else if (iCoff
> 31) {
1044 /* IQCORR_Q_Q_COFF is a signed 5 bit number */
1045 qCoff
= (powerMeasI
/ qCoffDenom
) - 128;
1048 } else if (qCoff
> 15) {
1052 HALDEBUG(ah
, HAL_DEBUG_PERCAL
,
1053 "****************** MISGATED IQ CAL! *******************\n");
1054 HALDEBUG(ah
, HAL_DEBUG_PERCAL
,
1055 "time = %d, i = %d, \n", OS_GETUPTIME(ah
), i
);
1056 HALDEBUG(ah
, HAL_DEBUG_PERCAL
,
1057 "powerMeasI = 0x%08x\n", powerMeasI
);
1058 HALDEBUG(ah
, HAL_DEBUG_PERCAL
,
1059 "powerMeasQ = 0x%08x\n", powerMeasQ
);
1060 HALDEBUG(ah
, HAL_DEBUG_PERCAL
,
1061 "iqCorrMeas = 0x%08x\n", iqCorrMeas
);
1062 HALDEBUG(ah
, HAL_DEBUG_PERCAL
,
1063 "iCoff = %d\n", iCoff
);
1064 HALDEBUG(ah
, HAL_DEBUG_PERCAL
,
1065 "qCoff = %d\n", qCoff
);
1067 /* Write values and enable correction */
1068 OS_REG_RMW_FIELD(ah
, AR_PHY_TIMING_CTRL4
,
1069 AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF
, iCoff
);
1070 OS_REG_RMW_FIELD(ah
, AR_PHY_TIMING_CTRL4
,
1071 AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF
, qCoff
);
1072 OS_REG_SET_BIT(ah
, AR_PHY_TIMING_CTRL4
,
1073 AR_PHY_TIMING_CTRL4_IQCORR_ENABLE
);
1075 ahp
->ah_bIQCalibration
= IQ_CAL_DONE
;
1076 ichan
->iqCalValid
= AH_TRUE
;
1077 ichan
->iCoff
= iCoff
;
1078 ichan
->qCoff
= qCoff
;
1080 } else if (!IS_CHAN_B(chan
) && ahp
->ah_bIQCalibration
== IQ_CAL_DONE
&&
1081 !ichan
->iqCalValid
) {
1083 * Start IQ calibration if configured channel has changed.
1084 * Use a magic number of 15 based on default value.
1086 OS_REG_RMW_FIELD(ah
, AR_PHY_TIMING_CTRL4
,
1087 AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX
,
1088 INIT_IQCAL_LOG_COUNT_MAX
);
1089 OS_REG_SET_BIT(ah
, AR_PHY_TIMING_CTRL4
,
1090 AR_PHY_TIMING_CTRL4_DO_IQCAL
);
1091 ahp
->ah_bIQCalibration
= IQ_CAL_RUNNING
;
1096 /* Check noise floor results */
1097 ar5212GetNf(ah
, ichan
);
1099 if ((ichan
->channelFlags
& CHANNEL_CW_INT
) == 0) {
1100 /* Perform cal for 5Ghz channels and any OFDM on 5112 */
1101 if (IS_CHAN_5GHZ(chan
) ||
1102 (IS_RAD5112(ah
) && IS_CHAN_OFDM(chan
)))
1103 ar5212RequestRfgain(ah
);
1105 /* report up and clear internal state */
1106 chan
->channelFlags
|= CHANNEL_CW_INT
;
1107 ichan
->channelFlags
&= ~CHANNEL_CW_INT
;
1110 RESTORE_CCK(ah
, ichan
, ichan_isBmode
);
1111 RESTORE_CCK(ah
, chan
, isBmode
);
1118 ar5212PerCalibration(struct ath_hal
*ah
, HAL_CHANNEL
*chan
, HAL_BOOL
*isIQdone
)
1120 return ar5212PerCalibrationN(ah
, chan
, 0x1, AH_TRUE
, isIQdone
);
1124 ar5212ResetCalValid(struct ath_hal
*ah
, HAL_CHANNEL
*chan
)
1131 * Write the given reset bit mask into the reset register
1134 ar5212SetResetReg(struct ath_hal
*ah
, uint32_t resetMask
)
1136 uint32_t mask
= resetMask
? resetMask
: ~0;
1139 /* XXX ar5212MacStop & co. */
1142 resetMask
&= ~AR_RC_PCI
;
1145 (void) OS_REG_READ(ah
, AR_RXDP
);/* flush any pending MMR writes */
1146 OS_REG_WRITE(ah
, AR_RC
, resetMask
);
1147 OS_DELAY(15); /* need to wait at least 128 clocks
1148 when reseting PCI before read */
1149 mask
&= (AR_RC_MAC
| AR_RC_BB
);
1150 resetMask
&= (AR_RC_MAC
| AR_RC_BB
);
1151 rt
= ath_hal_wait(ah
, AR_RC
, mask
, resetMask
);
1152 if ((resetMask
& AR_RC_MAC
) == 0) {
1153 if (isBigEndian()) {
1155 * Set CFG, little-endian for register
1156 * and descriptor accesses.
1158 mask
= INIT_CONFIG_STATUS
| AR_CFG_SWRD
| AR_CFG_SWRG
;
1159 #ifndef AH_NEED_DESC_SWAP
1160 mask
|= AR_CFG_SWTD
;
1162 OS_REG_WRITE(ah
, AR_CFG
, LE_READ_4(&mask
));
1164 OS_REG_WRITE(ah
, AR_CFG
, INIT_CONFIG_STATUS
);
1165 if (ar5212SetPowerMode(ah
, HAL_PM_AWAKE
, AH_TRUE
))
1166 (void) OS_REG_READ(ah
, AR_ISR_RAC
);
1169 /* track PHY power state so we don't try to r/w BB registers */
1170 AH5212(ah
)->ah_phyPowerOn
= ((resetMask
& AR_RC_BB
) == 0);
1175 ar5212GetNoiseFloor(struct ath_hal
*ah
)
1177 int16_t nf
= (OS_REG_READ(ah
, AR_PHY(25)) >> 19) & 0x1ff;
1179 nf
= 0 - ((nf
^ 0x1ff) + 1);
1184 getNoiseFloorThresh(struct ath_hal
*ah
, const HAL_CHANNEL_INTERNAL
*chan
,
1187 const HAL_EEPROM
*ee
= AH_PRIVATE(ah
)->ah_eeprom
;
1189 HALASSERT(ah
->ah_magic
== AR5212_MAGIC
);
1191 switch (chan
->channelFlags
& CHANNEL_ALL_NOTURBO
) {
1193 *nft
= ee
->ee_noiseFloorThresh
[headerInfo11A
];
1196 *nft
= ee
->ee_noiseFloorThresh
[headerInfo11B
];
1199 *nft
= ee
->ee_noiseFloorThresh
[headerInfo11G
];
1202 HALDEBUG(ah
, HAL_DEBUG_ANY
, "%s: invalid channel flags 0x%x\n",
1203 __func__
, chan
->channelFlags
);
1210 * Setup the noise floor cal history buffer.
1213 ar5212InitNfCalHistBuffer(struct ath_hal
*ah
)
1215 struct ath_hal_5212
*ahp
= AH5212(ah
);
1218 ahp
->ah_nfCalHist
.first_run
= 1;
1219 ahp
->ah_nfCalHist
.currIndex
= 0;
1220 ahp
->ah_nfCalHist
.privNF
= AR5212_CCA_MAX_GOOD_VALUE
;
1221 ahp
->ah_nfCalHist
.invalidNFcount
= AR512_NF_CAL_HIST_MAX
;
1222 for (i
= 0; i
< AR512_NF_CAL_HIST_MAX
; i
++)
1223 ahp
->ah_nfCalHist
.nfCalBuffer
[i
] = AR5212_CCA_MAX_GOOD_VALUE
;
1227 * Add a noise floor value to the ring buffer.
1229 static __inline
void
1230 updateNFHistBuff(struct ar5212NfCalHist
*h
, int16_t nf
)
1232 h
->nfCalBuffer
[h
->currIndex
] = nf
;
1233 if (++h
->currIndex
>= AR512_NF_CAL_HIST_MAX
)
1238 * Return the median noise floor value in the ring buffer.
1241 ar5212GetNfHistMid(const int16_t calData
[AR512_NF_CAL_HIST_MAX
])
1243 int16_t sort
[AR512_NF_CAL_HIST_MAX
];
1246 OS_MEMCPY(sort
, calData
, AR512_NF_CAL_HIST_MAX
*sizeof(int16_t));
1247 for (i
= 0; i
< AR512_NF_CAL_HIST_MAX
-1; i
++) {
1248 for (j
= 1; j
< AR512_NF_CAL_HIST_MAX
-i
; j
++) {
1249 if (sort
[j
] > sort
[j
-1]) {
1250 int16_t nf
= sort
[j
];
1251 sort
[j
] = sort
[j
-1];
1256 return sort
[(AR512_NF_CAL_HIST_MAX
-1)>>1];
1260 * Read the NF and check it against the noise floor threshhold
1263 ar5212GetNf(struct ath_hal
*ah
, HAL_CHANNEL_INTERNAL
*chan
)
1265 struct ath_hal_5212
*ahp
= AH5212(ah
);
1266 struct ar5212NfCalHist
*h
= &ahp
->ah_nfCalHist
;
1267 int16_t nf
, nfThresh
;
1270 if (OS_REG_READ(ah
, AR_PHY_AGC_CONTROL
) & AR_PHY_AGC_CONTROL_NF
) {
1271 HALDEBUG(ah
, HAL_DEBUG_ANY
,
1272 "%s: NF did not complete in calibration window\n", __func__
);
1273 chan
->rawNoiseFloor
= h
->privNF
; /* most recent value */
1274 return chan
->rawNoiseFloor
;
1278 * Finished NF cal, check against threshold.
1280 nf
= ar5212GetNoiseFloor(ah
);
1281 if (getNoiseFloorThresh(ah
, chan
, &nfThresh
)) {
1282 if (nf
> nfThresh
) {
1283 HALDEBUG(ah
, HAL_DEBUG_ANY
,
1284 "%s: noise floor failed detected; detected %u, "
1285 "threshold %u\n", __func__
, nf
, nfThresh
);
1287 * NB: Don't discriminate 2.4 vs 5Ghz, if this
1288 * happens it indicates a problem regardless
1291 chan
->channelFlags
|= CHANNEL_CW_INT
;
1298 * Pass through histogram and write median value as
1299 * calculated from the accrued window. We require a
1300 * full window of in-range values to be seen before we
1301 * start using the history.
1303 updateNFHistBuff(h
, nf
);
1305 if (nf
< AR5212_CCA_MIN_BAD_VALUE
||
1306 nf
> AR5212_CCA_MAX_HIGH_VALUE
) {
1307 nf
= AR5212_CCA_MAX_GOOD_VALUE
;
1308 h
->invalidNFcount
= AR512_NF_CAL_HIST_MAX
;
1309 } else if (--(h
->invalidNFcount
) == 0) {
1311 h
->privNF
= nf
= ar5212GetNfHistMid(h
->nfCalBuffer
);
1313 nf
= AR5212_CCA_MAX_GOOD_VALUE
;
1316 h
->privNF
= nf
= ar5212GetNfHistMid(h
->nfCalBuffer
);
1319 val
= OS_REG_READ(ah
, AR_PHY(25));
1321 val
|= (((uint32_t)nf
<< 1) & 0x1FF);
1322 OS_REG_WRITE(ah
, AR_PHY(25), val
);
1323 OS_REG_CLR_BIT(ah
, AR_PHY_AGC_CONTROL
, AR_PHY_AGC_CONTROL_ENABLE_NF
);
1324 OS_REG_CLR_BIT(ah
, AR_PHY_AGC_CONTROL
, AR_PHY_AGC_CONTROL_NO_UPDATE_NF
);
1325 OS_REG_SET_BIT(ah
, AR_PHY_AGC_CONTROL
, AR_PHY_AGC_CONTROL_NF
);
1327 if (!ath_hal_wait(ah
, AR_PHY_AGC_CONTROL
, AR_PHY_AGC_CONTROL_NF
, 0)) {
1329 ath_hal_printf(ah
, "%s: AGC not ready AGC_CONTROL 0x%x\n",
1330 __func__
, OS_REG_READ(ah
, AR_PHY_AGC_CONTROL
));
1335 * Now load a high maxCCAPower value again so that we're
1336 * not capped by the median we just loaded
1339 val
|= (((uint32_t)(-50) << 1) & 0x1FF);
1340 OS_REG_WRITE(ah
, AR_PHY(25), val
);
1341 OS_REG_SET_BIT(ah
, AR_PHY_AGC_CONTROL
, AR_PHY_AGC_CONTROL_ENABLE_NF
);
1342 OS_REG_SET_BIT(ah
, AR_PHY_AGC_CONTROL
, AR_PHY_AGC_CONTROL_NO_UPDATE_NF
);
1343 OS_REG_SET_BIT(ah
, AR_PHY_AGC_CONTROL
, AR_PHY_AGC_CONTROL_NF
);
1345 return (chan
->rawNoiseFloor
= nf
);
1349 * Set up compression configuration registers
1352 ar5212SetCompRegs(struct ath_hal
*ah
)
1354 struct ath_hal_5212
*ahp
= AH5212(ah
);
1357 /* Check if h/w supports compression */
1358 if (!AH_PRIVATE(ah
)->ah_caps
.halCompressSupport
)
1361 OS_REG_WRITE(ah
, AR_DCCFG
, 1);
1363 OS_REG_WRITE(ah
, AR_CCFG
,
1364 (AR_COMPRESSION_WINDOW_SIZE
>> 8) & AR_CCFG_WIN_M
);
1366 OS_REG_WRITE(ah
, AR_CCFG
,
1367 OS_REG_READ(ah
, AR_CCFG
) | AR_CCFG_MIB_INT_EN
);
1368 OS_REG_WRITE(ah
, AR_CCUCFG
,
1369 AR_CCUCFG_RESET_VAL
| AR_CCUCFG_CATCHUP_EN
);
1371 OS_REG_WRITE(ah
, AR_CPCOVF
, 0);
1373 /* reset decompression mask */
1374 for (i
= 0; i
< HAL_DECOMP_MASK_SIZE
; i
++) {
1375 OS_REG_WRITE(ah
, AR_DCM_A
, i
);
1376 OS_REG_WRITE(ah
, AR_DCM_D
, ahp
->ah_decompMask
[i
]);
1381 ar5212SetAntennaSwitchInternal(struct ath_hal
*ah
, HAL_ANT_SETTING settings
,
1382 const HAL_CHANNEL_INTERNAL
*chan
)
1384 #define ANT_SWITCH_TABLE1 AR_PHY(88)
1385 #define ANT_SWITCH_TABLE2 AR_PHY(89)
1386 struct ath_hal_5212
*ahp
= AH5212(ah
);
1387 const HAL_EEPROM
*ee
= AH_PRIVATE(ah
)->ah_eeprom
;
1388 uint32_t antSwitchA
, antSwitchB
;
1390 HAL_BOOL isBmode
= AH_FALSE
;
1391 /* NB: need local copy for SAVE/RESTORE 'cuz chan is const */
1392 HAL_CHANNEL_INTERNAL ichan
= *chan
;
1394 HALASSERT(ah
->ah_magic
== AR5212_MAGIC
);
1395 HALASSERT(ahp
->ah_phyPowerOn
);
1397 SAVE_CCK(ah
, &ichan
, isBmode
);
1398 switch (ichan
.channelFlags
& CHANNEL_ALL_NOTURBO
) {
1399 case CHANNEL_A
: ix
= 0; break;
1400 case CHANNEL_B
: ix
= 1; break;
1401 case CHANNEL_PUREG
: ix
= 2; break;
1403 HALDEBUG(ah
, HAL_DEBUG_ANY
, "%s: invalid channel flags 0x%x\n",
1404 __func__
, ichan
.channelFlags
);
1405 RESTORE_CCK(ah
, &ichan
, isBmode
);
1408 RESTORE_CCK(ah
, &ichan
, isBmode
);
1410 antSwitchA
= ee
->ee_antennaControl
[1][ix
]
1411 | (ee
->ee_antennaControl
[2][ix
] << 6)
1412 | (ee
->ee_antennaControl
[3][ix
] << 12)
1413 | (ee
->ee_antennaControl
[4][ix
] << 18)
1414 | (ee
->ee_antennaControl
[5][ix
] << 24)
1416 antSwitchB
= ee
->ee_antennaControl
[6][ix
]
1417 | (ee
->ee_antennaControl
[7][ix
] << 6)
1418 | (ee
->ee_antennaControl
[8][ix
] << 12)
1419 | (ee
->ee_antennaControl
[9][ix
] << 18)
1420 | (ee
->ee_antennaControl
[10][ix
] << 24)
1423 * For fixed antenna, give the same setting for both switch banks
1426 case HAL_ANT_FIXED_A
:
1427 antSwitchB
= antSwitchA
;
1429 case HAL_ANT_FIXED_B
:
1430 antSwitchA
= antSwitchB
;
1432 case HAL_ANT_VARIABLE
:
1435 HALDEBUG(ah
, HAL_DEBUG_ANY
, "%s: bad antenna setting %u\n",
1436 __func__
, settings
);
1439 if (antSwitchB
== antSwitchA
) {
1440 HALDEBUG(ah
, HAL_DEBUG_RFPARAM
,
1441 "%s: Setting fast diversity off.\n", __func__
);
1442 OS_REG_CLR_BIT(ah
,AR_PHY_CCK_DETECT
,
1443 AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV
);
1444 ahp
->ah_diversity
= AH_FALSE
;
1446 HALDEBUG(ah
, HAL_DEBUG_RFPARAM
,
1447 "%s: Setting fast diversity on.\n", __func__
);
1448 OS_REG_SET_BIT(ah
,AR_PHY_CCK_DETECT
,
1449 AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV
);
1450 ahp
->ah_diversity
= AH_TRUE
;
1452 ahp
->ah_antControl
= settings
;
1454 OS_REG_WRITE(ah
, ANT_SWITCH_TABLE1
, antSwitchA
);
1455 OS_REG_WRITE(ah
, ANT_SWITCH_TABLE2
, antSwitchB
);
1458 #undef ANT_SWITCH_TABLE2
1459 #undef ANT_SWITCH_TABLE1
1463 ar5212IsSpurChannel(struct ath_hal
*ah
, HAL_CHANNEL
*chan
)
1465 uint32_t clockFreq
=
1466 ((IS_5413(ah
) || IS_RAD5112_ANY(ah
) || IS_2417(ah
)) ? 40 : 32);
1467 return ( ((chan
->channel
% clockFreq
) != 0)
1468 && (((chan
->channel
% clockFreq
) < 10)
1469 || (((chan
->channel
) % clockFreq
) > 22)) );
1473 * Read EEPROM header info and program the device for correct operation
1474 * given the channel value.
1477 ar5212SetBoardValues(struct ath_hal
*ah
, HAL_CHANNEL_INTERNAL
*chan
)
1479 #define NO_FALSE_DETECT_BACKOFF 2
1480 #define CB22_FALSE_DETECT_BACKOFF 6
1481 #define AR_PHY_BIS(_ah, _reg, _mask, _val) \
1482 OS_REG_WRITE(_ah, AR_PHY(_reg), \
1483 (OS_REG_READ(_ah, AR_PHY(_reg)) & _mask) | (_val));
1484 struct ath_hal_5212
*ahp
= AH5212(ah
);
1485 const HAL_EEPROM
*ee
= AH_PRIVATE(ah
)->ah_eeprom
;
1486 int arrayMode
, falseDectectBackoff
;
1487 int is2GHz
= IS_CHAN_2GHZ(chan
);
1488 int8_t adcDesiredSize
, pgaDesiredSize
;
1489 uint16_t switchSettling
, txrxAtten
, rxtxMargin
;
1492 HALASSERT(ah
->ah_magic
== AR5212_MAGIC
);
1494 switch (chan
->channelFlags
& CHANNEL_ALL
) {
1497 arrayMode
= headerInfo11A
;
1498 if (!IS_RAD5112_ANY(ah
) && !IS_2413(ah
) && !IS_5413(ah
))
1499 OS_REG_RMW_FIELD(ah
, AR_PHY_FRAME_CTL
,
1500 AR_PHY_FRAME_CTL_TX_CLIP
,
1501 ahp
->ah_gainValues
.currStep
->paramVal
[GP_TXCLIP
]);
1504 arrayMode
= headerInfo11B
;
1508 arrayMode
= headerInfo11G
;
1511 HALDEBUG(ah
, HAL_DEBUG_ANY
, "%s: invalid channel flags 0x%x\n",
1512 __func__
, chan
->channelFlags
);
1516 /* Set the antenna register(s) correctly for the chip revision */
1517 AR_PHY_BIS(ah
, 68, 0xFFFFFC06,
1518 (ee
->ee_antennaControl
[0][arrayMode
] << 4) | 0x1);
1520 ar5212SetAntennaSwitchInternal(ah
, ahp
->ah_antControl
, chan
);
1522 /* Set the Noise Floor Thresh on ar5211 devices */
1523 OS_REG_WRITE(ah
, AR_PHY(90),
1524 (ee
->ee_noiseFloorThresh
[arrayMode
] & 0x1FF)
1527 if (ee
->ee_version
>= AR_EEPROM_VER5_0
&& IS_CHAN_TURBO(chan
)) {
1528 switchSettling
= ee
->ee_switchSettlingTurbo
[is2GHz
];
1529 adcDesiredSize
= ee
->ee_adcDesiredSizeTurbo
[is2GHz
];
1530 pgaDesiredSize
= ee
->ee_pgaDesiredSizeTurbo
[is2GHz
];
1531 txrxAtten
= ee
->ee_txrxAttenTurbo
[is2GHz
];
1532 rxtxMargin
= ee
->ee_rxtxMarginTurbo
[is2GHz
];
1534 switchSettling
= ee
->ee_switchSettling
[arrayMode
];
1535 adcDesiredSize
= ee
->ee_adcDesiredSize
[arrayMode
];
1536 pgaDesiredSize
= ee
->ee_pgaDesiredSize
[is2GHz
];
1537 txrxAtten
= ee
->ee_txrxAtten
[is2GHz
];
1538 rxtxMargin
= ee
->ee_rxtxMargin
[is2GHz
];
1541 OS_REG_RMW_FIELD(ah
, AR_PHY_SETTLING
,
1542 AR_PHY_SETTLING_SWITCH
, switchSettling
);
1543 OS_REG_RMW_FIELD(ah
, AR_PHY_DESIRED_SZ
,
1544 AR_PHY_DESIRED_SZ_ADC
, adcDesiredSize
);
1545 OS_REG_RMW_FIELD(ah
, AR_PHY_DESIRED_SZ
,
1546 AR_PHY_DESIRED_SZ_PGA
, pgaDesiredSize
);
1547 OS_REG_RMW_FIELD(ah
, AR_PHY_RXGAIN
,
1548 AR_PHY_RXGAIN_TXRX_ATTEN
, txrxAtten
);
1549 OS_REG_WRITE(ah
, AR_PHY(13),
1550 (ee
->ee_txEndToXPAOff
[arrayMode
] << 24)
1551 | (ee
->ee_txEndToXPAOff
[arrayMode
] << 16)
1552 | (ee
->ee_txFrameToXPAOn
[arrayMode
] << 8)
1553 | ee
->ee_txFrameToXPAOn
[arrayMode
]);
1554 AR_PHY_BIS(ah
, 10, 0xFFFF00FF,
1555 ee
->ee_txEndToXLNAOn
[arrayMode
] << 8);
1556 AR_PHY_BIS(ah
, 25, 0xFFF80FFF,
1557 (ee
->ee_thresh62
[arrayMode
] << 12) & 0x7F000);
1560 * False detect backoff - suspected 32 MHz spur causes false
1561 * detects in OFDM, causing Tx Hangs. Decrease weak signal
1562 * sensitivity for this card.
1564 falseDectectBackoff
= NO_FALSE_DETECT_BACKOFF
;
1565 if (ee
->ee_version
< AR_EEPROM_VER3_3
) {
1566 /* XXX magic number */
1567 if (AH_PRIVATE(ah
)->ah_subvendorid
== 0x1022 &&
1569 falseDectectBackoff
+= CB22_FALSE_DETECT_BACKOFF
;
1571 if (ar5212IsSpurChannel(ah
, (HAL_CHANNEL
*)chan
)) {
1572 falseDectectBackoff
+= ee
->ee_falseDetectBackoff
[arrayMode
];
1575 AR_PHY_BIS(ah
, 73, 0xFFFFFF01, (falseDectectBackoff
<< 1) & 0xFE);
1577 if (chan
->iqCalValid
) {
1578 iCoff
= chan
->iCoff
;
1579 qCoff
= chan
->qCoff
;
1581 iCoff
= ee
->ee_iqCalI
[is2GHz
];
1582 qCoff
= ee
->ee_iqCalQ
[is2GHz
];
1585 /* write previous IQ results */
1586 OS_REG_RMW_FIELD(ah
, AR_PHY_TIMING_CTRL4
,
1587 AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF
, iCoff
);
1588 OS_REG_RMW_FIELD(ah
, AR_PHY_TIMING_CTRL4
,
1589 AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF
, qCoff
);
1590 OS_REG_SET_BIT(ah
, AR_PHY_TIMING_CTRL4
,
1591 AR_PHY_TIMING_CTRL4_IQCORR_ENABLE
);
1593 if (ee
->ee_version
>= AR_EEPROM_VER4_1
) {
1594 if (!IS_CHAN_108G(chan
) || ee
->ee_version
>= AR_EEPROM_VER5_0
)
1595 OS_REG_RMW_FIELD(ah
, AR_PHY_GAIN_2GHZ
,
1596 AR_PHY_GAIN_2GHZ_RXTX_MARGIN
, rxtxMargin
);
1598 if (ee
->ee_version
>= AR_EEPROM_VER5_1
) {
1599 /* for now always disabled */
1600 OS_REG_WRITE(ah
, AR_PHY_HEAVY_CLIP_ENABLE
, 0);
1605 #undef NO_FALSE_DETECT_BACKOFF
1606 #undef CB22_FALSE_DETECT_BACKOFF
1610 * Apply Spur Immunity to Boards that require it.
1611 * Applies only to OFDM RX operation.
1615 ar5212SetSpurMitigation(struct ath_hal
*ah
, HAL_CHANNEL_INTERNAL
*ichan
)
1617 uint32_t pilotMask
[2] = {0, 0}, binMagMask
[4] = {0, 0, 0 , 0};
1618 uint16_t i
, finalSpur
, curChanAsSpur
, binWidth
= 0, spurDetectWidth
, spurChan
;
1619 int32_t spurDeltaPhase
= 0, spurFreqSd
= 0, spurOffset
, binOffsetNumT16
, curBinOffset
;
1620 int16_t numBinOffsets
;
1621 static const uint16_t magMapFor4
[4] = {1, 2, 2, 1};
1622 static const uint16_t magMapFor3
[3] = {1, 2, 1};
1623 const uint16_t *pMagMap
;
1624 HAL_BOOL is2GHz
= IS_CHAN_2GHZ(ichan
);
1627 #define CHAN_TO_SPUR(_f, _freq) ( ((_freq) - ((_f) ? 2300 : 4900)) * 10 )
1629 HALDEBUG(ah
, HAL_DEBUG_RFPARAM
, "%s: no spur mitigation\n",
1634 curChanAsSpur
= CHAN_TO_SPUR(is2GHz
, ichan
->channel
);
1636 if (ichan
->mainSpur
) {
1637 /* Pull out the saved spur value */
1638 finalSpur
= ichan
->mainSpur
;
1641 * Check if spur immunity should be performed for this channel
1642 * Should only be performed once per channel and then saved
1644 finalSpur
= AR_NO_SPUR
;
1645 spurDetectWidth
= HAL_SPUR_CHAN_WIDTH
;
1646 if (IS_CHAN_TURBO(ichan
))
1647 spurDetectWidth
*= 2;
1649 /* Decide if any spur affects the current channel */
1650 for (i
= 0; i
< AR_EEPROM_MODAL_SPURS
; i
++) {
1651 spurChan
= ath_hal_getSpurChan(ah
, i
, is2GHz
);
1652 if (spurChan
== AR_NO_SPUR
) {
1655 if ((curChanAsSpur
- spurDetectWidth
<= (spurChan
& HAL_SPUR_VAL_MASK
)) &&
1656 (curChanAsSpur
+ spurDetectWidth
>= (spurChan
& HAL_SPUR_VAL_MASK
))) {
1657 finalSpur
= spurChan
& HAL_SPUR_VAL_MASK
;
1661 /* Save detected spur (or no spur) for this channel */
1662 ichan
->mainSpur
= finalSpur
;
1665 /* Write spur immunity data */
1666 if (finalSpur
== AR_NO_SPUR
) {
1667 /* Disable Spur Immunity Regs if they appear set */
1668 if (OS_REG_READ(ah
, AR_PHY_TIMING_CTRL4
) & AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER
) {
1669 /* Clear Spur Delta Phase, Spur Freq, and enable bits */
1670 OS_REG_RMW_FIELD(ah
, AR_PHY_MASK_CTL
, AR_PHY_MASK_CTL_RATE
, 0);
1671 val
= OS_REG_READ(ah
, AR_PHY_TIMING_CTRL4
);
1672 val
&= ~(AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER
|
1673 AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK
|
1674 AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK
);
1675 OS_REG_WRITE(ah
, AR_PHY_MASK_CTL
, val
);
1676 OS_REG_WRITE(ah
, AR_PHY_TIMING11
, 0);
1678 /* Clear pilot masks */
1679 OS_REG_WRITE(ah
, AR_PHY_TIMING7
, 0);
1680 OS_REG_RMW_FIELD(ah
, AR_PHY_TIMING8
, AR_PHY_TIMING8_PILOT_MASK_2
, 0);
1681 OS_REG_WRITE(ah
, AR_PHY_TIMING9
, 0);
1682 OS_REG_RMW_FIELD(ah
, AR_PHY_TIMING10
, AR_PHY_TIMING10_PILOT_MASK_2
, 0);
1684 /* Clear magnitude masks */
1685 OS_REG_WRITE(ah
, AR_PHY_BIN_MASK_1
, 0);
1686 OS_REG_WRITE(ah
, AR_PHY_BIN_MASK_2
, 0);
1687 OS_REG_WRITE(ah
, AR_PHY_BIN_MASK_3
, 0);
1688 OS_REG_RMW_FIELD(ah
, AR_PHY_MASK_CTL
, AR_PHY_MASK_CTL_MASK_4
, 0);
1689 OS_REG_WRITE(ah
, AR_PHY_BIN_MASK2_1
, 0);
1690 OS_REG_WRITE(ah
, AR_PHY_BIN_MASK2_2
, 0);
1691 OS_REG_WRITE(ah
, AR_PHY_BIN_MASK2_3
, 0);
1692 OS_REG_RMW_FIELD(ah
, AR_PHY_BIN_MASK2_4
, AR_PHY_BIN_MASK2_4_MASK_4
, 0);
1695 spurOffset
= finalSpur
- curChanAsSpur
;
1697 * Spur calculations:
1698 * spurDeltaPhase is (spurOffsetIn100KHz / chipFrequencyIn100KHz) << 21
1699 * spurFreqSd is (spurOffsetIn100KHz / sampleFrequencyIn100KHz) << 11
1701 switch (ichan
->channelFlags
& CHANNEL_ALL
) {
1702 case CHANNEL_A
: /* Chip Frequency & sampleFrequency are 40 MHz */
1703 spurDeltaPhase
= (spurOffset
<< 17) / 25;
1704 spurFreqSd
= spurDeltaPhase
>> 10;
1705 binWidth
= HAL_BIN_WIDTH_BASE_100HZ
;
1707 case CHANNEL_G
: /* Chip Frequency is 44MHz, sampleFrequency is 40 MHz */
1708 spurFreqSd
= (spurOffset
<< 8) / 55;
1709 spurDeltaPhase
= (spurOffset
<< 17) / 25;
1710 binWidth
= HAL_BIN_WIDTH_BASE_100HZ
;
1712 case CHANNEL_T
: /* Chip Frequency & sampleFrequency are 80 MHz */
1714 spurDeltaPhase
= (spurOffset
<< 16) / 25;
1715 spurFreqSd
= spurDeltaPhase
>> 10;
1716 binWidth
= HAL_BIN_WIDTH_TURBO_100HZ
;
1720 /* Compute Pilot Mask */
1721 binOffsetNumT16
= ((spurOffset
* 1000) << 4) / binWidth
;
1722 /* The spur is on a bin if it's remainder at times 16 is 0 */
1723 if (binOffsetNumT16
& 0xF) {
1725 pMagMap
= magMapFor4
;
1728 pMagMap
= magMapFor3
;
1730 for (i
= 0; i
< numBinOffsets
; i
++) {
1731 if ((binOffsetNumT16
>> 4) > HAL_MAX_BINS_ALLOWED
) {
1732 HALDEBUG(ah
, HAL_DEBUG_ANY
,
1733 "Too man bins in spur mitigation\n");
1737 /* Get Pilot Mask values */
1738 curBinOffset
= (binOffsetNumT16
>> 4) + i
+ 25;
1739 if ((curBinOffset
>= 0) && (curBinOffset
<= 32)) {
1740 if (curBinOffset
<= 25)
1741 pilotMask
[0] |= 1 << curBinOffset
;
1742 else if (curBinOffset
>= 27)
1743 pilotMask
[0] |= 1 << (curBinOffset
- 1);
1744 } else if ((curBinOffset
>= 33) && (curBinOffset
<= 52))
1745 pilotMask
[1] |= 1 << (curBinOffset
- 33);
1747 /* Get viterbi values */
1748 if ((curBinOffset
>= -1) && (curBinOffset
<= 14))
1749 binMagMask
[0] |= pMagMap
[i
] << (curBinOffset
+ 1) * 2;
1750 else if ((curBinOffset
>= 15) && (curBinOffset
<= 30))
1751 binMagMask
[1] |= pMagMap
[i
] << (curBinOffset
- 15) * 2;
1752 else if ((curBinOffset
>= 31) && (curBinOffset
<= 46))
1753 binMagMask
[2] |= pMagMap
[i
] << (curBinOffset
-31) * 2;
1754 else if((curBinOffset
>= 47) && (curBinOffset
<= 53))
1755 binMagMask
[3] |= pMagMap
[i
] << (curBinOffset
-47) * 2;
1758 /* Write Spur Delta Phase, Spur Freq, and enable bits */
1759 OS_REG_RMW_FIELD(ah
, AR_PHY_MASK_CTL
, AR_PHY_MASK_CTL_RATE
, 0xFF);
1760 val
= OS_REG_READ(ah
, AR_PHY_TIMING_CTRL4
);
1761 val
|= (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER
|
1762 AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK
|
1763 AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK
);
1764 OS_REG_WRITE(ah
, AR_PHY_TIMING_CTRL4
, val
);
1765 OS_REG_WRITE(ah
, AR_PHY_TIMING11
, AR_PHY_TIMING11_USE_SPUR_IN_AGC
|
1766 SM(spurFreqSd
, AR_PHY_TIMING11_SPUR_FREQ_SD
) |
1767 SM(spurDeltaPhase
, AR_PHY_TIMING11_SPUR_DELTA_PHASE
));
1769 /* Write pilot masks */
1770 OS_REG_WRITE(ah
, AR_PHY_TIMING7
, pilotMask
[0]);
1771 OS_REG_RMW_FIELD(ah
, AR_PHY_TIMING8
, AR_PHY_TIMING8_PILOT_MASK_2
, pilotMask
[1]);
1772 OS_REG_WRITE(ah
, AR_PHY_TIMING9
, pilotMask
[0]);
1773 OS_REG_RMW_FIELD(ah
, AR_PHY_TIMING10
, AR_PHY_TIMING10_PILOT_MASK_2
, pilotMask
[1]);
1775 /* Write magnitude masks */
1776 OS_REG_WRITE(ah
, AR_PHY_BIN_MASK_1
, binMagMask
[0]);
1777 OS_REG_WRITE(ah
, AR_PHY_BIN_MASK_2
, binMagMask
[1]);
1778 OS_REG_WRITE(ah
, AR_PHY_BIN_MASK_3
, binMagMask
[2]);
1779 OS_REG_RMW_FIELD(ah
, AR_PHY_MASK_CTL
, AR_PHY_MASK_CTL_MASK_4
, binMagMask
[3]);
1780 OS_REG_WRITE(ah
, AR_PHY_BIN_MASK2_1
, binMagMask
[0]);
1781 OS_REG_WRITE(ah
, AR_PHY_BIN_MASK2_2
, binMagMask
[1]);
1782 OS_REG_WRITE(ah
, AR_PHY_BIN_MASK2_3
, binMagMask
[2]);
1783 OS_REG_RMW_FIELD(ah
, AR_PHY_BIN_MASK2_4
, AR_PHY_BIN_MASK2_4_MASK_4
, binMagMask
[3]);
1790 * Delta slope coefficient computation.
1791 * Required for OFDM operation.
1794 ar5212SetDeltaSlope(struct ath_hal
*ah
, HAL_CHANNEL
*chan
)
1796 #define COEF_SCALE_S 24
1797 #define INIT_CLOCKMHZSCALED 0x64000000
1798 unsigned long coef_scaled
, coef_exp
, coef_man
, ds_coef_exp
, ds_coef_man
;
1799 unsigned long clockMhzScaled
= INIT_CLOCKMHZSCALED
;
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 coef_scaled
= clockMhzScaled
/ chan
->channel
;
1818 * ALGO -> coef_exp = 14-floor(log2(coef));
1819 * floor(log2(x)) is the highest set bit position
1821 for (coef_exp
= 31; coef_exp
> 0; coef_exp
--)
1822 if ((coef_scaled
>> coef_exp
) & 0x1)
1824 /* A coef_exp of 0 is a legal bit position but an unexpected coef_exp */
1825 HALASSERT(coef_exp
);
1826 coef_exp
= 14 - (coef_exp
- COEF_SCALE_S
);
1829 * ALGO -> coef_man = floor(coef* 2^coef_exp+0.5);
1830 * The coefficient is already shifted up for scaling
1832 coef_man
= coef_scaled
+ (1 << (COEF_SCALE_S
- coef_exp
- 1));
1833 ds_coef_man
= coef_man
>> (COEF_SCALE_S
- coef_exp
);
1834 ds_coef_exp
= coef_exp
- 16;
1836 OS_REG_RMW_FIELD(ah
, AR_PHY_TIMING3
,
1837 AR_PHY_TIMING3_DSC_MAN
, ds_coef_man
);
1838 OS_REG_RMW_FIELD(ah
, AR_PHY_TIMING3
,
1839 AR_PHY_TIMING3_DSC_EXP
, ds_coef_exp
);
1840 #undef INIT_CLOCKMHZSCALED
1845 * Set a limit on the overall output power. Used for dynamic
1846 * transmit power control and the like.
1848 * NB: limit is in units of 0.5 dbM.
1851 ar5212SetTxPowerLimit(struct ath_hal
*ah
, uint32_t limit
)
1853 uint16_t dummyXpdGains
[2];
1854 HAL_BOOL ret
, isBmode
= AH_FALSE
;
1856 SAVE_CCK(ah
, AH_PRIVATE(ah
)->ah_curchan
, isBmode
);
1857 AH_PRIVATE(ah
)->ah_powerLimit
= AH_MIN(limit
, MAX_RATE_POWER
);
1858 ret
= ar5212SetTransmitPower(ah
, AH_PRIVATE(ah
)->ah_curchan
,
1860 RESTORE_CCK(ah
, AH_PRIVATE(ah
)->ah_curchan
, isBmode
);
1865 * Set the transmit power in the baseband for the given
1866 * operating channel and mode.
1869 ar5212SetTransmitPower(struct ath_hal
*ah
, HAL_CHANNEL_INTERNAL
*chan
,
1870 uint16_t *rfXpdGain
)
1872 #define POW_OFDM(_r, _s) (((0 & 1)<< ((_s)+6)) | (((_r) & 0x3f) << (_s)))
1873 #define POW_CCK(_r, _s) (((_r) & 0x3f) << (_s))
1874 #define N(a) (sizeof (a) / sizeof (a[0]))
1875 static const uint16_t tpcScaleReductionTable
[5] =
1876 { 0, 3, 6, 9, MAX_RATE_POWER
};
1877 struct ath_hal_5212
*ahp
= AH5212(ah
);
1878 const HAL_EEPROM
*ee
= AH_PRIVATE(ah
)->ah_eeprom
;
1879 int16_t minPower
, maxPower
, tpcInDb
, powerLimit
;
1882 HALASSERT(ah
->ah_magic
== AR5212_MAGIC
);
1884 OS_MEMZERO(ahp
->ah_pcdacTable
, ahp
->ah_pcdacTableSize
);
1885 OS_MEMZERO(ahp
->ah_ratesArray
, sizeof(ahp
->ah_ratesArray
));
1887 powerLimit
= AH_MIN(MAX_RATE_POWER
, AH_PRIVATE(ah
)->ah_powerLimit
);
1888 if (powerLimit
>= MAX_RATE_POWER
|| powerLimit
== 0)
1889 tpcInDb
= tpcScaleReductionTable
[AH_PRIVATE(ah
)->ah_tpScale
];
1892 if (!ar5212SetRateTable(ah
, (HAL_CHANNEL
*) chan
, tpcInDb
, powerLimit
,
1893 AH_TRUE
, &minPower
, &maxPower
)) {
1894 HALDEBUG(ah
, HAL_DEBUG_ANY
, "%s: unable to set rate table\n",
1898 if (!ahp
->ah_rfHal
->setPowerTable(ah
,
1899 &minPower
, &maxPower
, chan
, rfXpdGain
)) {
1900 HALDEBUG(ah
, HAL_DEBUG_ANY
, "%s: unable to set power table\n",
1906 * Adjust XR power/rate up by 2 dB to account for greater peak
1907 * to avg ratio - except in newer avg power designs
1909 if (!IS_2413(ah
) && !IS_5413(ah
))
1910 ahp
->ah_ratesArray
[15] += 4;
1912 * txPowerIndexOffset is set by the SetPowerTable() call -
1913 * adjust the rate table
1915 for (i
= 0; i
< N(ahp
->ah_ratesArray
); i
++) {
1916 ahp
->ah_ratesArray
[i
] += ahp
->ah_txPowerIndexOffset
;
1917 if (ahp
->ah_ratesArray
[i
] > 63)
1918 ahp
->ah_ratesArray
[i
] = 63;
1921 if (ee
->ee_eepMap
< 2) {
1923 * Correct gain deltas for 5212 G operation -
1924 * Removed with revised chipset
1926 if (AH_PRIVATE(ah
)->ah_phyRev
< AR_PHY_CHIP_ID_REV_2
&&
1928 uint16_t cckOfdmPwrDelta
;
1930 if (chan
->channel
== 2484)
1931 cckOfdmPwrDelta
= SCALE_OC_DELTA(
1932 ee
->ee_cckOfdmPwrDelta
-
1933 ee
->ee_scaledCh14FilterCckDelta
);
1935 cckOfdmPwrDelta
= SCALE_OC_DELTA(
1936 ee
->ee_cckOfdmPwrDelta
);
1937 ar5212CorrectGainDelta(ah
, cckOfdmPwrDelta
);
1940 * Finally, write the power values into the
1941 * baseband power table
1943 for (i
= 0; i
< (PWR_TABLE_SIZE
/2); i
++) {
1944 OS_REG_WRITE(ah
, AR_PHY_PCDAC_TX_POWER(i
),
1945 ((((ahp
->ah_pcdacTable
[2*i
+ 1] << 8) | 0xff) & 0xffff) << 16)
1946 | (((ahp
->ah_pcdacTable
[2*i
] << 8) | 0xff) & 0xffff)
1951 /* Write the OFDM power per rate set */
1952 OS_REG_WRITE(ah
, AR_PHY_POWER_TX_RATE1
,
1953 POW_OFDM(ahp
->ah_ratesArray
[3], 24)
1954 | POW_OFDM(ahp
->ah_ratesArray
[2], 16)
1955 | POW_OFDM(ahp
->ah_ratesArray
[1], 8)
1956 | POW_OFDM(ahp
->ah_ratesArray
[0], 0)
1958 OS_REG_WRITE(ah
, AR_PHY_POWER_TX_RATE2
,
1959 POW_OFDM(ahp
->ah_ratesArray
[7], 24)
1960 | POW_OFDM(ahp
->ah_ratesArray
[6], 16)
1961 | POW_OFDM(ahp
->ah_ratesArray
[5], 8)
1962 | POW_OFDM(ahp
->ah_ratesArray
[4], 0)
1965 /* Write the CCK power per rate set */
1966 OS_REG_WRITE(ah
, AR_PHY_POWER_TX_RATE3
,
1967 POW_CCK(ahp
->ah_ratesArray
[10], 24)
1968 | POW_CCK(ahp
->ah_ratesArray
[9], 16)
1969 | POW_CCK(ahp
->ah_ratesArray
[15], 8) /* XR target power */
1970 | POW_CCK(ahp
->ah_ratesArray
[8], 0)
1972 OS_REG_WRITE(ah
, AR_PHY_POWER_TX_RATE4
,
1973 POW_CCK(ahp
->ah_ratesArray
[14], 24)
1974 | POW_CCK(ahp
->ah_ratesArray
[13], 16)
1975 | POW_CCK(ahp
->ah_ratesArray
[12], 8)
1976 | POW_CCK(ahp
->ah_ratesArray
[11], 0)
1980 * Set max power to 30 dBm and, optionally,
1981 * enable TPC in tx descriptors.
1983 OS_REG_WRITE(ah
, AR_PHY_POWER_TX_RATE_MAX
, MAX_RATE_POWER
|
1984 (ahp
->ah_tpcEnabled
? AR_PHY_POWER_TX_RATE_MAX_TPC_ENABLE
: 0));
1993 * Sets the transmit power in the baseband for the given
1994 * operating channel and mode.
1997 ar5212SetRateTable(struct ath_hal
*ah
, HAL_CHANNEL
*chan
,
1998 int16_t tpcScaleReduction
, int16_t powerLimit
, HAL_BOOL commit
,
1999 int16_t *pMinPower
, int16_t *pMaxPower
)
2001 struct ath_hal_5212
*ahp
= AH5212(ah
);
2002 const HAL_EEPROM
*ee
= AH_PRIVATE(ah
)->ah_eeprom
;
2003 uint16_t *rpow
= ahp
->ah_ratesArray
;
2004 uint16_t twiceMaxEdgePower
= MAX_RATE_POWER
;
2005 uint16_t twiceMaxEdgePowerCck
= MAX_RATE_POWER
;
2006 uint16_t twiceMaxRDPower
= MAX_RATE_POWER
;
2009 int8_t twiceAntennaGain
, twiceAntennaReduction
;
2010 const RD_EDGES_POWER
*rep
;
2011 TRGT_POWER_INFO targetPowerOfdm
, targetPowerCck
;
2012 int16_t scaledPower
, maxAvailPower
= 0;
2013 int16_t r13
, r9
, r7
, r0
;
2015 HALASSERT(ah
->ah_magic
== AR5212_MAGIC
);
2017 twiceMaxRDPower
= chan
->maxRegTxPower
* 2;
2018 *pMaxPower
= -MAX_RATE_POWER
;
2019 *pMinPower
= MAX_RATE_POWER
;
2021 /* Get conformance test limit maximum for this channel */
2022 cfgCtl
= ath_hal_getctl(ah
, chan
);
2023 for (i
= 0; i
< ee
->ee_numCtls
; i
++) {
2024 uint16_t twiceMinEdgePower
;
2026 if (ee
->ee_ctl
[i
] == 0)
2028 if (ee
->ee_ctl
[i
] == cfgCtl
||
2029 cfgCtl
== ((ee
->ee_ctl
[i
] & CTL_MODE_M
) | SD_NO_CTL
)) {
2030 rep
= &ee
->ee_rdEdgesPower
[i
* NUM_EDGES
];
2031 twiceMinEdgePower
= ar5212GetMaxEdgePower(chan
->channel
, rep
);
2032 if ((cfgCtl
& ~CTL_MODE_M
) == SD_NO_CTL
) {
2033 /* Find the minimum of all CTL edge powers that apply to this channel */
2034 twiceMaxEdgePower
= AH_MIN(twiceMaxEdgePower
, twiceMinEdgePower
);
2036 twiceMaxEdgePower
= twiceMinEdgePower
;
2042 if (IS_CHAN_G(chan
)) {
2043 /* Check for a CCK CTL for 11G CCK powers */
2044 cfgCtl
= (cfgCtl
& ~CTL_MODE_M
) | CTL_11B
;
2045 for (i
= 0; i
< ee
->ee_numCtls
; i
++) {
2046 uint16_t twiceMinEdgePowerCck
;
2048 if (ee
->ee_ctl
[i
] == 0)
2050 if (ee
->ee_ctl
[i
] == cfgCtl
||
2051 cfgCtl
== ((ee
->ee_ctl
[i
] & CTL_MODE_M
) | SD_NO_CTL
)) {
2052 rep
= &ee
->ee_rdEdgesPower
[i
* NUM_EDGES
];
2053 twiceMinEdgePowerCck
= ar5212GetMaxEdgePower(chan
->channel
, rep
);
2054 if ((cfgCtl
& ~CTL_MODE_M
) == SD_NO_CTL
) {
2055 /* Find the minimum of all CTL edge powers that apply to this channel */
2056 twiceMaxEdgePowerCck
= AH_MIN(twiceMaxEdgePowerCck
, twiceMinEdgePowerCck
);
2058 twiceMaxEdgePowerCck
= twiceMinEdgePowerCck
;
2064 /* Set the 11B cck edge power to the one found before */
2065 twiceMaxEdgePowerCck
= twiceMaxEdgePower
;
2068 /* Get Antenna Gain reduction */
2069 if (IS_CHAN_5GHZ(chan
)) {
2070 ath_hal_eepromGet(ah
, AR_EEP_ANTGAINMAX_5
, &twiceAntennaGain
);
2072 ath_hal_eepromGet(ah
, AR_EEP_ANTGAINMAX_2
, &twiceAntennaGain
);
2074 twiceAntennaReduction
=
2075 ath_hal_getantennareduction(ah
, chan
, twiceAntennaGain
);
2077 if (IS_CHAN_OFDM(chan
)) {
2078 /* Get final OFDM target powers */
2079 if (IS_CHAN_2GHZ(chan
)) {
2080 ar5212GetTargetPowers(ah
, chan
, ee
->ee_trgtPwr_11g
,
2081 ee
->ee_numTargetPwr_11g
, &targetPowerOfdm
);
2083 ar5212GetTargetPowers(ah
, chan
, ee
->ee_trgtPwr_11a
,
2084 ee
->ee_numTargetPwr_11a
, &targetPowerOfdm
);
2087 /* Get Maximum OFDM power */
2088 /* Minimum of target and edge powers */
2089 scaledPower
= AH_MIN(twiceMaxEdgePower
,
2090 twiceMaxRDPower
- twiceAntennaReduction
);
2093 * If turbo is set, reduce power to keep power
2094 * consumption under 2 Watts. Note that we always do
2095 * this unless specially configured. Then we limit
2096 * power only for non-AP operation.
2098 if (IS_CHAN_TURBO(chan
)
2099 #ifdef AH_ENABLE_AP_SUPPORT
2100 && AH_PRIVATE(ah
)->ah_opmode
!= HAL_M_HOSTAP
2104 * If turbo is set, reduce power to keep power
2105 * consumption under 2 Watts
2107 if (ee
->ee_version
>= AR_EEPROM_VER3_1
)
2108 scaledPower
= AH_MIN(scaledPower
,
2109 ee
->ee_turbo2WMaxPower5
);
2111 * EEPROM version 4.0 added an additional
2112 * constraint on 2.4GHz channels.
2114 if (ee
->ee_version
>= AR_EEPROM_VER4_0
&&
2116 scaledPower
= AH_MIN(scaledPower
,
2117 ee
->ee_turbo2WMaxPower2
);
2120 maxAvailPower
= AH_MIN(scaledPower
,
2121 targetPowerOfdm
.twicePwr6_24
);
2123 /* Reduce power by max regulatory domain allowed restrictions */
2124 scaledPower
= maxAvailPower
- (tpcScaleReduction
* 2);
2125 scaledPower
= (scaledPower
< 0) ? 0 : scaledPower
;
2126 scaledPower
= AH_MIN(scaledPower
, powerLimit
);
2129 /* Set OFDM rates 9, 12, 18, 24 */
2130 r0
= rpow
[0] = rpow
[1] = rpow
[2] = rpow
[3] = rpow
[4] = scaledPower
;
2132 /* Set OFDM rates 36, 48, 54, XR */
2133 rpow
[5] = AH_MIN(rpow
[0], targetPowerOfdm
.twicePwr36
);
2134 rpow
[6] = AH_MIN(rpow
[0], targetPowerOfdm
.twicePwr48
);
2135 r7
= rpow
[7] = AH_MIN(rpow
[0], targetPowerOfdm
.twicePwr54
);
2137 if (ee
->ee_version
>= AR_EEPROM_VER4_0
) {
2138 /* Setup XR target power from EEPROM */
2139 rpow
[15] = AH_MIN(scaledPower
, IS_CHAN_2GHZ(chan
) ?
2140 ee
->ee_xrTargetPower2
: ee
->ee_xrTargetPower5
);
2142 /* XR uses 6mb power */
2145 ahp
->ah_ofdmTxPower
= *pMaxPower
;
2149 r7
= AH_MIN(r0
, targetPowerOfdm
.twicePwr54
);
2154 HALDEBUG(ah
, HAL_DEBUG_RFPARAM
,
2155 "%s: MaxRD: %d TurboMax: %d MaxCTL: %d "
2156 "TPC_Reduction %d chan=%d (0x%x) maxAvailPower=%d pwr6_24=%d, maxPower=%d\n",
2157 __func__
, twiceMaxRDPower
, ee
->ee_turbo2WMaxPower5
,
2158 twiceMaxEdgePower
, tpcScaleReduction
* 2,
2159 chan
->channel
, chan
->channelFlags
,
2160 maxAvailPower
, targetPowerOfdm
.twicePwr6_24
, *pMaxPower
);
2163 if (IS_CHAN_CCK(chan
) || IS_CHAN_G(chan
)) {
2164 /* Get final CCK target powers */
2165 ar5212GetTargetPowers(ah
, chan
, ee
->ee_trgtPwr_11b
,
2166 ee
->ee_numTargetPwr_11b
, &targetPowerCck
);
2168 /* Reduce power by max regulatory domain allowed restrictions */
2169 scaledPower
= AH_MIN(twiceMaxEdgePowerCck
,
2170 twiceMaxRDPower
- twiceAntennaReduction
);
2171 if (maxAvailPower
< AH_MIN(scaledPower
, targetPowerCck
.twicePwr6_24
))
2172 maxAvailPower
= AH_MIN(scaledPower
, targetPowerCck
.twicePwr6_24
);
2174 /* Reduce power by user selection */
2175 scaledPower
= AH_MIN(scaledPower
, targetPowerCck
.twicePwr6_24
) - (tpcScaleReduction
* 2);
2176 scaledPower
= (scaledPower
< 0) ? 0 : scaledPower
;
2177 scaledPower
= AH_MIN(scaledPower
, powerLimit
);
2180 /* Set CCK rates 2L, 2S, 5.5L, 5.5S, 11L, 11S */
2181 rpow
[8] = AH_MIN(scaledPower
, targetPowerCck
.twicePwr6_24
);
2182 r9
= rpow
[9] = AH_MIN(scaledPower
, targetPowerCck
.twicePwr36
);
2184 rpow
[11] = AH_MIN(scaledPower
, targetPowerCck
.twicePwr48
);
2185 rpow
[12] = rpow
[11];
2186 r13
= rpow
[13] = AH_MIN(scaledPower
, targetPowerCck
.twicePwr54
);
2187 rpow
[14] = rpow
[13];
2189 r9
= AH_MIN(scaledPower
, targetPowerCck
.twicePwr36
);
2190 r13
= AH_MIN(scaledPower
, targetPowerCck
.twicePwr54
);
2193 /* Set min/max power based off OFDM values or initialization */
2194 if (r13
< *pMinPower
)
2196 if (r9
> *pMaxPower
)
2199 HALDEBUG(ah
, HAL_DEBUG_RFPARAM
,
2200 "%s: cck: MaxRD: %d MaxCTL: %d "
2201 "TPC_Reduction %d chan=%d (0x%x) maxAvailPower=%d pwr6_24=%d, maxPower=%d\n",
2202 __func__
, twiceMaxRDPower
, twiceMaxEdgePowerCck
,
2203 tpcScaleReduction
* 2, chan
->channel
, chan
->channelFlags
,
2204 maxAvailPower
, targetPowerCck
.twicePwr6_24
, *pMaxPower
);
2207 ahp
->ah_tx6PowerInHalfDbm
= *pMaxPower
;
2208 AH_PRIVATE(ah
)->ah_maxPowerLevel
= ahp
->ah_tx6PowerInHalfDbm
;
2214 ar5212GetChipPowerLimits(struct ath_hal
*ah
, HAL_CHANNEL
*chans
, uint32_t nchans
)
2216 struct ath_hal_5212
*ahp
= AH5212(ah
);
2217 static const uint16_t tpcScaleReductionTable
[5] =
2218 { 0, 3, 6, 9, MAX_RATE_POWER
};
2219 int16_t minPower
, maxPower
, tpcInDb
, powerLimit
;
2224 * Get Pier table max and min powers.
2226 for (i
= 0; i
< nchans
; i
++) {
2228 if (ahp
->ah_rfHal
->getChannelMaxMinPower(ah
, chan
, &maxPower
, &minPower
)) {
2229 /* NB: rf code returns 1/4 dBm units, convert */
2230 chan
->maxTxPower
= maxPower
/ 2;
2231 chan
->minTxPower
= minPower
/ 2;
2233 HALDEBUG(ah
, HAL_DEBUG_ANY
,
2234 "%s: no min/max power for %u/0x%x\n",
2235 __func__
, chan
->channel
, chan
->channelFlags
);
2236 chan
->maxTxPower
= MAX_RATE_POWER
;
2237 chan
->minTxPower
= 0;
2241 * Now adjust to reflect any global scale and/or CTL's.
2242 * (XXX is that correct?)
2244 powerLimit
= AH_MIN(MAX_RATE_POWER
, AH_PRIVATE(ah
)->ah_powerLimit
);
2245 if (powerLimit
>= MAX_RATE_POWER
|| powerLimit
== 0)
2246 tpcInDb
= tpcScaleReductionTable
[AH_PRIVATE(ah
)->ah_tpScale
];
2249 for (i
=0; i
<nchans
; i
++) {
2251 if (!ar5212SetRateTable(ah
, (HAL_CHANNEL
*) chan
, tpcInDb
, powerLimit
,
2252 AH_FALSE
, &minPower
, &maxPower
)) {
2253 HALDEBUG(ah
, HAL_DEBUG_ANY
,
2254 "%s: unable to find max/min power\n",__func__
);
2257 if (maxPower
< chan
->maxTxPower
)
2258 chan
->maxTxPower
= maxPower
;
2259 if (minPower
< chan
->minTxPower
)
2260 chan
->minTxPower
= minPower
;
2263 for (i
=0; i
<nchans
; i
++) {
2264 HALDEBUG(ah
, HAL_DEBUG_RESET
,
2265 "Chan %d: MaxPow = %d MinPow = %d\n",
2266 chans
[i
].channel
,chans
[i
].maxTxPower
, chans
[i
].minTxPower
);
2273 * Correct for the gain-delta between ofdm and cck mode target
2274 * powers. Write the results to the rate table and the power table.
2277 * 1. rpow[ii] is the integer value of 2*(desired power
2278 * for the rate ii in dBm) to provide 0.5dB resolution. rate
2279 * mapping is as following :
2280 * [0..7] --> ofdm 6, 9, .. 48, 54
2281 * [8..14] --> cck 1L, 2L, 2S, .. 11L, 11S
2282 * [15] --> XR (all rates get the same power)
2283 * 2. powv[ii] is the pcdac corresponding to ii/2 dBm.
2286 ar5212CorrectGainDelta(struct ath_hal
*ah
, int twiceOfdmCckDelta
)
2288 #define N(_a) (sizeof(_a) / sizeof(_a[0]))
2289 struct ath_hal_5212
*ahp
= AH5212(ah
);
2290 const HAL_EEPROM
*ee
= AH_PRIVATE(ah
)->ah_eeprom
;
2291 int16_t ratesIndex
[N(ahp
->ah_ratesArray
)];
2292 uint16_t ii
, jj
, iter
;
2294 int16_t gainDeltaAdjust
;
2296 HALASSERT(ah
->ah_magic
== AR5212_MAGIC
);
2298 gainDeltaAdjust
= ee
->ee_cckOfdmGainDelta
;
2300 /* make a local copy of desired powers as initial indices */
2301 OS_MEMCPY(ratesIndex
, ahp
->ah_ratesArray
, sizeof(ratesIndex
));
2303 /* fix only the CCK indices */
2304 for (ii
= 8; ii
< 15; ii
++) {
2305 /* apply a gain_delta correction of -15 for CCK */
2306 ratesIndex
[ii
] -= gainDeltaAdjust
;
2308 /* Now check for contention with all ofdm target powers */
2311 /* indicates not all ofdm rates checked forcontention yet */
2313 if (ratesIndex
[ii
] < 0)
2315 if (jj
== 8) { /* skip CCK rates */
2319 if (ratesIndex
[ii
] == ahp
->ah_ratesArray
[jj
]) {
2320 if (ahp
->ah_ratesArray
[jj
] == 0)
2322 else if (iter
> 50) {
2324 * To avoid pathological case of of
2325 * dm target powers 0 and 0.5dBm
2330 /* check with all rates again */
2336 if (ratesIndex
[ii
] >= PWR_TABLE_SIZE
)
2337 ratesIndex
[ii
] = PWR_TABLE_SIZE
-1;
2338 cckIndex
= ahp
->ah_ratesArray
[ii
] - twiceOfdmCckDelta
;
2343 * Validate that the indexes for the powv are not
2346 HALASSERT(cckIndex
< PWR_TABLE_SIZE
);
2347 HALASSERT(ratesIndex
[ii
] < PWR_TABLE_SIZE
);
2348 ahp
->ah_pcdacTable
[ratesIndex
[ii
]] =
2349 ahp
->ah_pcdacTable
[cckIndex
];
2351 /* Override rate per power table with new values */
2352 for (ii
= 8; ii
< 15; ii
++)
2353 ahp
->ah_ratesArray
[ii
] = ratesIndex
[ii
];
2358 * Find the maximum conformance test limit for the given channel and CTL info
2361 ar5212GetMaxEdgePower(uint16_t channel
, const RD_EDGES_POWER
*pRdEdgesPower
)
2363 /* temp array for holding edge channels */
2364 uint16_t tempChannelList
[NUM_EDGES
];
2365 uint16_t clo
= 0, chi
= 0, twiceMaxEdgePower
;
2368 /* Get the edge power */
2369 for (i
= 0; i
< NUM_EDGES
; i
++) {
2370 if (pRdEdgesPower
[i
].rdEdge
== 0)
2372 tempChannelList
[i
] = pRdEdgesPower
[i
].rdEdge
;
2376 ar5212GetLowerUpperValues(channel
, tempChannelList
,
2377 numEdges
, &clo
, &chi
);
2378 /* Get the index for the lower channel */
2379 for (i
= 0; i
< numEdges
&& clo
!= tempChannelList
[i
]; i
++)
2381 /* Is lower channel ever outside the rdEdge? */
2382 HALASSERT(i
!= numEdges
);
2384 if ((clo
== chi
&& clo
== channel
) || (pRdEdgesPower
[i
].flag
)) {
2386 * If there's an exact channel match or an inband flag set
2387 * on the lower channel use the given rdEdgePower
2389 twiceMaxEdgePower
= pRdEdgesPower
[i
].twice_rdEdgePower
;
2390 HALASSERT(twiceMaxEdgePower
> 0);
2392 twiceMaxEdgePower
= MAX_RATE_POWER
;
2393 return twiceMaxEdgePower
;
2397 * Returns interpolated or the scaled up interpolated value
2400 interpolate(uint16_t target
, uint16_t srcLeft
, uint16_t srcRight
,
2401 uint16_t targetLeft
, uint16_t targetRight
)
2406 /* to get an accurate ratio, always scale, if want to scale, then don't scale back down */
2407 if ((targetLeft
* targetRight
) == 0)
2410 if (srcRight
!= srcLeft
) {
2412 * Note the ratio always need to be scaled,
2413 * since it will be a fraction.
2415 lRatio
= (target
- srcLeft
) * EEP_SCALE
/ (srcRight
- srcLeft
);
2417 /* Return as Left target if value would be negative */
2419 } else if (lRatio
> EEP_SCALE
) {
2420 /* Return as Right target if Ratio is greater than 100% (SCALE) */
2423 rv
= (lRatio
* targetRight
+ (EEP_SCALE
- lRatio
) *
2424 targetLeft
) / EEP_SCALE
;
2433 * Return the four rates of target power for the given target power table
2434 * channel, and number of channels
2437 ar5212GetTargetPowers(struct ath_hal
*ah
, HAL_CHANNEL
*chan
,
2438 const TRGT_POWER_INFO
*powInfo
,
2439 uint16_t numChannels
, TRGT_POWER_INFO
*pNewPower
)
2441 /* temp array for holding target power channels */
2442 uint16_t tempChannelList
[NUM_TEST_FREQUENCIES
];
2443 uint16_t clo
= 0, chi
= 0, ixlo
, ixhi
;
2446 /* Copy the target powers into the temp channel list */
2447 for (i
= 0; i
< numChannels
; i
++)
2448 tempChannelList
[i
] = powInfo
[i
].testChannel
;
2450 ar5212GetLowerUpperValues(chan
->channel
, tempChannelList
,
2451 numChannels
, &clo
, &chi
);
2453 /* Get the indices for the channel */
2455 for (i
= 0; i
< numChannels
; i
++) {
2456 if (clo
== tempChannelList
[i
]) {
2459 if (chi
== tempChannelList
[i
]) {
2466 * Get the lower and upper channels, target powers,
2467 * and interpolate between them.
2469 pNewPower
->twicePwr6_24
= interpolate(chan
->channel
, clo
, chi
,
2470 powInfo
[ixlo
].twicePwr6_24
, powInfo
[ixhi
].twicePwr6_24
);
2471 pNewPower
->twicePwr36
= interpolate(chan
->channel
, clo
, chi
,
2472 powInfo
[ixlo
].twicePwr36
, powInfo
[ixhi
].twicePwr36
);
2473 pNewPower
->twicePwr48
= interpolate(chan
->channel
, clo
, chi
,
2474 powInfo
[ixlo
].twicePwr48
, powInfo
[ixhi
].twicePwr48
);
2475 pNewPower
->twicePwr54
= interpolate(chan
->channel
, clo
, chi
,
2476 powInfo
[ixlo
].twicePwr54
, powInfo
[ixhi
].twicePwr54
);
2480 * Search a list for a specified value v that is within
2481 * EEP_DELTA of the search values. Return the closest
2482 * values in the list above and below the desired value.
2483 * EEP_DELTA is a factional value; everything is scaled
2484 * so only integer arithmetic is used.
2486 * NB: the input list is assumed to be sorted in ascending order
2489 ar5212GetLowerUpperValues(uint16_t v
, uint16_t *lp
, uint16_t listSize
,
2490 uint16_t *vlo
, uint16_t *vhi
)
2492 uint32_t target
= v
* EEP_SCALE
;
2493 uint16_t *ep
= lp
+listSize
;
2496 * Check first and last elements for out-of-bounds conditions.
2498 if (target
< (uint32_t)(lp
[0] * EEP_SCALE
- EEP_DELTA
)) {
2499 *vlo
= *vhi
= lp
[0];
2502 if (target
> (uint32_t)(ep
[-1] * EEP_SCALE
+ EEP_DELTA
)) {
2503 *vlo
= *vhi
= ep
[-1];
2507 /* look for value being near or between 2 values in list */
2508 for (; lp
< ep
; lp
++) {
2510 * If value is close to the current value of the list
2511 * then target is not between values, it is one of the values
2513 if (abs(lp
[0] * EEP_SCALE
- target
) < EEP_DELTA
) {
2514 *vlo
= *vhi
= lp
[0];
2518 * Look for value being between current value and next value
2519 * if so return these 2 values
2521 if (target
< (uint32_t)(lp
[1] * EEP_SCALE
- EEP_DELTA
)) {
2527 HALASSERT(AH_FALSE
); /* should not reach here */
2531 * Perform analog "swizzling" of parameters into their location
2533 * NB: used by RF backends
2536 ar5212ModifyRfBuffer(uint32_t *rfBuf
, uint32_t reg32
, uint32_t numBits
,
2537 uint32_t firstBit
, uint32_t column
)
2539 #define MAX_ANALOG_START 319 /* XXX */
2540 uint32_t tmp32
, mask
, arrayEntry
, lastBit
;
2541 int32_t bitPosition
, bitsLeft
;
2543 HALASSERT(column
<= 3);
2544 HALASSERT(numBits
<= 32);
2545 HALASSERT(firstBit
+ numBits
<= MAX_ANALOG_START
);
2547 tmp32
= ath_hal_reverseBits(reg32
, numBits
);
2548 arrayEntry
= (firstBit
- 1) / 8;
2549 bitPosition
= (firstBit
- 1) % 8;
2551 while (bitsLeft
> 0) {
2552 lastBit
= (bitPosition
+ bitsLeft
> 8) ?
2553 8 : bitPosition
+ bitsLeft
;
2554 mask
= (((1 << lastBit
) - 1) ^ ((1 << bitPosition
) - 1)) <<
2556 rfBuf
[arrayEntry
] &= ~mask
;
2557 rfBuf
[arrayEntry
] |= ((tmp32
<< bitPosition
) <<
2558 (column
* 8)) & mask
;
2559 bitsLeft
-= 8 - bitPosition
;
2560 tmp32
= tmp32
>> (8 - bitPosition
);
2564 #undef MAX_ANALOG_START
2568 * Sets the rate to duration values in MAC - used for multi-
2570 * The rate duration table needs to cover all valid rate codes;
2571 * the 11g table covers all ofdm rates, while the 11b table
2572 * covers all cck rates => all valid rates get covered between
2573 * these two mode's ratetables!
2574 * But if we're turbo, the ofdm phy is replaced by the turbo phy
2575 * and cck is not valid with turbo => all rates get covered
2576 * by the turbo ratetable only
2579 ar5212SetRateDurationTable(struct ath_hal
*ah
, HAL_CHANNEL
*chan
)
2581 const HAL_RATE_TABLE
*rt
;
2584 /* NB: band doesn't matter for 1/2 and 1/4 rate */
2585 if (IS_CHAN_HALF_RATE(chan
)) {
2586 rt
= ar5212GetRateTable(ah
, HAL_MODE_11A_HALF_RATE
);
2587 } else if (IS_CHAN_QUARTER_RATE(chan
)) {
2588 rt
= ar5212GetRateTable(ah
, HAL_MODE_11A_QUARTER_RATE
);
2590 rt
= ar5212GetRateTable(ah
,
2591 IS_CHAN_TURBO(chan
) ? HAL_MODE_TURBO
: HAL_MODE_11G
);
2594 for (i
= 0; i
< rt
->rateCount
; ++i
)
2596 AR_RATE_DURATION(rt
->info
[i
].rateCode
),
2597 ath_hal_computetxtime(ah
, rt
,
2598 WLAN_CTRL_FRAME_SIZE
,
2599 rt
->info
[i
].controlRate
, AH_FALSE
));
2600 if (!IS_CHAN_TURBO(chan
)) {
2601 /* 11g Table is used to cover the CCK rates. */
2602 rt
= ar5212GetRateTable(ah
, HAL_MODE_11G
);
2603 for (i
= 0; i
< rt
->rateCount
; ++i
) {
2604 uint32_t reg
= AR_RATE_DURATION(rt
->info
[i
].rateCode
);
2606 if (rt
->info
[i
].phy
!= IEEE80211_T_CCK
)
2609 OS_REG_WRITE(ah
, reg
,
2610 ath_hal_computetxtime(ah
, rt
,
2611 WLAN_CTRL_FRAME_SIZE
,
2612 rt
->info
[i
].controlRate
, AH_FALSE
));
2613 /* cck rates have short preamble option also */
2614 if (rt
->info
[i
].shortPreamble
) {
2615 reg
+= rt
->info
[i
].shortPreamble
<< 2;
2616 OS_REG_WRITE(ah
, reg
,
2617 ath_hal_computetxtime(ah
, rt
,
2618 WLAN_CTRL_FRAME_SIZE
,
2619 rt
->info
[i
].controlRate
,
2626 /* Adjust various register settings based on half/quarter rate clock setting.
2627 * This includes: +USEC, TX/RX latency,
2628 * + IFS params: slot, eifs, misc etc.
2631 ar5212SetIFSTiming(struct ath_hal
*ah
, HAL_CHANNEL
*chan
)
2633 uint32_t txLat
, rxLat
, usec
, slot
, refClock
, eifs
, init_usec
;
2635 HALASSERT(IS_CHAN_HALF_RATE(chan
) || IS_CHAN_QUARTER_RATE(chan
));
2637 refClock
= OS_REG_READ(ah
, AR_USEC
) & AR_USEC_USEC32
;
2638 if (IS_CHAN_HALF_RATE(chan
)) {
2639 slot
= IFS_SLOT_HALF_RATE
;
2640 rxLat
= RX_NON_FULL_RATE_LATENCY
<< AR5212_USEC_RX_LAT_S
;
2641 txLat
= TX_HALF_RATE_LATENCY
<< AR5212_USEC_TX_LAT_S
;
2642 usec
= HALF_RATE_USEC
;
2643 eifs
= IFS_EIFS_HALF_RATE
;
2644 init_usec
= INIT_USEC
>> 1;
2645 } else { /* quarter rate */
2646 slot
= IFS_SLOT_QUARTER_RATE
;
2647 rxLat
= RX_NON_FULL_RATE_LATENCY
<< AR5212_USEC_RX_LAT_S
;
2648 txLat
= TX_QUARTER_RATE_LATENCY
<< AR5212_USEC_TX_LAT_S
;
2649 usec
= QUARTER_RATE_USEC
;
2650 eifs
= IFS_EIFS_QUARTER_RATE
;
2651 init_usec
= INIT_USEC
>> 2;
2654 OS_REG_WRITE(ah
, AR_USEC
, (usec
| refClock
| txLat
| rxLat
));
2655 OS_REG_WRITE(ah
, AR_D_GBL_IFS_SLOT
, slot
);
2656 OS_REG_WRITE(ah
, AR_D_GBL_IFS_EIFS
, eifs
);
2657 OS_REG_RMW_FIELD(ah
, AR_D_GBL_IFS_MISC
,
2658 AR_D_GBL_IFS_MISC_USEC_DURATION
, init_usec
);