2 * Copyright (c) 2002-2009 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.
22 #include "ah_internal.h"
24 #include "ah_desc.h" /* NB: for HAL_PHYERR* */
26 #include "ar5212/ar5212.h"
27 #include "ar5212/ar5212reg.h"
28 #include "ar5212/ar5212phy.h"
30 #include "ah_eeprom_v3.h"
32 #define AR_NUM_GPIO 6 /* 6 GPIO pins */
33 #define AR_GPIOD_MASK 0x0000002F /* GPIO data reg r/w mask */
36 ar5212GetMacAddress(struct ath_hal *ah, uint8_t *mac)
38 struct ath_hal_5212 *ahp = AH5212(ah);
40 OS_MEMCPY(mac, ahp->ah_macaddr, IEEE80211_ADDR_LEN);
44 ar5212SetMacAddress(struct ath_hal *ah, const uint8_t *mac)
46 struct ath_hal_5212 *ahp = AH5212(ah);
48 OS_MEMCPY(ahp->ah_macaddr, mac, IEEE80211_ADDR_LEN);
53 ar5212GetBssIdMask(struct ath_hal *ah, uint8_t *mask)
55 struct ath_hal_5212 *ahp = AH5212(ah);
57 OS_MEMCPY(mask, ahp->ah_bssidmask, IEEE80211_ADDR_LEN);
61 ar5212SetBssIdMask(struct ath_hal *ah, const uint8_t *mask)
63 struct ath_hal_5212 *ahp = AH5212(ah);
65 /* save it since it must be rewritten on reset */
66 OS_MEMCPY(ahp->ah_bssidmask, mask, IEEE80211_ADDR_LEN);
68 OS_REG_WRITE(ah, AR_BSSMSKL, LE_READ_4(ahp->ah_bssidmask));
69 OS_REG_WRITE(ah, AR_BSSMSKU, LE_READ_2(ahp->ah_bssidmask + 4));
74 * Attempt to change the cards operating regulatory domain to the given value
77 ar5212SetRegulatoryDomain(struct ath_hal *ah,
78 uint16_t regDomain, HAL_STATUS *status)
82 if (AH_PRIVATE(ah)->ah_currentRD == regDomain) {
86 if (ath_hal_eepromGetFlag(ah, AR_EEP_WRITEPROTECT)) {
90 #ifdef AH_SUPPORT_WRITE_REGDOMAIN
91 if (ath_hal_eepromWrite(ah, AR_EEPROM_REG_DOMAIN, regDomain)) {
92 HALDEBUG(ah, HAL_DEBUG_ANY,
93 "%s: set regulatory domain to %u (0x%x)\n",
94 __func__, regDomain, regDomain);
95 AH_PRIVATE(ah)->ah_currentRD = regDomain;
107 * Return the wireless modes (a,b,g,t) supported by hardware.
109 * This value is what is actually supported by the hardware
110 * and is unaffected by regulatory/country code settings.
113 ar5212GetWirelessModes(struct ath_hal *ah)
117 if (ath_hal_eepromGetFlag(ah, AR_EEP_AMODE)) {
119 if (!ath_hal_eepromGetFlag(ah, AR_EEP_TURBO5DISABLE))
120 mode |= HAL_MODE_TURBO | HAL_MODE_108A;
121 if (AH_PRIVATE(ah)->ah_caps.halChanHalfRate)
122 mode |= HAL_MODE_11A_HALF_RATE;
123 if (AH_PRIVATE(ah)->ah_caps.halChanQuarterRate)
124 mode |= HAL_MODE_11A_QUARTER_RATE;
126 if (ath_hal_eepromGetFlag(ah, AR_EEP_BMODE))
127 mode |= HAL_MODE_11B;
128 if (ath_hal_eepromGetFlag(ah, AR_EEP_GMODE) &&
129 AH_PRIVATE(ah)->ah_subvendorid != AR_SUBVENDOR_ID_NOG) {
130 mode |= HAL_MODE_11G;
131 if (!ath_hal_eepromGetFlag(ah, AR_EEP_TURBO2DISABLE))
132 mode |= HAL_MODE_108G;
133 if (AH_PRIVATE(ah)->ah_caps.halChanHalfRate)
134 mode |= HAL_MODE_11G_HALF_RATE;
135 if (AH_PRIVATE(ah)->ah_caps.halChanQuarterRate)
136 mode |= HAL_MODE_11G_QUARTER_RATE;
142 * Set the interrupt and GPIO values so the ISR can disable RF
143 * on a switch signal. Assumes GPIO port and interrupt polarity
144 * are set prior to call.
147 ar5212EnableRfKill(struct ath_hal *ah)
149 uint16_t rfsilent = AH_PRIVATE(ah)->ah_rfsilent;
150 int select = MS(rfsilent, AR_EEPROM_RFSILENT_GPIO_SEL);
151 int polarity = MS(rfsilent, AR_EEPROM_RFSILENT_POLARITY);
154 * Configure the desired GPIO port for input
155 * and enable baseband rf silence.
157 ath_hal_gpioCfgInput(ah, select);
158 OS_REG_SET_BIT(ah, AR_PHY(0), 0x00002000);
160 * If radio disable switch connection to GPIO bit x is enabled
161 * program GPIO interrupt.
162 * If rfkill bit on eeprom is 1, setupeeprommap routine has already
163 * verified that it is a later version of eeprom, it has a place for
164 * rfkill bit and it is set to 1, indicating that GPIO bit x hardware
165 * connection is present.
167 ath_hal_gpioSetIntr(ah, select,
168 (ath_hal_gpioGet(ah, select) == polarity ? !polarity : polarity));
172 * Change the LED blinking pattern to correspond to the connectivity
175 ar5212SetLedState(struct ath_hal *ah, HAL_LED_STATE state)
177 static const uint32_t ledbits[8] = {
178 AR_PCICFG_LEDCTL_NONE, /* HAL_LED_INIT */
179 AR_PCICFG_LEDCTL_PEND, /* HAL_LED_SCAN */
180 AR_PCICFG_LEDCTL_PEND, /* HAL_LED_AUTH */
181 AR_PCICFG_LEDCTL_ASSOC, /* HAL_LED_ASSOC*/
182 AR_PCICFG_LEDCTL_ASSOC, /* HAL_LED_RUN */
183 AR_PCICFG_LEDCTL_NONE,
184 AR_PCICFG_LEDCTL_NONE,
185 AR_PCICFG_LEDCTL_NONE,
189 bits = OS_REG_READ(ah, AR_PCICFG);
192 * Enable LED for Nala. There is a bit marked reserved
193 * that must be set and we also turn on the power led.
194 * Because we mark s/w LED control setting the control
195 * status bits below is meangless (the driver must flash
196 * the LED(s) using the GPIO lines).
198 bits = (bits &~ AR_PCICFG_LEDMODE)
199 | SM(AR_PCICFG_LEDMODE_POWON, AR_PCICFG_LEDMODE)
201 | SM(AR_PCICFG_LEDMODE_NETON, AR_PCICFG_LEDMODE)
205 bits = (bits &~ AR_PCICFG_LEDCTL)
206 | SM(ledbits[state & 0x7], AR_PCICFG_LEDCTL);
207 OS_REG_WRITE(ah, AR_PCICFG, bits);
211 * Change association related fields programmed into the hardware.
212 * Writing a valid BSSID to the hardware effectively enables the hardware
213 * to synchronize its TSF to the correct beacons and receive frames coming
214 * from that BSSID. It is called by the SME JOIN operation.
217 ar5212WriteAssocid(struct ath_hal *ah, const uint8_t *bssid, uint16_t assocId)
219 struct ath_hal_5212 *ahp = AH5212(ah);
221 /* save bssid for possible re-use on reset */
222 OS_MEMCPY(ahp->ah_bssid, bssid, IEEE80211_ADDR_LEN);
223 ahp->ah_assocId = assocId;
224 OS_REG_WRITE(ah, AR_BSS_ID0, LE_READ_4(ahp->ah_bssid));
225 OS_REG_WRITE(ah, AR_BSS_ID1, LE_READ_2(ahp->ah_bssid+4) |
226 ((assocId & 0x3fff)<<AR_BSS_ID1_AID_S));
230 * Get the current hardware tsf for stamlme
233 ar5212GetTsf64(struct ath_hal *ah)
235 uint32_t low1, low2, u32;
237 /* sync multi-word read */
238 low1 = OS_REG_READ(ah, AR_TSF_L32);
239 u32 = OS_REG_READ(ah, AR_TSF_U32);
240 low2 = OS_REG_READ(ah, AR_TSF_L32);
241 if (low2 < low1) { /* roll over */
243 * If we are not preempted this will work. If we are
244 * then we re-reading AR_TSF_U32 does no good as the
245 * low bits will be meaningless. Likewise reading
246 * L32, U32, U32, then comparing the last two reads
247 * to check for rollover doesn't help if preempted--so
248 * we take this approach as it costs one less PCI read
249 * which can be noticeable when doing things like
250 * timestamping packets in monitor mode.
254 return (((uint64_t) u32) << 32) | ((uint64_t) low2);
258 * Get the current hardware tsf for stamlme
261 ar5212GetTsf32(struct ath_hal *ah)
263 return OS_REG_READ(ah, AR_TSF_L32);
267 ar5212SetTsf64(struct ath_hal *ah, uint64_t tsf64)
269 OS_REG_WRITE(ah, AR_TSF_L32, tsf64 & 0xffffffff);
270 OS_REG_WRITE(ah, AR_TSF_U32, (tsf64 >> 32) & 0xffffffff);
274 * Reset the current hardware tsf for stamlme.
277 ar5212ResetTsf(struct ath_hal *ah)
280 uint32_t val = OS_REG_READ(ah, AR_BEACON);
282 OS_REG_WRITE(ah, AR_BEACON, val | AR_BEACON_RESET_TSF);
284 * When resetting the TSF, write twice to the
285 * corresponding register; each write to the RESET_TSF bit toggles
286 * the internal signal to cause a reset of the TSF - but if the signal
287 * is left high, it will reset the TSF on the next chip reset also!
288 * writing the bit an even number of times fixes this issue
290 OS_REG_WRITE(ah, AR_BEACON, val | AR_BEACON_RESET_TSF);
294 * Set or clear hardware basic rate bit
295 * Set hardware basic rate set if basic rate is found
296 * and basic rate is equal or less than 2Mbps
299 ar5212SetBasicRate(struct ath_hal *ah, HAL_RATE_SET *rs)
301 const struct ieee80211_channel *chan = AH_PRIVATE(ah)->ah_curchan;
306 if (chan == AH_NULL || !IEEE80211_IS_CHAN_CCK(chan))
309 for (i = 0; i < rs->rs_count; i++) {
310 uint8_t rset = rs->rs_rates[i];
311 /* Basic rate defined? */
312 if ((rset & 0x80) && (rset &= 0x7f) >= xset)
316 * Set the h/w bit to reflect whether or not the basic
317 * rate is found to be equal or less than 2Mbps.
319 reg = OS_REG_READ(ah, AR_STA_ID1);
320 if (xset && xset/2 <= 2)
321 OS_REG_WRITE(ah, AR_STA_ID1, reg | AR_STA_ID1_BASE_RATE_11B);
323 OS_REG_WRITE(ah, AR_STA_ID1, reg &~ AR_STA_ID1_BASE_RATE_11B);
327 * Grab a semi-random value from hardware registers - may not
331 ar5212GetRandomSeed(struct ath_hal *ah)
335 nf = (OS_REG_READ(ah, AR_PHY(25)) >> 19) & 0x1ff;
337 nf = 0 - ((nf ^ 0x1ff) + 1);
338 return (OS_REG_READ(ah, AR_TSF_U32) ^
339 OS_REG_READ(ah, AR_TSF_L32) ^ nf);
343 * Detect if our card is present
346 ar5212DetectCardPresent(struct ath_hal *ah)
348 uint16_t macVersion, macRev;
352 * Read the Silicon Revision register and compare that
353 * to what we read at attach time. If the same, we say
354 * a card/device is present.
356 v = OS_REG_READ(ah, AR_SREV) & AR_SREV_ID;
357 macVersion = v >> AR_SREV_ID_S;
358 macRev = v & AR_SREV_REVISION;
359 return (AH_PRIVATE(ah)->ah_macVersion == macVersion &&
360 AH_PRIVATE(ah)->ah_macRev == macRev);
364 ar5212EnableMibCounters(struct ath_hal *ah)
366 /* NB: this just resets the mib counter machinery */
367 OS_REG_WRITE(ah, AR_MIBC,
368 ~(AR_MIBC_COW | AR_MIBC_FMC | AR_MIBC_CMC | AR_MIBC_MCS) & 0x0f);
372 ar5212DisableMibCounters(struct ath_hal *ah)
374 OS_REG_WRITE(ah, AR_MIBC, AR_MIBC | AR_MIBC_CMC);
378 * Update MIB Counters
381 ar5212UpdateMibCounters(struct ath_hal *ah, HAL_MIB_STATS* stats)
383 stats->ackrcv_bad += OS_REG_READ(ah, AR_ACK_FAIL);
384 stats->rts_bad += OS_REG_READ(ah, AR_RTS_FAIL);
385 stats->fcs_bad += OS_REG_READ(ah, AR_FCS_FAIL);
386 stats->rts_good += OS_REG_READ(ah, AR_RTS_OK);
387 stats->beacons += OS_REG_READ(ah, AR_BEACON_CNT);
391 * Detect if the HW supports spreading a CCK signal on channel 14
394 ar5212IsJapanChannelSpreadSupported(struct ath_hal *ah)
400 * Get the rssi of frame curently being received.
403 ar5212GetCurRssi(struct ath_hal *ah)
405 return (OS_REG_READ(ah, AR_PHY_CURRENT_RSSI) & 0xff);
409 ar5212GetDefAntenna(struct ath_hal *ah)
411 return (OS_REG_READ(ah, AR_DEF_ANTENNA) & 0x7);
415 ar5212SetDefAntenna(struct ath_hal *ah, u_int antenna)
417 OS_REG_WRITE(ah, AR_DEF_ANTENNA, (antenna & 0x7));
421 ar5212GetAntennaSwitch(struct ath_hal *ah)
423 return AH5212(ah)->ah_antControl;
427 ar5212SetAntennaSwitch(struct ath_hal *ah, HAL_ANT_SETTING setting)
429 struct ath_hal_5212 *ahp = AH5212(ah);
430 const struct ieee80211_channel *chan = AH_PRIVATE(ah)->ah_curchan;
432 if (!ahp->ah_phyPowerOn || chan == AH_NULL) {
433 /* PHY powered off, just stash settings */
434 ahp->ah_antControl = setting;
435 ahp->ah_diversity = (setting == HAL_ANT_VARIABLE);
438 return ar5212SetAntennaSwitchInternal(ah, setting, chan);
442 ar5212IsSleepAfterBeaconBroken(struct ath_hal *ah)
448 ar5212SetSifsTime(struct ath_hal *ah, u_int us)
450 struct ath_hal_5212 *ahp = AH5212(ah);
452 if (us > ath_hal_mac_usec(ah, 0xffff)) {
453 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad SIFS time %u\n",
455 ahp->ah_sifstime = (u_int) -1; /* restore default handling */
458 /* convert to system clocks */
459 OS_REG_WRITE(ah, AR_D_GBL_IFS_SIFS, ath_hal_mac_clks(ah, us-2));
460 ahp->ah_sifstime = us;
466 ar5212GetSifsTime(struct ath_hal *ah)
468 u_int clks = OS_REG_READ(ah, AR_D_GBL_IFS_SIFS) & 0xffff;
469 return ath_hal_mac_usec(ah, clks)+2; /* convert from system clocks */
473 ar5212SetSlotTime(struct ath_hal *ah, u_int us)
475 struct ath_hal_5212 *ahp = AH5212(ah);
477 if (us < HAL_SLOT_TIME_6 || us > ath_hal_mac_usec(ah, 0xffff)) {
478 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad slot time %u\n",
480 ahp->ah_slottime = (u_int) -1; /* restore default handling */
483 /* convert to system clocks */
484 OS_REG_WRITE(ah, AR_D_GBL_IFS_SLOT, ath_hal_mac_clks(ah, us));
485 ahp->ah_slottime = us;
491 ar5212GetSlotTime(struct ath_hal *ah)
493 u_int clks = OS_REG_READ(ah, AR_D_GBL_IFS_SLOT) & 0xffff;
494 return ath_hal_mac_usec(ah, clks); /* convert from system clocks */
498 ar5212SetAckTimeout(struct ath_hal *ah, u_int us)
500 struct ath_hal_5212 *ahp = AH5212(ah);
502 if (us > ath_hal_mac_usec(ah, MS(0xffffffff, AR_TIME_OUT_ACK))) {
503 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad ack timeout %u\n",
505 ahp->ah_acktimeout = (u_int) -1; /* restore default handling */
508 /* convert to system clocks */
509 OS_REG_RMW_FIELD(ah, AR_TIME_OUT,
510 AR_TIME_OUT_ACK, ath_hal_mac_clks(ah, us));
511 ahp->ah_acktimeout = us;
517 ar5212GetAckTimeout(struct ath_hal *ah)
519 u_int clks = MS(OS_REG_READ(ah, AR_TIME_OUT), AR_TIME_OUT_ACK);
520 return ath_hal_mac_usec(ah, clks); /* convert from system clocks */
524 ar5212GetAckCTSRate(struct ath_hal *ah)
526 return ((AH5212(ah)->ah_staId1Defaults & AR_STA_ID1_ACKCTS_6MB) == 0);
530 ar5212SetAckCTSRate(struct ath_hal *ah, u_int high)
532 struct ath_hal_5212 *ahp = AH5212(ah);
535 OS_REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_ACKCTS_6MB);
536 ahp->ah_staId1Defaults &= ~AR_STA_ID1_ACKCTS_6MB;
538 OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_ACKCTS_6MB);
539 ahp->ah_staId1Defaults |= AR_STA_ID1_ACKCTS_6MB;
545 ar5212SetCTSTimeout(struct ath_hal *ah, u_int us)
547 struct ath_hal_5212 *ahp = AH5212(ah);
549 if (us > ath_hal_mac_usec(ah, MS(0xffffffff, AR_TIME_OUT_CTS))) {
550 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad cts timeout %u\n",
552 ahp->ah_ctstimeout = (u_int) -1; /* restore default handling */
555 /* convert to system clocks */
556 OS_REG_RMW_FIELD(ah, AR_TIME_OUT,
557 AR_TIME_OUT_CTS, ath_hal_mac_clks(ah, us));
558 ahp->ah_ctstimeout = us;
564 ar5212GetCTSTimeout(struct ath_hal *ah)
566 u_int clks = MS(OS_REG_READ(ah, AR_TIME_OUT), AR_TIME_OUT_CTS);
567 return ath_hal_mac_usec(ah, clks); /* convert from system clocks */
570 /* Setup decompression for given key index */
572 ar5212SetDecompMask(struct ath_hal *ah, uint16_t keyidx, int en)
574 struct ath_hal_5212 *ahp = AH5212(ah);
576 if (keyidx >= HAL_DECOMP_MASK_SIZE)
578 OS_REG_WRITE(ah, AR_DCM_A, keyidx);
579 OS_REG_WRITE(ah, AR_DCM_D, en ? AR_DCM_D_EN : 0);
580 ahp->ah_decompMask[keyidx] = en;
585 /* Setup coverage class */
587 ar5212SetCoverageClass(struct ath_hal *ah, uint8_t coverageclass, int now)
589 uint32_t slot, timeout, eifs;
592 AH_PRIVATE(ah)->ah_coverageClass = coverageclass;
595 if (AH_PRIVATE(ah)->ah_coverageClass == 0)
598 /* Don't apply coverage class to non A channels */
599 if (!IEEE80211_IS_CHAN_A(AH_PRIVATE(ah)->ah_curchan))
602 /* Get core clock rate */
603 clkRate = ath_hal_mac_clks(ah, 1);
606 slot = coverageclass * 3 * clkRate;
607 eifs = coverageclass * 6 * clkRate;
608 if (IEEE80211_IS_CHAN_HALF(AH_PRIVATE(ah)->ah_curchan)) {
609 slot += IFS_SLOT_HALF_RATE;
610 eifs += IFS_EIFS_HALF_RATE;
611 } else if (IEEE80211_IS_CHAN_QUARTER(AH_PRIVATE(ah)->ah_curchan)) {
612 slot += IFS_SLOT_QUARTER_RATE;
613 eifs += IFS_EIFS_QUARTER_RATE;
614 } else { /* full rate */
615 slot += IFS_SLOT_FULL_RATE;
616 eifs += IFS_EIFS_FULL_RATE;
620 * Add additional time for air propagation for ACK and CTS
621 * timeouts. This value is in core clocks.
623 timeout = ACK_CTS_TIMEOUT_11A + (coverageclass * 3 * clkRate);
626 * Write the values: slot, eifs, ack/cts timeouts.
628 OS_REG_WRITE(ah, AR_D_GBL_IFS_SLOT, slot);
629 OS_REG_WRITE(ah, AR_D_GBL_IFS_EIFS, eifs);
630 OS_REG_WRITE(ah, AR_TIME_OUT,
631 SM(timeout, AR_TIME_OUT_CTS)
632 | SM(timeout, AR_TIME_OUT_ACK));
637 ar5212SetQuiet(struct ath_hal *ah, uint32_t period, uint32_t duration,
638 uint32_t nextStart, HAL_QUIET_FLAG flag)
640 OS_REG_WRITE(ah, AR_QUIET2, period | (duration << AR_QUIET2_QUIET_DUR_S));
641 if (flag & HAL_QUIET_ENABLE) {
642 OS_REG_WRITE(ah, AR_QUIET1, nextStart | (1 << 16));
645 OS_REG_WRITE(ah, AR_QUIET1, nextStart);
651 ar5212SetPCUConfig(struct ath_hal *ah)
653 ar5212SetOperatingMode(ah, AH_PRIVATE(ah)->ah_opmode);
657 * Return whether an external 32KHz crystal should be used
658 * to reduce power consumption when sleeping. We do so if
659 * the crystal is present (obtained from EEPROM) and if we
660 * are not running as an AP and are configured to use it.
663 ar5212Use32KHzclock(struct ath_hal *ah, HAL_OPMODE opmode)
665 if (opmode != HAL_M_HOSTAP) {
666 struct ath_hal_5212 *ahp = AH5212(ah);
667 return ath_hal_eepromGetFlag(ah, AR_EEP_32KHZCRYSTAL) &&
668 (ahp->ah_enable32kHzClock == USE_32KHZ ||
669 ahp->ah_enable32kHzClock == AUTO_32KHZ);
675 * If 32KHz clock exists, use it to lower power consumption during sleep
677 * Note: If clock is set to 32 KHz, delays on accessing certain
678 * baseband registers (27-31, 124-127) are required.
681 ar5212SetupClock(struct ath_hal *ah, HAL_OPMODE opmode)
683 if (ar5212Use32KHzclock(ah, opmode)) {
685 * Enable clocks to be turned OFF in BB during sleep
686 * and also enable turning OFF 32MHz/40MHz Refclk
689 OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_CONTROL, 0x1f);
690 OS_REG_WRITE(ah, AR_PHY_REFCLKPD,
691 IS_RAD5112_ANY(ah) || IS_5413(ah) ? 0x14 : 0x18);
692 OS_REG_RMW_FIELD(ah, AR_USEC, AR_USEC_USEC32, 1);
693 OS_REG_WRITE(ah, AR_TSF_PARM, 61); /* 32 KHz TSF incr */
694 OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_SEL, 1);
696 if (IS_2413(ah) || IS_5413(ah) || IS_2417(ah)) {
697 OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_LIMIT, 0x26);
698 OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0d);
699 OS_REG_WRITE(ah, AR_PHY_M_SLEEP, 0x07);
700 OS_REG_WRITE(ah, AR_PHY_REFCLKDLY, 0x3f);
701 /* # Set sleep clock rate to 32 KHz. */
702 OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_RATE_IND, 0x2);
704 OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_LIMIT, 0x0a);
705 OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0c);
706 OS_REG_WRITE(ah, AR_PHY_M_SLEEP, 0x03);
707 OS_REG_WRITE(ah, AR_PHY_REFCLKDLY, 0x20);
708 OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_RATE_IND, 0x3);
711 OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_RATE_IND, 0x0);
712 OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_SEL, 0);
714 OS_REG_WRITE(ah, AR_TSF_PARM, 1); /* 32MHz TSF inc */
716 OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_CONTROL, 0x1f);
717 OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_LIMIT, 0x7f);
720 OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0a);
721 else if (IS_HB63(ah))
722 OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x32);
724 OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0e);
725 OS_REG_WRITE(ah, AR_PHY_M_SLEEP, 0x0c);
726 OS_REG_WRITE(ah, AR_PHY_REFCLKDLY, 0xff);
727 OS_REG_WRITE(ah, AR_PHY_REFCLKPD,
728 IS_RAD5112_ANY(ah) || IS_5413(ah) || IS_2417(ah) ? 0x14 : 0x18);
729 OS_REG_RMW_FIELD(ah, AR_USEC, AR_USEC_USEC32,
730 IS_RAD5112_ANY(ah) || IS_5413(ah) ? 39 : 31);
735 * If 32KHz clock exists, turn it off and turn back on the 32Mhz
738 ar5212RestoreClock(struct ath_hal *ah, HAL_OPMODE opmode)
740 if (ar5212Use32KHzclock(ah, opmode)) {
741 /* # Set sleep clock rate back to 32 MHz. */
742 OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_RATE_IND, 0);
743 OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_SEL, 0);
745 OS_REG_WRITE(ah, AR_TSF_PARM, 1); /* 32 MHz TSF incr */
746 OS_REG_RMW_FIELD(ah, AR_USEC, AR_USEC_USEC32,
747 IS_RAD5112_ANY(ah) || IS_5413(ah) ? 39 : 31);
750 * Restore BB registers to power-on defaults
752 OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_CONTROL, 0x1f);
753 OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_LIMIT, 0x7f);
754 OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0e);
755 OS_REG_WRITE(ah, AR_PHY_M_SLEEP, 0x0c);
756 OS_REG_WRITE(ah, AR_PHY_REFCLKDLY, 0xff);
757 OS_REG_WRITE(ah, AR_PHY_REFCLKPD,
758 IS_RAD5112_ANY(ah) || IS_5413(ah) ? 0x14 : 0x18);
763 * Adjust NF based on statistical values for 5GHz frequencies.
764 * Default method: this may be overridden by the rf backend.
767 ar5212GetNfAdjust(struct ath_hal *ah, const HAL_CHANNEL_INTERNAL *c)
769 static const struct {
773 { 5790, 11 }, /* NB: ordered high -> low */
787 for (i = 0; c->channel <= adjustDef[i].freqLow; i++)
789 return adjustDef[i].adjust;
793 ar5212GetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
794 uint32_t capability, uint32_t *result)
796 #define MACVERSION(ah) AH_PRIVATE(ah)->ah_macVersion
797 struct ath_hal_5212 *ahp = AH5212(ah);
798 const HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps;
799 const struct ar5212AniState *ani;
802 case HAL_CAP_CIPHER: /* cipher handled in hardware */
803 switch (capability) {
804 case HAL_CIPHER_AES_CCM:
805 return pCap->halCipherAesCcmSupport ?
806 HAL_OK : HAL_ENOTSUPP;
807 case HAL_CIPHER_AES_OCB:
808 case HAL_CIPHER_TKIP:
816 case HAL_CAP_TKIP_MIC: /* handle TKIP MIC in hardware */
817 switch (capability) {
818 case 0: /* hardware capability */
821 return (ahp->ah_staId1Defaults &
822 AR_STA_ID1_CRPT_MIC_ENABLE) ? HAL_OK : HAL_ENXIO;
825 case HAL_CAP_TKIP_SPLIT: /* hardware TKIP uses split keys */
826 switch (capability) {
827 case 0: /* hardware capability */
828 return pCap->halTkipMicTxRxKeySupport ?
830 case 1: /* current setting */
831 return (ahp->ah_miscMode &
832 AR_MISC_MODE_MIC_NEW_LOC_ENABLE) ? HAL_ENXIO : HAL_OK;
835 case HAL_CAP_WME_TKIPMIC: /* hardware can do TKIP MIC w/ WMM */
836 /* XXX move to capability bit */
837 return MACVERSION(ah) > AR_SREV_VERSION_VENICE ||
838 (MACVERSION(ah) == AR_SREV_VERSION_VENICE &&
839 AH_PRIVATE(ah)->ah_macRev >= 8) ? HAL_OK : HAL_ENOTSUPP;
840 case HAL_CAP_DIVERSITY: /* hardware supports fast diversity */
841 switch (capability) {
842 case 0: /* hardware capability */
844 case 1: /* current setting */
845 return ahp->ah_diversity ? HAL_OK : HAL_ENXIO;
846 case HAL_CAP_STRONG_DIV:
847 *result = OS_REG_READ(ah, AR_PHY_RESTART);
848 *result = MS(*result, AR_PHY_RESTART_DIV_GC);
853 *result = AH_PRIVATE(ah)->ah_diagreg;
856 switch (capability) {
857 case 0: /* hardware capability */
860 return ahp->ah_tpcEnabled ? HAL_OK : HAL_ENXIO;
863 case HAL_CAP_PHYDIAG: /* radar pulse detection capability */
864 switch (capability) {
866 return ath_hal_eepromGetFlag(ah, AR_EEP_AMODE) ?
869 return (ath_hal_eepromGetFlag(ah, AR_EEP_GMODE) ||
870 ath_hal_eepromGetFlag(ah, AR_EEP_BMODE)) ?
874 case HAL_CAP_MCAST_KEYSRCH: /* multicast frame keycache search */
875 switch (capability) {
876 case 0: /* hardware capability */
877 return pCap->halMcastKeySrchSupport ? HAL_OK : HAL_ENXIO;
879 return (ahp->ah_staId1Defaults &
880 AR_STA_ID1_MCAST_KSRCH) ? HAL_OK : HAL_ENXIO;
883 case HAL_CAP_TSF_ADJUST: /* hardware has beacon tsf adjust */
884 switch (capability) {
885 case 0: /* hardware capability */
886 return pCap->halTsfAddSupport ? HAL_OK : HAL_ENOTSUPP;
888 return (ahp->ah_miscMode & AR_MISC_MODE_TX_ADD_TSF) ?
892 case HAL_CAP_TPC_ACK:
893 *result = MS(ahp->ah_macTPC, AR_TPC_ACK);
895 case HAL_CAP_TPC_CTS:
896 *result = MS(ahp->ah_macTPC, AR_TPC_CTS);
898 case HAL_CAP_INTMIT: /* interference mitigation */
899 switch (capability) {
900 case HAL_CAP_INTMIT_PRESENT: /* hardware capability */
902 case HAL_CAP_INTMIT_ENABLE:
903 return (ahp->ah_procPhyErr & HAL_ANI_ENA) ?
905 case HAL_CAP_INTMIT_NOISE_IMMUNITY_LEVEL:
906 case HAL_CAP_INTMIT_OFDM_WEAK_SIGNAL_LEVEL:
907 case HAL_CAP_INTMIT_CCK_WEAK_SIGNAL_THR:
908 case HAL_CAP_INTMIT_FIRSTEP_LEVEL:
909 case HAL_CAP_INTMIT_SPUR_IMMUNITY_LEVEL:
910 ani = ar5212AniGetCurrentState(ah);
913 switch (capability) {
914 case 2: *result = ani->noiseImmunityLevel; break;
915 case 3: *result = !ani->ofdmWeakSigDetectOff; break;
916 case 4: *result = ani->cckWeakSigThreshold; break;
917 case 5: *result = ani->firstepLevel; break;
918 case 6: *result = ani->spurImmunityLevel; break;
924 return ath_hal_getcapability(ah, type, capability, result);
930 ar5212SetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
931 uint32_t capability, uint32_t setting, HAL_STATUS *status)
933 #define N(a) (sizeof(a)/sizeof(a[0]))
934 struct ath_hal_5212 *ahp = AH5212(ah);
935 const HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps;
939 case HAL_CAP_TKIP_MIC: /* handle TKIP MIC in hardware */
941 ahp->ah_staId1Defaults |= AR_STA_ID1_CRPT_MIC_ENABLE;
943 ahp->ah_staId1Defaults &= ~AR_STA_ID1_CRPT_MIC_ENABLE;
945 case HAL_CAP_TKIP_SPLIT: /* hardware TKIP uses split keys */
946 if (!pCap->halTkipMicTxRxKeySupport)
948 /* NB: true =>'s use split key cache layout */
950 ahp->ah_miscMode &= ~AR_MISC_MODE_MIC_NEW_LOC_ENABLE;
952 ahp->ah_miscMode |= AR_MISC_MODE_MIC_NEW_LOC_ENABLE;
953 /* NB: write here so keys can be setup w/o a reset */
954 OS_REG_WRITE(ah, AR_MISC_MODE, OS_REG_READ(ah, AR_MISC_MODE) | ahp->ah_miscMode);
956 case HAL_CAP_DIVERSITY:
957 switch (capability) {
960 case 1: /* setting */
961 if (ahp->ah_phyPowerOn) {
962 if (capability == HAL_CAP_STRONG_DIV) {
963 v = OS_REG_READ(ah, AR_PHY_CCK_DETECT);
965 v |= AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV;
967 v &= ~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV;
968 OS_REG_WRITE(ah, AR_PHY_CCK_DETECT, v);
971 ahp->ah_diversity = (setting != 0);
974 case HAL_CAP_STRONG_DIV:
975 if (! ahp->ah_phyPowerOn)
977 v = OS_REG_READ(ah, AR_PHY_RESTART);
978 v &= ~AR_PHY_RESTART_DIV_GC;
979 v |= SM(setting, AR_PHY_RESTART_DIV_GC);
980 OS_REG_WRITE(ah, AR_PHY_RESTART, v);
985 case HAL_CAP_DIAG: /* hardware diagnostic support */
987 * NB: could split this up into virtual capabilities,
988 * (e.g. 1 => ACK, 2 => CTS, etc.) but it hardly
989 * seems worth the additional complexity.
991 AH_PRIVATE(ah)->ah_diagreg = setting;
992 OS_REG_WRITE(ah, AR_DIAG_SW, AH_PRIVATE(ah)->ah_diagreg);
995 ahp->ah_tpcEnabled = (setting != 0);
997 case HAL_CAP_MCAST_KEYSRCH: /* multicast frame keycache search */
999 ahp->ah_staId1Defaults |= AR_STA_ID1_MCAST_KSRCH;
1001 ahp->ah_staId1Defaults &= ~AR_STA_ID1_MCAST_KSRCH;
1003 case HAL_CAP_TPC_ACK:
1004 case HAL_CAP_TPC_CTS:
1005 setting += ahp->ah_txPowerIndexOffset;
1008 if (type == HAL_CAP_TPC_ACK) {
1009 ahp->ah_macTPC &= AR_TPC_ACK;
1010 ahp->ah_macTPC |= MS(setting, AR_TPC_ACK);
1012 ahp->ah_macTPC &= AR_TPC_CTS;
1013 ahp->ah_macTPC |= MS(setting, AR_TPC_CTS);
1015 OS_REG_WRITE(ah, AR_TPC, ahp->ah_macTPC);
1017 case HAL_CAP_INTMIT: { /* interference mitigation */
1018 /* This maps the public ANI commands to the internal ANI commands */
1019 /* Private: HAL_ANI_CMD; Public: HAL_CAP_INTMIT_CMD */
1020 static const HAL_ANI_CMD cmds[] = {
1023 HAL_ANI_NOISE_IMMUNITY_LEVEL,
1024 HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION,
1025 HAL_ANI_CCK_WEAK_SIGNAL_THR,
1026 HAL_ANI_FIRSTEP_LEVEL,
1027 HAL_ANI_SPUR_IMMUNITY_LEVEL,
1029 return capability < N(cmds) ?
1030 AH5212(ah)->ah_aniControl(ah, cmds[capability], setting) :
1033 case HAL_CAP_TSF_ADJUST: /* hardware has beacon tsf adjust */
1034 if (pCap->halTsfAddSupport) {
1036 ahp->ah_miscMode |= AR_MISC_MODE_TX_ADD_TSF;
1038 ahp->ah_miscMode &= ~AR_MISC_MODE_TX_ADD_TSF;
1043 return ath_hal_setcapability(ah, type, capability,
1050 ar5212GetDiagState(struct ath_hal *ah, int request,
1051 const void *args, uint32_t argsize,
1052 void **result, uint32_t *resultsize)
1054 struct ath_hal_5212 *ahp = AH5212(ah);
1057 if (ath_hal_getdiagstate(ah, request, args, argsize, result, resultsize))
1060 case HAL_DIAG_EEPROM:
1061 case HAL_DIAG_EEPROM_EXP_11A:
1062 case HAL_DIAG_EEPROM_EXP_11B:
1063 case HAL_DIAG_EEPROM_EXP_11G:
1064 case HAL_DIAG_RFGAIN:
1065 return ath_hal_eepromDiag(ah, request,
1066 args, argsize, result, resultsize);
1067 case HAL_DIAG_RFGAIN_CURSTEP:
1068 *result = __DECONST(void *, ahp->ah_gainValues.currStep);
1069 *resultsize = (*result == AH_NULL) ?
1070 0 : sizeof(GAIN_OPTIMIZATION_STEP);
1072 case HAL_DIAG_PCDAC:
1073 *result = ahp->ah_pcdacTable;
1074 *resultsize = ahp->ah_pcdacTableSize;
1076 case HAL_DIAG_TXRATES:
1077 *result = &ahp->ah_ratesArray[0];
1078 *resultsize = sizeof(ahp->ah_ratesArray);
1080 case HAL_DIAG_ANI_CURRENT:
1081 *result = ar5212AniGetCurrentState(ah);
1082 *resultsize = (*result == AH_NULL) ?
1083 0 : sizeof(struct ar5212AniState);
1085 case HAL_DIAG_ANI_STATS:
1086 *result = ar5212AniGetCurrentStats(ah);
1087 *resultsize = (*result == AH_NULL) ?
1088 0 : sizeof(struct ar5212Stats);
1090 case HAL_DIAG_ANI_CMD:
1091 if (argsize != 2*sizeof(uint32_t))
1093 AH5212(ah)->ah_aniControl(ah, ((const uint32_t *)args)[0],
1094 ((const uint32_t *)args)[1]);
1096 case HAL_DIAG_ANI_PARAMS:
1098 * NB: We assume struct ar5212AniParams is identical
1099 * to HAL_ANI_PARAMS; if they diverge then we'll need
1102 if (argsize == 0 && args == AH_NULL) {
1103 struct ar5212AniState *aniState =
1104 ar5212AniGetCurrentState(ah);
1105 if (aniState == AH_NULL)
1107 *result = __DECONST(void *, aniState->params);
1108 *resultsize = sizeof(struct ar5212AniParams);
1111 if (argsize != sizeof(struct ar5212AniParams))
1113 return ar5212AniSetParams(ah, args, args);
1116 case HAL_DIAG_CHANSURVEY:
1117 *result = &ahp->ah_chansurvey;
1118 *resultsize = sizeof(HAL_CHANNEL_SURVEY);
1125 * Check whether there's an in-progress NF completion.
1127 * Returns AH_TRUE if there's a in-progress NF calibration, AH_FALSE
1131 ar5212IsNFCalInProgress(struct ath_hal *ah)
1133 if (OS_REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF)
1139 * Wait for an in-progress NF calibration to complete.
1141 * The completion function waits "i" times 10uS.
1142 * It returns AH_TRUE if the NF calibration completed (or was never
1143 * in progress); AH_FALSE if it was still in progress after "i" checks.
1146 ar5212WaitNFCalComplete(struct ath_hal *ah, int i)
1150 i = 1; /* it should run at least once */
1151 for (j = 0; j < i; j++) {
1152 if (! ar5212IsNFCalInProgress(ah))
1160 ar5212EnableDfs(struct ath_hal *ah, HAL_PHYERR_PARAM *pe)
1163 val = OS_REG_READ(ah, AR_PHY_RADAR_0);
1165 if (pe->pe_firpwr != HAL_PHYERR_PARAM_NOVAL) {
1166 val &= ~AR_PHY_RADAR_0_FIRPWR;
1167 val |= SM(pe->pe_firpwr, AR_PHY_RADAR_0_FIRPWR);
1169 if (pe->pe_rrssi != HAL_PHYERR_PARAM_NOVAL) {
1170 val &= ~AR_PHY_RADAR_0_RRSSI;
1171 val |= SM(pe->pe_rrssi, AR_PHY_RADAR_0_RRSSI);
1173 if (pe->pe_height != HAL_PHYERR_PARAM_NOVAL) {
1174 val &= ~AR_PHY_RADAR_0_HEIGHT;
1175 val |= SM(pe->pe_height, AR_PHY_RADAR_0_HEIGHT);
1177 if (pe->pe_prssi != HAL_PHYERR_PARAM_NOVAL) {
1178 val &= ~AR_PHY_RADAR_0_PRSSI;
1179 val |= SM(pe->pe_prssi, AR_PHY_RADAR_0_PRSSI);
1181 if (pe->pe_inband != HAL_PHYERR_PARAM_NOVAL) {
1182 val &= ~AR_PHY_RADAR_0_INBAND;
1183 val |= SM(pe->pe_inband, AR_PHY_RADAR_0_INBAND);
1186 val |= AR_PHY_RADAR_0_ENA;
1188 val &= ~ AR_PHY_RADAR_0_ENA;
1192 if (pe->pe_blockradar == 1)
1193 OS_REG_SET_BIT(ah, AR_PHY_RADAR_2,
1194 AR_PHY_RADAR_2_BLOCKOFDMWEAK);
1196 OS_REG_CLR_BIT(ah, AR_PHY_RADAR_2,
1197 AR_PHY_RADAR_2_BLOCKOFDMWEAK);
1199 if (pe->pe_en_relstep_check == 1)
1200 OS_REG_SET_BIT(ah, AR_PHY_RADAR_2,
1201 AR_PHY_RADAR_2_ENRELSTEPCHK);
1203 OS_REG_CLR_BIT(ah, AR_PHY_RADAR_2,
1204 AR_PHY_RADAR_2_ENRELSTEPCHK);
1206 if (pe->pe_usefir128 == 1)
1207 OS_REG_SET_BIT(ah, AR_PHY_RADAR_2,
1208 AR_PHY_RADAR_2_USEFIR128);
1210 OS_REG_CLR_BIT(ah, AR_PHY_RADAR_2,
1211 AR_PHY_RADAR_2_USEFIR128);
1213 if (pe->pe_enmaxrssi == 1)
1214 OS_REG_SET_BIT(ah, AR_PHY_RADAR_2,
1215 AR_PHY_RADAR_2_ENMAXRSSI);
1217 OS_REG_CLR_BIT(ah, AR_PHY_RADAR_2,
1218 AR_PHY_RADAR_2_ENMAXRSSI);
1220 if (pe->pe_enrelpwr == 1)
1221 OS_REG_SET_BIT(ah, AR_PHY_RADAR_2,
1222 AR_PHY_RADAR_2_ENRELPWRCHK);
1224 OS_REG_CLR_BIT(ah, AR_PHY_RADAR_2,
1225 AR_PHY_RADAR_2_ENRELPWRCHK);
1227 if (pe->pe_relpwr != HAL_PHYERR_PARAM_NOVAL)
1228 OS_REG_RMW_FIELD(ah, AR_PHY_RADAR_2,
1229 AR_PHY_RADAR_2_RELPWR, pe->pe_relpwr);
1231 if (pe->pe_relstep != HAL_PHYERR_PARAM_NOVAL)
1232 OS_REG_RMW_FIELD(ah, AR_PHY_RADAR_2,
1233 AR_PHY_RADAR_2_RELSTEP, pe->pe_relstep);
1235 if (pe->pe_maxlen != HAL_PHYERR_PARAM_NOVAL)
1236 OS_REG_RMW_FIELD(ah, AR_PHY_RADAR_2,
1237 AR_PHY_RADAR_2_MAXLEN, pe->pe_maxlen);
1240 OS_REG_WRITE(ah, AR_PHY_RADAR_0, val);
1244 * Parameters for the AR5212 PHY.
1246 #define AR5212_DFS_FIRPWR -35
1247 #define AR5212_DFS_RRSSI 20
1248 #define AR5212_DFS_HEIGHT 14
1249 #define AR5212_DFS_PRSSI 6
1250 #define AR5212_DFS_INBAND 4
1253 * Default parameters for the AR5413 PHY.
1255 #define AR5413_DFS_FIRPWR -34
1256 #define AR5413_DFS_RRSSI 20
1257 #define AR5413_DFS_HEIGHT 10
1258 #define AR5413_DFS_PRSSI 15
1259 #define AR5413_DFS_INBAND 6
1260 #define AR5413_DFS_RELPWR 8
1261 #define AR5413_DFS_RELSTEP 31
1262 #define AR5413_DFS_MAXLEN 255
1265 ar5212GetDfsDefaultThresh(struct ath_hal *ah, HAL_PHYERR_PARAM *pe)
1269 pe->pe_firpwr = AR5413_DFS_FIRPWR;
1270 pe->pe_rrssi = AR5413_DFS_RRSSI;
1271 pe->pe_height = AR5413_DFS_HEIGHT;
1272 pe->pe_prssi = AR5413_DFS_PRSSI;
1273 pe->pe_inband = AR5413_DFS_INBAND;
1274 pe->pe_relpwr = AR5413_DFS_RELPWR;
1275 pe->pe_relstep = AR5413_DFS_RELSTEP;
1276 pe->pe_maxlen = AR5413_DFS_MAXLEN;
1277 pe->pe_usefir128 = 0;
1278 pe->pe_blockradar = 1;
1279 pe->pe_enmaxrssi = 1;
1280 pe->pe_enrelpwr = 1;
1281 pe->pe_en_relstep_check = 0;
1283 pe->pe_firpwr = AR5212_DFS_FIRPWR;
1284 pe->pe_rrssi = AR5212_DFS_RRSSI;
1285 pe->pe_height = AR5212_DFS_HEIGHT;
1286 pe->pe_prssi = AR5212_DFS_PRSSI;
1287 pe->pe_inband = AR5212_DFS_INBAND;
1291 pe->pe_usefir128 = 0;
1292 pe->pe_blockradar = 0;
1293 pe->pe_enmaxrssi = 0;
1294 pe->pe_enrelpwr = 0;
1295 pe->pe_en_relstep_check = 0;
1302 ar5212GetDfsThresh(struct ath_hal *ah, HAL_PHYERR_PARAM *pe)
1306 val = OS_REG_READ(ah, AR_PHY_RADAR_0);
1308 temp = MS(val,AR_PHY_RADAR_0_FIRPWR);
1310 pe->pe_firpwr = temp;
1311 pe->pe_rrssi = MS(val, AR_PHY_RADAR_0_RRSSI);
1312 pe->pe_height = MS(val, AR_PHY_RADAR_0_HEIGHT);
1313 pe->pe_prssi = MS(val, AR_PHY_RADAR_0_PRSSI);
1314 pe->pe_inband = MS(val, AR_PHY_RADAR_0_INBAND);
1315 pe->pe_enabled = !! (val & AR_PHY_RADAR_0_ENA);
1320 pe->pe_usefir128 = 0;
1321 pe->pe_blockradar = 0;
1322 pe->pe_enmaxrssi = 0;
1323 pe->pe_enrelpwr = 0;
1324 pe->pe_en_relstep_check = 0;
1325 pe->pe_extchannel = AH_FALSE;
1328 val = OS_REG_READ(ah, AR_PHY_RADAR_2);
1329 pe->pe_relpwr = !! MS(val, AR_PHY_RADAR_2_RELPWR);
1330 pe->pe_relstep = !! MS(val, AR_PHY_RADAR_2_RELSTEP);
1331 pe->pe_maxlen = !! MS(val, AR_PHY_RADAR_2_MAXLEN);
1333 pe->pe_usefir128 = !! (val & AR_PHY_RADAR_2_USEFIR128);
1334 pe->pe_blockradar = !! (val & AR_PHY_RADAR_2_BLOCKOFDMWEAK);
1335 pe->pe_enmaxrssi = !! (val & AR_PHY_RADAR_2_ENMAXRSSI);
1336 pe->pe_enrelpwr = !! (val & AR_PHY_RADAR_2_ENRELPWRCHK);
1337 pe->pe_en_relstep_check =
1338 !! (val & AR_PHY_RADAR_2_ENRELSTEPCHK);
1343 * Process the radar phy error and extract the pulse duration.
1346 ar5212ProcessRadarEvent(struct ath_hal *ah, struct ath_rx_status *rxs,
1347 uint64_t fulltsf, const char *buf, HAL_DFS_EVENT *event)
1352 /* Check whether the given phy error is a radar event */
1353 if ((rxs->rs_phyerr != HAL_PHYERR_RADAR) &&
1354 (rxs->rs_phyerr != HAL_PHYERR_FALSE_RADAR_EXT))
1358 * The first byte is the pulse width - if there's
1359 * no data, simply set the duration to 0
1361 if (rxs->rs_datalen >= 1)
1362 /* The pulse width is byte 0 of the data */
1363 dur = ((uint8_t) buf[0]) & 0xff;
1367 /* Pulse RSSI is the normal reported RSSI */
1368 rssi = (uint8_t) rxs->rs_rssi;
1370 /* 0 duration/rssi is not a valid radar event */
1371 if (dur == 0 && rssi == 0)
1374 HALDEBUG(ah, HAL_DEBUG_DFS, "%s: rssi=%d, dur=%d\n",
1375 __func__, rssi, dur);
1377 /* Record the event */
1378 event->re_full_ts = fulltsf;
1379 event->re_ts = rxs->rs_tstamp;
1380 event->re_rssi = rssi;
1381 event->re_dur = dur;
1382 event->re_flags = HAL_DFS_EVENT_PRICH;
1388 * Return whether 5GHz fast-clock (44MHz) is enabled.
1389 * It's always disabled for AR5212 series NICs.
1392 ar5212IsFastClockEnabled(struct ath_hal *ah)
1398 * Return what percentage of the extension channel is busy.
1399 * This is always disabled for AR5212 series NICs.
1402 ar5212Get11nExtBusy(struct ath_hal *ah)
1408 * Channel survey support.
1411 ar5212GetMibCycleCounts(struct ath_hal *ah, HAL_SURVEY_SAMPLE *hsample)
1413 struct ath_hal_5212 *ahp = AH5212(ah);
1414 u_int32_t good = AH_TRUE;
1416 /* XXX freeze/unfreeze mib counters */
1417 uint32_t rc = OS_REG_READ(ah, AR_RCCNT);
1418 uint32_t rf = OS_REG_READ(ah, AR_RFCNT);
1419 uint32_t tf = OS_REG_READ(ah, AR_TFCNT);
1420 uint32_t cc = OS_REG_READ(ah, AR_CCCNT); /* read cycles last */
1422 if (ahp->ah_cycleCount == 0 || ahp->ah_cycleCount > cc) {
1424 * Cycle counter wrap (or initial call); it's not possible
1425 * to accurately calculate a value because the registers
1426 * right shift rather than wrap--so punt and return 0.
1428 HALDEBUG(ah, HAL_DEBUG_ANY,
1429 "%s: cycle counter wrap. ExtBusy = 0\n", __func__);
1432 hsample->cycle_count = cc - ahp->ah_cycleCount;
1433 hsample->chan_busy = rc - ahp->ah_ctlBusy;
1434 hsample->ext_chan_busy = 0;
1435 hsample->rx_busy = rf - ahp->ah_rxBusy;
1436 hsample->tx_busy = tf - ahp->ah_txBusy;
1440 * Keep a copy of the MIB results so the next sample has something
1443 ahp->ah_cycleCount = cc;
1444 ahp->ah_rxBusy = rf;
1445 ahp->ah_ctlBusy = rc;
1446 ahp->ah_txBusy = tf;
1452 ar5212SetChainMasks(struct ath_hal *ah, uint32_t tx_chainmask,
1453 uint32_t rx_chainmask)