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_misc.c,v 1.1.1.1 2008/12/11 04:46:41 alc Exp $
22 #include "ah_internal.h"
25 #include "ah_desc.h" /* NB: for HAL_PHYERR* */
28 #include "ar5212/ar5212.h"
29 #include "ar5212/ar5212reg.h"
30 #include "ar5212/ar5212phy.h"
32 #include "ah_eeprom_v3.h"
34 #define AR_NUM_GPIO 6 /* 6 GPIO pins */
35 #define AR_GPIOD_MASK 0x0000002F /* GPIO data reg r/w mask */
37 extern void ar5212SetRateDurationTable(struct ath_hal
*, HAL_CHANNEL
*);
40 ar5212GetMacAddress(struct ath_hal
*ah
, uint8_t *mac
)
42 struct ath_hal_5212
*ahp
= AH5212(ah
);
44 OS_MEMCPY(mac
, ahp
->ah_macaddr
, IEEE80211_ADDR_LEN
);
48 ar5212SetMacAddress(struct ath_hal
*ah
, const uint8_t *mac
)
50 struct ath_hal_5212
*ahp
= AH5212(ah
);
52 OS_MEMCPY(ahp
->ah_macaddr
, mac
, IEEE80211_ADDR_LEN
);
57 ar5212GetBssIdMask(struct ath_hal
*ah
, uint8_t *mask
)
59 struct ath_hal_5212
*ahp
= AH5212(ah
);
61 OS_MEMCPY(mask
, ahp
->ah_bssidmask
, IEEE80211_ADDR_LEN
);
65 ar5212SetBssIdMask(struct ath_hal
*ah
, const uint8_t *mask
)
67 struct ath_hal_5212
*ahp
= AH5212(ah
);
69 /* save it since it must be rewritten on reset */
70 OS_MEMCPY(ahp
->ah_bssidmask
, mask
, IEEE80211_ADDR_LEN
);
72 OS_REG_WRITE(ah
, AR_BSSMSKL
, LE_READ_4(ahp
->ah_bssidmask
));
73 OS_REG_WRITE(ah
, AR_BSSMSKU
, LE_READ_2(ahp
->ah_bssidmask
+ 4));
78 * Attempt to change the cards operating regulatory domain to the given value
81 ar5212SetRegulatoryDomain(struct ath_hal
*ah
,
82 uint16_t regDomain
, HAL_STATUS
*status
)
86 if (AH_PRIVATE(ah
)->ah_currentRD
== regDomain
) {
90 if (ath_hal_eepromGetFlag(ah
, AR_EEP_WRITEPROTECT
)) {
94 #ifdef AH_SUPPORT_WRITE_REGDOMAIN
95 if (ath_hal_eepromWrite(ah
, AR_EEPROM_REG_DOMAIN
, regDomain
)) {
96 HALDEBUG(ah
, HAL_DEBUG_ANY
,
97 "%s: set regulatory domain to %u (0x%x)\n",
98 __func__
, regDomain
, regDomain
);
99 AH_PRIVATE(ah
)->ah_currentRD
= regDomain
;
111 * Return the wireless modes (a,b,g,t) supported by hardware.
113 * This value is what is actually supported by the hardware
114 * and is unaffected by regulatory/country code settings.
117 ar5212GetWirelessModes(struct ath_hal
*ah
)
121 if (ath_hal_eepromGetFlag(ah
, AR_EEP_AMODE
)) {
123 if (!ath_hal_eepromGetFlag(ah
, AR_EEP_TURBO5DISABLE
))
124 mode
|= HAL_MODE_TURBO
| HAL_MODE_108A
;
125 if (AH_PRIVATE(ah
)->ah_caps
.halChanHalfRate
)
126 mode
|= HAL_MODE_11A_HALF_RATE
;
127 if (AH_PRIVATE(ah
)->ah_caps
.halChanQuarterRate
)
128 mode
|= HAL_MODE_11A_QUARTER_RATE
;
130 if (ath_hal_eepromGetFlag(ah
, AR_EEP_BMODE
))
131 mode
|= HAL_MODE_11B
;
132 if (ath_hal_eepromGetFlag(ah
, AR_EEP_GMODE
) &&
133 AH_PRIVATE(ah
)->ah_subvendorid
!= AR_SUBVENDOR_ID_NOG
) {
134 mode
|= HAL_MODE_11G
;
135 if (!ath_hal_eepromGetFlag(ah
, AR_EEP_TURBO2DISABLE
))
136 mode
|= HAL_MODE_108G
;
137 if (AH_PRIVATE(ah
)->ah_caps
.halChanHalfRate
)
138 mode
|= HAL_MODE_11G_HALF_RATE
;
139 if (AH_PRIVATE(ah
)->ah_caps
.halChanQuarterRate
)
140 mode
|= HAL_MODE_11G_QUARTER_RATE
;
146 * Set the interrupt and GPIO values so the ISR can disable RF
147 * on a switch signal. Assumes GPIO port and interrupt polarity
148 * are set prior to call.
151 ar5212EnableRfKill(struct ath_hal
*ah
)
153 uint16_t rfsilent
= AH_PRIVATE(ah
)->ah_rfsilent
;
154 int select
= MS(rfsilent
, AR_EEPROM_RFSILENT_GPIO_SEL
);
155 int polarity
= MS(rfsilent
, AR_EEPROM_RFSILENT_POLARITY
);
158 * Configure the desired GPIO port for input
159 * and enable baseband rf silence.
161 ath_hal_gpioCfgInput(ah
, select
);
162 OS_REG_SET_BIT(ah
, AR_PHY(0), 0x00002000);
164 * If radio disable switch connection to GPIO bit x is enabled
165 * program GPIO interrupt.
166 * If rfkill bit on eeprom is 1, setupeeprommap routine has already
167 * verified that it is a later version of eeprom, it has a place for
168 * rfkill bit and it is set to 1, indicating that GPIO bit x hardware
169 * connection is present.
171 ath_hal_gpioSetIntr(ah
, select
,
172 (ath_hal_gpioGet(ah
, select
) == polarity
? !polarity
: polarity
));
176 * Change the LED blinking pattern to correspond to the connectivity
179 ar5212SetLedState(struct ath_hal
*ah
, HAL_LED_STATE state
)
181 static const uint32_t ledbits
[8] = {
182 AR_PCICFG_LEDCTL_NONE
, /* HAL_LED_INIT */
183 AR_PCICFG_LEDCTL_PEND
, /* HAL_LED_SCAN */
184 AR_PCICFG_LEDCTL_PEND
, /* HAL_LED_AUTH */
185 AR_PCICFG_LEDCTL_ASSOC
, /* HAL_LED_ASSOC*/
186 AR_PCICFG_LEDCTL_ASSOC
, /* HAL_LED_RUN */
187 AR_PCICFG_LEDCTL_NONE
,
188 AR_PCICFG_LEDCTL_NONE
,
189 AR_PCICFG_LEDCTL_NONE
,
193 bits
= OS_REG_READ(ah
, AR_PCICFG
);
196 * Enable LED for Nala. There is a bit marked reserved
197 * that must be set and we also turn on the power led.
198 * Because we mark s/w LED control setting the control
199 * status bits below is meangless (the driver must flash
200 * the LED(s) using the GPIO lines).
202 bits
= (bits
&~ AR_PCICFG_LEDMODE
)
203 | SM(AR_PCICFG_LEDMODE_POWON
, AR_PCICFG_LEDMODE
)
205 | SM(AR_PCICFG_LEDMODE_NETON
, AR_PCICFG_LEDMODE
)
209 bits
= (bits
&~ AR_PCICFG_LEDCTL
)
210 | SM(ledbits
[state
& 0x7], AR_PCICFG_LEDCTL
);
211 OS_REG_WRITE(ah
, AR_PCICFG
, bits
);
215 * Change association related fields programmed into the hardware.
216 * Writing a valid BSSID to the hardware effectively enables the hardware
217 * to synchronize its TSF to the correct beacons and receive frames coming
218 * from that BSSID. It is called by the SME JOIN operation.
221 ar5212WriteAssocid(struct ath_hal
*ah
, const uint8_t *bssid
, uint16_t assocId
)
223 struct ath_hal_5212
*ahp
= AH5212(ah
);
225 /* XXX save bssid for possible re-use on reset */
226 OS_MEMCPY(ahp
->ah_bssid
, bssid
, IEEE80211_ADDR_LEN
);
227 OS_REG_WRITE(ah
, AR_BSS_ID0
, LE_READ_4(ahp
->ah_bssid
));
228 OS_REG_WRITE(ah
, AR_BSS_ID1
, LE_READ_2(ahp
->ah_bssid
+4) |
229 ((assocId
& 0x3fff)<<AR_BSS_ID1_AID_S
));
233 * Get the current hardware tsf for stamlme
236 ar5212GetTsf64(struct ath_hal
*ah
)
238 uint32_t low1
, low2
, u32
;
240 /* sync multi-word read */
241 low1
= OS_REG_READ(ah
, AR_TSF_L32
);
242 u32
= OS_REG_READ(ah
, AR_TSF_U32
);
243 low2
= OS_REG_READ(ah
, AR_TSF_L32
);
244 if (low2
< low1
) { /* roll over */
246 * If we are not preempted this will work. If we are
247 * then we re-reading AR_TSF_U32 does no good as the
248 * low bits will be meaningless. Likewise reading
249 * L32, U32, U32, then comparing the last two reads
250 * to check for rollover doesn't help if preempted--so
251 * we take this approach as it costs one less PCI read
252 * which can be noticeable when doing things like
253 * timestamping packets in monitor mode.
257 return (((uint64_t) u32
) << 32) | ((uint64_t) low2
);
261 * Get the current hardware tsf for stamlme
264 ar5212GetTsf32(struct ath_hal
*ah
)
266 return OS_REG_READ(ah
, AR_TSF_L32
);
270 * Reset the current hardware tsf for stamlme.
273 ar5212ResetTsf(struct ath_hal
*ah
)
276 uint32_t val
= OS_REG_READ(ah
, AR_BEACON
);
278 OS_REG_WRITE(ah
, AR_BEACON
, val
| AR_BEACON_RESET_TSF
);
280 * When resetting the TSF, write twice to the
281 * corresponding register; each write to the RESET_TSF bit toggles
282 * the internal signal to cause a reset of the TSF - but if the signal
283 * is left high, it will reset the TSF on the next chip reset also!
284 * writing the bit an even number of times fixes this issue
286 OS_REG_WRITE(ah
, AR_BEACON
, val
| AR_BEACON_RESET_TSF
);
290 * Set or clear hardware basic rate bit
291 * Set hardware basic rate set if basic rate is found
292 * and basic rate is equal or less than 2Mbps
295 ar5212SetBasicRate(struct ath_hal
*ah
, HAL_RATE_SET
*rs
)
297 HAL_CHANNEL_INTERNAL
*chan
= AH_PRIVATE(ah
)->ah_curchan
;
302 if (chan
== AH_NULL
|| !IS_CHAN_CCK(chan
))
305 for (i
= 0; i
< rs
->rs_count
; i
++) {
306 uint8_t rset
= rs
->rs_rates
[i
];
307 /* Basic rate defined? */
308 if ((rset
& 0x80) && (rset
&= 0x7f) >= xset
)
312 * Set the h/w bit to reflect whether or not the basic
313 * rate is found to be equal or less than 2Mbps.
315 reg
= OS_REG_READ(ah
, AR_STA_ID1
);
316 if (xset
&& xset
/2 <= 2)
317 OS_REG_WRITE(ah
, AR_STA_ID1
, reg
| AR_STA_ID1_BASE_RATE_11B
);
319 OS_REG_WRITE(ah
, AR_STA_ID1
, reg
&~ AR_STA_ID1_BASE_RATE_11B
);
323 * Grab a semi-random value from hardware registers - may not
327 ar5212GetRandomSeed(struct ath_hal
*ah
)
331 nf
= (OS_REG_READ(ah
, AR_PHY(25)) >> 19) & 0x1ff;
333 nf
= 0 - ((nf
^ 0x1ff) + 1);
334 return (OS_REG_READ(ah
, AR_TSF_U32
) ^
335 OS_REG_READ(ah
, AR_TSF_L32
) ^ nf
);
339 * Detect if our card is present
342 ar5212DetectCardPresent(struct ath_hal
*ah
)
344 uint16_t macVersion
, macRev
;
348 * Read the Silicon Revision register and compare that
349 * to what we read at attach time. If the same, we say
350 * a card/device is present.
352 v
= OS_REG_READ(ah
, AR_SREV
) & AR_SREV_ID
;
353 macVersion
= v
>> AR_SREV_ID_S
;
354 macRev
= v
& AR_SREV_REVISION
;
355 return (AH_PRIVATE(ah
)->ah_macVersion
== macVersion
&&
356 AH_PRIVATE(ah
)->ah_macRev
== macRev
);
360 ar5212EnableMibCounters(struct ath_hal
*ah
)
362 /* NB: this just resets the mib counter machinery */
363 OS_REG_WRITE(ah
, AR_MIBC
,
364 ~(AR_MIBC_COW
| AR_MIBC_FMC
| AR_MIBC_CMC
| AR_MIBC_MCS
) & 0x0f);
368 ar5212DisableMibCounters(struct ath_hal
*ah
)
370 OS_REG_WRITE(ah
, AR_MIBC
, AR_MIBC
| AR_MIBC_CMC
);
374 * Update MIB Counters
377 ar5212UpdateMibCounters(struct ath_hal
*ah
, HAL_MIB_STATS
* stats
)
379 stats
->ackrcv_bad
+= OS_REG_READ(ah
, AR_ACK_FAIL
);
380 stats
->rts_bad
+= OS_REG_READ(ah
, AR_RTS_FAIL
);
381 stats
->fcs_bad
+= OS_REG_READ(ah
, AR_FCS_FAIL
);
382 stats
->rts_good
+= OS_REG_READ(ah
, AR_RTS_OK
);
383 stats
->beacons
+= OS_REG_READ(ah
, AR_BEACON_CNT
);
387 * Detect if the HW supports spreading a CCK signal on channel 14
390 ar5212IsJapanChannelSpreadSupported(struct ath_hal
*ah
)
396 * Get the rssi of frame curently being received.
399 ar5212GetCurRssi(struct ath_hal
*ah
)
401 return (OS_REG_READ(ah
, AR_PHY_CURRENT_RSSI
) & 0xff);
405 ar5212GetDefAntenna(struct ath_hal
*ah
)
407 return (OS_REG_READ(ah
, AR_DEF_ANTENNA
) & 0x7);
411 ar5212SetDefAntenna(struct ath_hal
*ah
, u_int antenna
)
413 OS_REG_WRITE(ah
, AR_DEF_ANTENNA
, (antenna
& 0x7));
417 ar5212GetAntennaSwitch(struct ath_hal
*ah
)
419 return AH5212(ah
)->ah_antControl
;
423 ar5212SetAntennaSwitch(struct ath_hal
*ah
, HAL_ANT_SETTING setting
)
425 struct ath_hal_5212
*ahp
= AH5212(ah
);
426 const HAL_CHANNEL_INTERNAL
*ichan
= AH_PRIVATE(ah
)->ah_curchan
;
428 if (!ahp
->ah_phyPowerOn
|| ichan
== AH_NULL
) {
429 /* PHY powered off, just stash settings */
430 ahp
->ah_antControl
= setting
;
431 ahp
->ah_diversity
= (setting
== HAL_ANT_VARIABLE
);
434 return ar5212SetAntennaSwitchInternal(ah
, setting
, ichan
);
438 ar5212IsSleepAfterBeaconBroken(struct ath_hal
*ah
)
444 ar5212SetSifsTime(struct ath_hal
*ah
, u_int us
)
446 struct ath_hal_5212
*ahp
= AH5212(ah
);
448 if (us
> ath_hal_mac_usec(ah
, 0xffff)) {
449 HALDEBUG(ah
, HAL_DEBUG_ANY
, "%s: bad SIFS time %u\n",
451 ahp
->ah_sifstime
= (u_int
) -1; /* restore default handling */
454 /* convert to system clocks */
455 OS_REG_WRITE(ah
, AR_D_GBL_IFS_SIFS
, ath_hal_mac_clks(ah
, us
));
456 ahp
->ah_slottime
= us
;
462 ar5212GetSifsTime(struct ath_hal
*ah
)
464 u_int clks
= OS_REG_READ(ah
, AR_D_GBL_IFS_SIFS
) & 0xffff;
465 return ath_hal_mac_usec(ah
, clks
); /* convert from system clocks */
469 ar5212SetSlotTime(struct ath_hal
*ah
, u_int us
)
471 struct ath_hal_5212
*ahp
= AH5212(ah
);
473 if (us
< HAL_SLOT_TIME_6
|| us
> ath_hal_mac_usec(ah
, 0xffff)) {
474 HALDEBUG(ah
, HAL_DEBUG_ANY
, "%s: bad slot time %u\n",
476 ahp
->ah_slottime
= (u_int
) -1; /* restore default handling */
479 /* convert to system clocks */
480 OS_REG_WRITE(ah
, AR_D_GBL_IFS_SLOT
, ath_hal_mac_clks(ah
, us
));
481 ahp
->ah_slottime
= us
;
487 ar5212GetSlotTime(struct ath_hal
*ah
)
489 u_int clks
= OS_REG_READ(ah
, AR_D_GBL_IFS_SLOT
) & 0xffff;
490 return ath_hal_mac_usec(ah
, clks
); /* convert from system clocks */
494 ar5212SetAckTimeout(struct ath_hal
*ah
, u_int us
)
496 struct ath_hal_5212
*ahp
= AH5212(ah
);
498 if (us
> ath_hal_mac_usec(ah
, MS(0xffffffff, AR_TIME_OUT_ACK
))) {
499 HALDEBUG(ah
, HAL_DEBUG_ANY
, "%s: bad ack timeout %u\n",
501 ahp
->ah_acktimeout
= (u_int
) -1; /* restore default handling */
504 /* convert to system clocks */
505 OS_REG_RMW_FIELD(ah
, AR_TIME_OUT
,
506 AR_TIME_OUT_ACK
, ath_hal_mac_clks(ah
, us
));
507 ahp
->ah_acktimeout
= us
;
513 ar5212GetAckTimeout(struct ath_hal
*ah
)
515 u_int clks
= MS(OS_REG_READ(ah
, AR_TIME_OUT
), AR_TIME_OUT_ACK
);
516 return ath_hal_mac_usec(ah
, clks
); /* convert from system clocks */
520 ar5212GetAckCTSRate(struct ath_hal
*ah
)
522 return ((AH5212(ah
)->ah_staId1Defaults
& AR_STA_ID1_ACKCTS_6MB
) == 0);
526 ar5212SetAckCTSRate(struct ath_hal
*ah
, u_int high
)
528 struct ath_hal_5212
*ahp
= AH5212(ah
);
531 OS_REG_CLR_BIT(ah
, AR_STA_ID1
, AR_STA_ID1_ACKCTS_6MB
);
532 ahp
->ah_staId1Defaults
&= ~AR_STA_ID1_ACKCTS_6MB
;
534 OS_REG_SET_BIT(ah
, AR_STA_ID1
, AR_STA_ID1_ACKCTS_6MB
);
535 ahp
->ah_staId1Defaults
|= AR_STA_ID1_ACKCTS_6MB
;
541 ar5212SetCTSTimeout(struct ath_hal
*ah
, u_int us
)
543 struct ath_hal_5212
*ahp
= AH5212(ah
);
545 if (us
> ath_hal_mac_usec(ah
, MS(0xffffffff, AR_TIME_OUT_CTS
))) {
546 HALDEBUG(ah
, HAL_DEBUG_ANY
, "%s: bad cts timeout %u\n",
548 ahp
->ah_ctstimeout
= (u_int
) -1; /* restore default handling */
551 /* convert to system clocks */
552 OS_REG_RMW_FIELD(ah
, AR_TIME_OUT
,
553 AR_TIME_OUT_CTS
, ath_hal_mac_clks(ah
, us
));
554 ahp
->ah_ctstimeout
= us
;
560 ar5212GetCTSTimeout(struct ath_hal
*ah
)
562 u_int clks
= MS(OS_REG_READ(ah
, AR_TIME_OUT
), AR_TIME_OUT_CTS
);
563 return ath_hal_mac_usec(ah
, clks
); /* convert from system clocks */
566 /* Setup decompression for given key index */
568 ar5212SetDecompMask(struct ath_hal
*ah
, uint16_t keyidx
, int en
)
570 struct ath_hal_5212
*ahp
= AH5212(ah
);
572 if (keyidx
>= HAL_DECOMP_MASK_SIZE
)
574 OS_REG_WRITE(ah
, AR_DCM_A
, keyidx
);
575 OS_REG_WRITE(ah
, AR_DCM_D
, en
? AR_DCM_D_EN
: 0);
576 ahp
->ah_decompMask
[keyidx
] = en
;
581 /* Setup coverage class */
583 ar5212SetCoverageClass(struct ath_hal
*ah
, uint8_t coverageclass
, int now
)
585 uint32_t slot
, timeout
, eifs
;
588 AH_PRIVATE(ah
)->ah_coverageClass
= coverageclass
;
591 if (AH_PRIVATE(ah
)->ah_coverageClass
== 0)
594 /* Don't apply coverage class to non A channels */
595 if (!IS_CHAN_A(AH_PRIVATE(ah
)->ah_curchan
))
598 /* Get core clock rate */
599 clkRate
= ath_hal_mac_clks(ah
, 1);
602 slot
= coverageclass
* 3 * clkRate
;
603 eifs
= coverageclass
* 6 * clkRate
;
604 if (IS_CHAN_HALF_RATE(AH_PRIVATE(ah
)->ah_curchan
)) {
605 slot
+= IFS_SLOT_HALF_RATE
;
606 eifs
+= IFS_EIFS_HALF_RATE
;
607 } else if (IS_CHAN_QUARTER_RATE(AH_PRIVATE(ah
)->ah_curchan
)) {
608 slot
+= IFS_SLOT_QUARTER_RATE
;
609 eifs
+= IFS_EIFS_QUARTER_RATE
;
610 } else { /* full rate */
611 slot
+= IFS_SLOT_FULL_RATE
;
612 eifs
+= IFS_EIFS_FULL_RATE
;
616 * Add additional time for air propagation for ACK and CTS
617 * timeouts. This value is in core clocks.
619 timeout
= ACK_CTS_TIMEOUT_11A
+ (coverageclass
* 3 * clkRate
);
622 * Write the values: slot, eifs, ack/cts timeouts.
624 OS_REG_WRITE(ah
, AR_D_GBL_IFS_SLOT
, slot
);
625 OS_REG_WRITE(ah
, AR_D_GBL_IFS_EIFS
, eifs
);
626 OS_REG_WRITE(ah
, AR_TIME_OUT
,
627 SM(timeout
, AR_TIME_OUT_CTS
)
628 | SM(timeout
, AR_TIME_OUT_ACK
));
633 ar5212SetPCUConfig(struct ath_hal
*ah
)
635 ar5212SetOperatingMode(ah
, AH_PRIVATE(ah
)->ah_opmode
);
639 * Return whether an external 32KHz crystal should be used
640 * to reduce power consumption when sleeping. We do so if
641 * the crystal is present (obtained from EEPROM) and if we
642 * are not running as an AP and are configured to use it.
645 ar5212Use32KHzclock(struct ath_hal
*ah
, HAL_OPMODE opmode
)
647 if (opmode
!= HAL_M_HOSTAP
) {
648 struct ath_hal_5212
*ahp
= AH5212(ah
);
649 return ath_hal_eepromGetFlag(ah
, AR_EEP_32KHZCRYSTAL
) &&
650 (ahp
->ah_enable32kHzClock
== USE_32KHZ
||
651 ahp
->ah_enable32kHzClock
== AUTO_32KHZ
);
657 * If 32KHz clock exists, use it to lower power consumption during sleep
659 * Note: If clock is set to 32 KHz, delays on accessing certain
660 * baseband registers (27-31, 124-127) are required.
663 ar5212SetupClock(struct ath_hal
*ah
, HAL_OPMODE opmode
)
665 if (ar5212Use32KHzclock(ah
, opmode
)) {
667 * Enable clocks to be turned OFF in BB during sleep
668 * and also enable turning OFF 32MHz/40MHz Refclk
671 OS_REG_WRITE(ah
, AR_PHY_SLEEP_CTR_CONTROL
, 0x1f);
672 OS_REG_WRITE(ah
, AR_PHY_REFCLKPD
,
673 IS_RAD5112_ANY(ah
) || IS_5413(ah
) ? 0x14 : 0x18);
674 OS_REG_RMW_FIELD(ah
, AR_USEC
, AR_USEC_USEC32
, 1);
675 OS_REG_WRITE(ah
, AR_TSF_PARM
, 61); /* 32 KHz TSF incr */
676 OS_REG_RMW_FIELD(ah
, AR_PCICFG
, AR_PCICFG_SCLK_SEL
, 1);
678 if (IS_2413(ah
) || IS_5413(ah
) || IS_2417(ah
)) {
679 OS_REG_WRITE(ah
, AR_PHY_SLEEP_CTR_LIMIT
, 0x26);
680 OS_REG_WRITE(ah
, AR_PHY_SLEEP_SCAL
, 0x0d);
681 OS_REG_WRITE(ah
, AR_PHY_M_SLEEP
, 0x07);
682 OS_REG_WRITE(ah
, AR_PHY_REFCLKDLY
, 0x3f);
683 /* # Set sleep clock rate to 32 KHz. */
684 OS_REG_RMW_FIELD(ah
, AR_PCICFG
, AR_PCICFG_SCLK_RATE_IND
, 0x2);
686 OS_REG_WRITE(ah
, AR_PHY_SLEEP_CTR_LIMIT
, 0x0a);
687 OS_REG_WRITE(ah
, AR_PHY_SLEEP_SCAL
, 0x0c);
688 OS_REG_WRITE(ah
, AR_PHY_M_SLEEP
, 0x03);
689 OS_REG_WRITE(ah
, AR_PHY_REFCLKDLY
, 0x20);
690 OS_REG_RMW_FIELD(ah
, AR_PCICFG
, AR_PCICFG_SCLK_RATE_IND
, 0x3);
693 OS_REG_RMW_FIELD(ah
, AR_PCICFG
, AR_PCICFG_SCLK_RATE_IND
, 0x0);
694 OS_REG_RMW_FIELD(ah
, AR_PCICFG
, AR_PCICFG_SCLK_SEL
, 0);
696 OS_REG_WRITE(ah
, AR_TSF_PARM
, 1); /* 32MHz TSF inc */
698 OS_REG_WRITE(ah
, AR_PHY_SLEEP_CTR_CONTROL
, 0x1f);
699 OS_REG_WRITE(ah
, AR_PHY_SLEEP_CTR_LIMIT
, 0x7f);
702 OS_REG_WRITE(ah
, AR_PHY_SLEEP_SCAL
, 0x0a);
703 else if (IS_HB63(ah
))
704 OS_REG_WRITE(ah
, AR_PHY_SLEEP_SCAL
, 0x32);
706 OS_REG_WRITE(ah
, AR_PHY_SLEEP_SCAL
, 0x0e);
707 OS_REG_WRITE(ah
, AR_PHY_M_SLEEP
, 0x0c);
708 OS_REG_WRITE(ah
, AR_PHY_REFCLKDLY
, 0xff);
709 OS_REG_WRITE(ah
, AR_PHY_REFCLKPD
,
710 IS_RAD5112_ANY(ah
) || IS_5413(ah
) || IS_2417(ah
) ? 0x14 : 0x18);
711 OS_REG_RMW_FIELD(ah
, AR_USEC
, AR_USEC_USEC32
,
712 IS_RAD5112_ANY(ah
) || IS_5413(ah
) ? 39 : 31);
717 * If 32KHz clock exists, turn it off and turn back on the 32Mhz
720 ar5212RestoreClock(struct ath_hal
*ah
, HAL_OPMODE opmode
)
722 if (ar5212Use32KHzclock(ah
, opmode
)) {
723 /* # Set sleep clock rate back to 32 MHz. */
724 OS_REG_RMW_FIELD(ah
, AR_PCICFG
, AR_PCICFG_SCLK_RATE_IND
, 0);
725 OS_REG_RMW_FIELD(ah
, AR_PCICFG
, AR_PCICFG_SCLK_SEL
, 0);
727 OS_REG_WRITE(ah
, AR_TSF_PARM
, 1); /* 32 MHz TSF incr */
728 OS_REG_RMW_FIELD(ah
, AR_USEC
, AR_USEC_USEC32
,
729 IS_RAD5112_ANY(ah
) || IS_5413(ah
) ? 39 : 31);
732 * Restore BB registers to power-on defaults
734 OS_REG_WRITE(ah
, AR_PHY_SLEEP_CTR_CONTROL
, 0x1f);
735 OS_REG_WRITE(ah
, AR_PHY_SLEEP_CTR_LIMIT
, 0x7f);
736 OS_REG_WRITE(ah
, AR_PHY_SLEEP_SCAL
, 0x0e);
737 OS_REG_WRITE(ah
, AR_PHY_M_SLEEP
, 0x0c);
738 OS_REG_WRITE(ah
, AR_PHY_REFCLKDLY
, 0xff);
739 OS_REG_WRITE(ah
, AR_PHY_REFCLKPD
,
740 IS_RAD5112_ANY(ah
) || IS_5413(ah
) ? 0x14 : 0x18);
745 * Adjust NF based on statistical values for 5GHz frequencies.
746 * Default method: this may be overridden by the rf backend.
749 ar5212GetNfAdjust(struct ath_hal
*ah
, const HAL_CHANNEL_INTERNAL
*c
)
751 static const struct {
755 { 5790, 11 }, /* NB: ordered high -> low */
769 for (i
= 0; c
->channel
<= adjustDef
[i
].freqLow
; i
++)
771 return adjustDef
[i
].adjust
;
775 ar5212GetCapability(struct ath_hal
*ah
, HAL_CAPABILITY_TYPE type
,
776 uint32_t capability
, uint32_t *result
)
778 #define MACVERSION(ah) AH_PRIVATE(ah)->ah_macVersion
779 struct ath_hal_5212
*ahp
= AH5212(ah
);
780 const HAL_CAPABILITIES
*pCap
= &AH_PRIVATE(ah
)->ah_caps
;
781 const struct ar5212AniState
*ani
;
784 case HAL_CAP_CIPHER
: /* cipher handled in hardware */
785 switch (capability
) {
786 case HAL_CIPHER_AES_CCM
:
787 return pCap
->halCipherAesCcmSupport
?
788 HAL_OK
: HAL_ENOTSUPP
;
789 case HAL_CIPHER_AES_OCB
:
790 case HAL_CIPHER_TKIP
:
798 case HAL_CAP_TKIP_MIC
: /* handle TKIP MIC in hardware */
799 switch (capability
) {
800 case 0: /* hardware capability */
803 return (ahp
->ah_staId1Defaults
&
804 AR_STA_ID1_CRPT_MIC_ENABLE
) ? HAL_OK
: HAL_ENXIO
;
806 case HAL_CAP_TKIP_SPLIT
: /* hardware TKIP uses split keys */
807 switch (capability
) {
808 case 0: /* hardware capability */
809 return pCap
->halTkipMicTxRxKeySupport
?
811 case 1: /* current setting */
812 return (ahp
->ah_miscMode
&
813 AR_MISC_MODE_MIC_NEW_LOC_ENABLE
) ? HAL_ENXIO
: HAL_OK
;
816 case HAL_CAP_WME_TKIPMIC
: /* hardware can do TKIP MIC w/ WMM */
817 /* XXX move to capability bit */
818 return MACVERSION(ah
) > AR_SREV_VERSION_VENICE
||
819 (MACVERSION(ah
) == AR_SREV_VERSION_VENICE
&&
820 AH_PRIVATE(ah
)->ah_macRev
>= 8) ? HAL_OK
: HAL_ENOTSUPP
;
821 case HAL_CAP_DIVERSITY
: /* hardware supports fast diversity */
822 switch (capability
) {
823 case 0: /* hardware capability */
825 case 1: /* current setting */
826 return ahp
->ah_diversity
? HAL_OK
: HAL_ENXIO
;
830 *result
= AH_PRIVATE(ah
)->ah_diagreg
;
833 switch (capability
) {
834 case 0: /* hardware capability */
837 return ahp
->ah_tpcEnabled
? HAL_OK
: HAL_ENXIO
;
840 case HAL_CAP_PHYDIAG
: /* radar pulse detection capability */
841 switch (capability
) {
843 return ath_hal_eepromGetFlag(ah
, AR_EEP_AMODE
) ?
846 return (ath_hal_eepromGetFlag(ah
, AR_EEP_GMODE
) ||
847 ath_hal_eepromGetFlag(ah
, AR_EEP_BMODE
)) ?
851 case HAL_CAP_MCAST_KEYSRCH
: /* multicast frame keycache search */
852 switch (capability
) {
853 case 0: /* hardware capability */
856 return (ahp
->ah_staId1Defaults
&
857 AR_STA_ID1_MCAST_KSRCH
) ? HAL_OK
: HAL_ENXIO
;
860 case HAL_CAP_TSF_ADJUST
: /* hardware has beacon tsf adjust */
861 switch (capability
) {
862 case 0: /* hardware capability */
863 return pCap
->halTsfAddSupport
? HAL_OK
: HAL_ENOTSUPP
;
865 return (ahp
->ah_miscMode
& AR_MISC_MODE_TX_ADD_TSF
) ?
869 case HAL_CAP_TPC_ACK
:
870 *result
= MS(ahp
->ah_macTPC
, AR_TPC_ACK
);
872 case HAL_CAP_TPC_CTS
:
873 *result
= MS(ahp
->ah_macTPC
, AR_TPC_CTS
);
875 case HAL_CAP_INTMIT
: /* interference mitigation */
876 switch (capability
) {
877 case 0: /* hardware capability */
880 return (ahp
->ah_procPhyErr
& HAL_ANI_ENA
) ?
882 case 2: /* HAL_ANI_NOISE_IMMUNITY_LEVEL */
883 case 3: /* HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION */
884 case 4: /* HAL_ANI_CCK_WEAK_SIGNAL_THR */
885 case 5: /* HAL_ANI_FIRSTEP_LEVEL */
886 case 6: /* HAL_ANI_SPUR_IMMUNITY_LEVEL */
887 ani
= ar5212AniGetCurrentState(ah
);
890 switch (capability
) {
891 case 2: *result
= ani
->noiseImmunityLevel
; break;
892 case 3: *result
= !ani
->ofdmWeakSigDetectOff
; break;
893 case 4: *result
= ani
->cckWeakSigThreshold
; break;
894 case 5: *result
= ani
->firstepLevel
; break;
895 case 6: *result
= ani
->spurImmunityLevel
; break;
901 return ath_hal_getcapability(ah
, type
, capability
, result
);
907 ar5212SetCapability(struct ath_hal
*ah
, HAL_CAPABILITY_TYPE type
,
908 uint32_t capability
, uint32_t setting
, HAL_STATUS
*status
)
910 #define N(a) (sizeof(a)/sizeof(a[0]))
911 struct ath_hal_5212
*ahp
= AH5212(ah
);
912 const HAL_CAPABILITIES
*pCap
= &AH_PRIVATE(ah
)->ah_caps
;
916 case HAL_CAP_TKIP_MIC
: /* handle TKIP MIC in hardware */
918 ahp
->ah_staId1Defaults
|= AR_STA_ID1_CRPT_MIC_ENABLE
;
920 ahp
->ah_staId1Defaults
&= ~AR_STA_ID1_CRPT_MIC_ENABLE
;
922 case HAL_CAP_TKIP_SPLIT
: /* hardware TKIP uses split keys */
923 if (!pCap
->halTkipMicTxRxKeySupport
)
925 /* NB: true =>'s use split key cache layout */
927 ahp
->ah_miscMode
&= ~AR_MISC_MODE_MIC_NEW_LOC_ENABLE
;
929 ahp
->ah_miscMode
|= AR_MISC_MODE_MIC_NEW_LOC_ENABLE
;
930 /* NB: write here so keys can be setup w/o a reset */
931 OS_REG_WRITE(ah
, AR_MISC_MODE
, ahp
->ah_miscMode
);
933 case HAL_CAP_DIVERSITY
:
934 if (ahp
->ah_phyPowerOn
) {
935 v
= OS_REG_READ(ah
, AR_PHY_CCK_DETECT
);
937 v
|= AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV
;
939 v
&= ~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV
;
940 OS_REG_WRITE(ah
, AR_PHY_CCK_DETECT
, v
);
942 ahp
->ah_diversity
= (setting
!= 0);
944 case HAL_CAP_DIAG
: /* hardware diagnostic support */
946 * NB: could split this up into virtual capabilities,
947 * (e.g. 1 => ACK, 2 => CTS, etc.) but it hardly
948 * seems worth the additional complexity.
950 AH_PRIVATE(ah
)->ah_diagreg
= setting
;
951 OS_REG_WRITE(ah
, AR_DIAG_SW
, AH_PRIVATE(ah
)->ah_diagreg
);
954 ahp
->ah_tpcEnabled
= (setting
!= 0);
956 case HAL_CAP_MCAST_KEYSRCH
: /* multicast frame keycache search */
958 ahp
->ah_staId1Defaults
|= AR_STA_ID1_MCAST_KSRCH
;
960 ahp
->ah_staId1Defaults
&= ~AR_STA_ID1_MCAST_KSRCH
;
962 case HAL_CAP_TPC_ACK
:
963 case HAL_CAP_TPC_CTS
:
964 setting
+= ahp
->ah_txPowerIndexOffset
;
967 if (type
== HAL_CAP_TPC_ACK
) {
968 ahp
->ah_macTPC
&= AR_TPC_ACK
;
969 ahp
->ah_macTPC
|= MS(setting
, AR_TPC_ACK
);
971 ahp
->ah_macTPC
&= AR_TPC_CTS
;
972 ahp
->ah_macTPC
|= MS(setting
, AR_TPC_CTS
);
974 OS_REG_WRITE(ah
, AR_TPC
, ahp
->ah_macTPC
);
976 case HAL_CAP_INTMIT
: { /* interference mitigation */
977 static const HAL_ANI_CMD cmds
[] = {
980 HAL_ANI_NOISE_IMMUNITY_LEVEL
,
981 HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION
,
982 HAL_ANI_CCK_WEAK_SIGNAL_THR
,
983 HAL_ANI_FIRSTEP_LEVEL
,
984 HAL_ANI_SPUR_IMMUNITY_LEVEL
,
986 return capability
< N(cmds
) ?
987 ar5212AniControl(ah
, cmds
[capability
], setting
) :
990 case HAL_CAP_TSF_ADJUST
: /* hardware has beacon tsf adjust */
991 if (pCap
->halTsfAddSupport
) {
993 ahp
->ah_miscMode
|= AR_MISC_MODE_TX_ADD_TSF
;
995 ahp
->ah_miscMode
&= ~AR_MISC_MODE_TX_ADD_TSF
;
1000 return ath_hal_setcapability(ah
, type
, capability
,
1007 ar5212GetDiagState(struct ath_hal
*ah
, int request
,
1008 const void *args
, uint32_t argsize
,
1009 void **result
, uint32_t *resultsize
)
1011 struct ath_hal_5212
*ahp
= AH5212(ah
);
1014 if (ath_hal_getdiagstate(ah
, request
, args
, argsize
, result
, resultsize
))
1017 case HAL_DIAG_EEPROM
:
1018 case HAL_DIAG_EEPROM_EXP_11A
:
1019 case HAL_DIAG_EEPROM_EXP_11B
:
1020 case HAL_DIAG_EEPROM_EXP_11G
:
1021 case HAL_DIAG_RFGAIN
:
1022 return ath_hal_eepromDiag(ah
, request
,
1023 args
, argsize
, result
, resultsize
);
1024 case HAL_DIAG_RFGAIN_CURSTEP
:
1025 *result
= __DECONST(void *, ahp
->ah_gainValues
.currStep
);
1026 *resultsize
= (*result
== AH_NULL
) ?
1027 0 : sizeof(GAIN_OPTIMIZATION_STEP
);
1029 case HAL_DIAG_PCDAC
:
1030 *result
= ahp
->ah_pcdacTable
;
1031 *resultsize
= ahp
->ah_pcdacTableSize
;
1033 case HAL_DIAG_TXRATES
:
1034 *result
= &ahp
->ah_ratesArray
[0];
1035 *resultsize
= sizeof(ahp
->ah_ratesArray
);
1037 case HAL_DIAG_ANI_CURRENT
:
1038 *result
= ar5212AniGetCurrentState(ah
);
1039 *resultsize
= (*result
== AH_NULL
) ?
1040 0 : sizeof(struct ar5212AniState
);
1042 case HAL_DIAG_ANI_STATS
:
1043 *result
= ar5212AniGetCurrentStats(ah
);
1044 *resultsize
= (*result
== AH_NULL
) ?
1045 0 : sizeof(struct ar5212Stats
);
1047 case HAL_DIAG_ANI_CMD
:
1048 if (argsize
!= 2*sizeof(uint32_t))
1050 ar5212AniControl(ah
, ((const uint32_t *)args
)[0],
1051 ((const uint32_t *)args
)[1]);
1053 case HAL_DIAG_ANI_PARAMS
:
1055 * NB: We assume struct ar5212AniParams is identical
1056 * to HAL_ANI_PARAMS; if they diverge then we'll need
1059 if (argsize
== 0 && args
== AH_NULL
) {
1060 struct ar5212AniState
*aniState
=
1061 ar5212AniGetCurrentState(ah
);
1062 if (aniState
== AH_NULL
)
1064 *result
= __DECONST(void *, aniState
->params
);
1065 *resultsize
= sizeof(struct ar5212AniParams
);
1068 if (argsize
!= sizeof(struct ar5212AniParams
))
1070 return ar5212AniSetParams(ah
, args
, args
);