2 * SPDX-License-Identifier: ISC
4 * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
5 * Copyright (c) 2002-2008 Atheros Communications, Inc.
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
24 #include "ah_internal.h"
26 #include "ah_desc.h" /* NB: for HAL_PHYERR* */
28 #include "ar5416/ar5416.h"
29 #include "ar5416/ar5416reg.h"
30 #include "ar5416/ar5416phy.h"
32 #include "ah_eeprom_v14.h" /* for owl_get_ntxchains() */
35 * Return the wireless modes (a,b,g,n,t) supported by hardware.
37 * This value is what is actually supported by the hardware
38 * and is unaffected by regulatory/country code settings.
42 ar5416GetWirelessModes(struct ath_hal *ah)
45 struct ath_hal_private *ahpriv = AH_PRIVATE(ah);
46 HAL_CAPABILITIES *pCap = &ahpriv->ah_caps;
48 mode = ar5212GetWirelessModes(ah);
50 /* Only enable HT modes if the NIC supports HT */
51 if (pCap->halHTSupport == AH_TRUE && (mode & HAL_MODE_11A))
52 mode |= HAL_MODE_11NA_HT20
53 | HAL_MODE_11NA_HT40PLUS
54 | HAL_MODE_11NA_HT40MINUS
56 if (pCap->halHTSupport == AH_TRUE && (mode & HAL_MODE_11G))
57 mode |= HAL_MODE_11NG_HT20
58 | HAL_MODE_11NG_HT40PLUS
59 | HAL_MODE_11NG_HT40MINUS
65 * Change the LED blinking pattern to correspond to the connectivity
68 ar5416SetLedState(struct ath_hal *ah, HAL_LED_STATE state)
70 static const uint32_t ledbits[8] = {
71 AR_MAC_LED_ASSOC_NONE, /* HAL_LED_INIT */
72 AR_MAC_LED_ASSOC_PEND, /* HAL_LED_SCAN */
73 AR_MAC_LED_ASSOC_PEND, /* HAL_LED_AUTH */
74 AR_MAC_LED_ASSOC_ACTIVE, /* HAL_LED_ASSOC*/
75 AR_MAC_LED_ASSOC_ACTIVE, /* HAL_LED_RUN */
76 AR_MAC_LED_ASSOC_NONE,
77 AR_MAC_LED_ASSOC_NONE,
78 AR_MAC_LED_ASSOC_NONE,
85 * Set the blink operating mode.
87 OS_REG_RMW_FIELD(ah, AR_MAC_LED,
88 AR_MAC_LED_ASSOC, ledbits[state & 0x7]);
90 /* XXX Blink slow mode? */
91 /* XXX Blink threshold? */
92 /* XXX Blink sleep hystersis? */
95 * Set the LED blink configuration to be proportional
96 * to the current TX and RX filter bytes. (Ie, RX'ed
97 * frames that don't match the filter are ignored.)
98 * This means that higher TX/RX throughput will result
99 * in the blink rate increasing.
101 OS_REG_RMW_FIELD(ah, AR_MAC_LED, AR_MAC_LED_MODE,
102 AR_MAC_LED_MODE_PROP);
106 * Get the current hardware tsf for stamlme
109 ar5416GetTsf64(struct ath_hal *ah)
111 uint32_t low1, low2, u32;
113 /* sync multi-word read */
114 low1 = OS_REG_READ(ah, AR_TSF_L32);
115 u32 = OS_REG_READ(ah, AR_TSF_U32);
116 low2 = OS_REG_READ(ah, AR_TSF_L32);
117 if (low2 < low1) { /* roll over */
119 * If we are not preempted this will work. If we are
120 * then we re-reading AR_TSF_U32 does no good as the
121 * low bits will be meaningless. Likewise reading
122 * L32, U32, U32, then comparing the last two reads
123 * to check for rollover doesn't help if preempted--so
124 * we take this approach as it costs one less PCI read
125 * which can be noticeable when doing things like
126 * timestamping packets in monitor mode.
130 return (((uint64_t) u32) << 32) | ((uint64_t) low2);
136 * The full TSF is only updated once the upper 32 bits have
137 * been written. Writing only the lower 32 bits of the TSF
138 * will not actually correctly update the TSF.
140 * The #if 0'ed code is to check whether the previous TSF
141 * reset or write has completed before writing to the
142 * TSF. Strictly speaking, it should be also checked before
143 * reading the TSF as the write/reset may not have completed.
146 ar5416SetTsf64(struct ath_hal *ah, uint64_t tsf64)
148 /* XXX check if this is correct! */
153 for (i = 0; i < 10; i++) {
154 v = OS_REG_READ(ah, AR_SLP32_MODE);
155 if ((v & AR_SLP32_TSF_WRITE_STATUS) == 0)
160 ath_hal_printf(ah, "%s: couldn't slew things right!\n", __func__);
163 OS_REG_WRITE(ah, AR_TSF_L32, tsf64 & 0xffffffff);
164 OS_REG_WRITE(ah, AR_TSF_U32, (tsf64 >> 32) & 0xffffffff);
168 * Reset the current hardware tsf for stamlme.
171 ar5416ResetTsf(struct ath_hal *ah)
176 for (i = 0; i < 10; i++) {
177 v = OS_REG_READ(ah, AR_SLP32_MODE);
178 if ((v & AR_SLP32_TSF_WRITE_STATUS) == 0)
182 OS_REG_WRITE(ah, AR_RESET_TSF, AR_RESET_TSF_ONCE);
186 ar5416GetCurRssi(struct ath_hal *ah)
189 return (OS_REG_READ(ah, AR_PHY_CURRENT_RSSI) & 0xff);
190 return (OS_REG_READ(ah, AR9130_PHY_CURRENT_RSSI) & 0xff);
194 ar5416SetAntennaSwitch(struct ath_hal *ah, HAL_ANT_SETTING settings)
199 /* Setup decompression for given key index */
201 ar5416SetDecompMask(struct ath_hal *ah, uint16_t keyidx, int en)
206 /* Setup coverage class */
208 ar5416SetCoverageClass(struct ath_hal *ah, uint8_t coverageclass, int now)
211 ar5212SetCoverageClass(ah, coverageclass, now);
215 * Return the busy for rx_frame, rx_clear, and tx_frame
218 ar5416GetMibCycleCounts(struct ath_hal *ah, HAL_SURVEY_SAMPLE *hsample)
220 struct ath_hal_5416 *ahp = AH5416(ah);
221 u_int32_t good = AH_TRUE;
223 /* XXX freeze/unfreeze mib counters */
224 uint32_t rc = OS_REG_READ(ah, AR_RCCNT);
225 uint32_t ec = OS_REG_READ(ah, AR_EXTRCCNT);
226 uint32_t rf = OS_REG_READ(ah, AR_RFCNT);
227 uint32_t tf = OS_REG_READ(ah, AR_TFCNT);
228 uint32_t cc = OS_REG_READ(ah, AR_CCCNT); /* read cycles last */
230 if (ahp->ah_cycleCount == 0 || ahp->ah_cycleCount > cc) {
232 * Cycle counter wrap (or initial call); it's not possible
233 * to accurately calculate a value because the registers
234 * right shift rather than wrap--so punt and return 0.
236 HALDEBUG(ah, HAL_DEBUG_ANY,
237 "%s: cycle counter wrap. ExtBusy = 0\n", __func__);
240 hsample->cycle_count = cc - ahp->ah_cycleCount;
241 hsample->chan_busy = rc - ahp->ah_ctlBusy;
242 hsample->ext_chan_busy = ec - ahp->ah_extBusy;
243 hsample->rx_busy = rf - ahp->ah_rxBusy;
244 hsample->tx_busy = tf - ahp->ah_txBusy;
248 * Keep a copy of the MIB results so the next sample has something
251 ahp->ah_cycleCount = cc;
253 ahp->ah_ctlBusy = rc;
255 ahp->ah_extBusy = ec;
261 * Setup the TX/RX chainmasks - this needs to be done before a call
262 * to the reset method as it doesn't update the hardware.
265 ar5416SetChainMasks(struct ath_hal *ah, uint32_t tx_chainmask,
266 uint32_t rx_chainmask)
268 HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps;
270 AH5416(ah)->ah_tx_chainmask = tx_chainmask & pCap->halTxChainMask;
271 AH5416(ah)->ah_rx_chainmask = rx_chainmask & pCap->halRxChainMask;
275 * Return approximation of extension channel busy over an time interval
276 * 0% (clear) -> 100% (busy)
278 * XXX TODO: update this to correctly sample all the counters,
279 * rather than a subset of it.
282 ar5416Get11nExtBusy(struct ath_hal *ah)
284 struct ath_hal_5416 *ahp = AH5416(ah);
285 uint32_t busy; /* percentage */
286 uint32_t cycleCount, ctlBusy, extBusy;
288 ctlBusy = OS_REG_READ(ah, AR_RCCNT);
289 extBusy = OS_REG_READ(ah, AR_EXTRCCNT);
290 cycleCount = OS_REG_READ(ah, AR_CCCNT);
292 if (ahp->ah_cycleCount == 0 || ahp->ah_cycleCount > cycleCount) {
294 * Cycle counter wrap (or initial call); it's not possible
295 * to accurately calculate a value because the registers
296 * right shift rather than wrap--so punt and return 0.
299 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: cycle counter wrap. ExtBusy = 0\n",
303 uint32_t cycleDelta = cycleCount - ahp->ah_cycleCount;
304 uint32_t ctlBusyDelta = ctlBusy - ahp->ah_ctlBusy;
305 uint32_t extBusyDelta = extBusy - ahp->ah_extBusy;
306 uint32_t ctlClearDelta = 0;
308 /* Compute control channel rxclear.
309 * The cycle delta may be less than the control channel delta.
310 * This could be solved by freezing the timers (or an atomic read,
311 * if one was available). Checking for the condition should be
314 if (cycleDelta > ctlBusyDelta) {
315 ctlClearDelta = cycleDelta - ctlBusyDelta;
318 /* Compute ratio of extension channel busy to control channel clear
319 * as an approximation to extension channel cleanliness.
321 * According to the hardware folks, ext rxclear is undefined
322 * if the ctrl rxclear is de-asserted (i.e. busy)
325 busy = (extBusyDelta * 100) / ctlClearDelta;
333 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: cycleDelta 0x%x, ctlBusyDelta 0x%x, "
334 "extBusyDelta 0x%x, ctlClearDelta 0x%x, "
336 __func__, cycleDelta, ctlBusyDelta, extBusyDelta, ctlClearDelta, busy);
340 ahp->ah_cycleCount = cycleCount;
341 ahp->ah_ctlBusy = ctlBusy;
342 ahp->ah_extBusy = extBusy;
348 * Configure 20/40 operation
350 * 20/40 = joint rx clear (control and extension)
351 * 20 = rx clear (control)
353 * - NOTE: must stop MAC (tx) and requeue 40 MHz packets as 20 MHz when changing
354 * from 20/40 => 20 only
357 ar5416Set11nMac2040(struct ath_hal *ah, HAL_HT_MACMODE mode)
361 /* Configure MAC for 20/40 operation */
362 if (mode == HAL_HT_MACMODE_2040) {
363 macmode = AR_2040_JOINED_RX_CLEAR;
367 OS_REG_WRITE(ah, AR_2040_MODE, macmode);
371 * Get Rx clear (control/extension channel)
373 * Returns active low (busy) for ctrl/ext channel
377 ar5416Get11nRxClear(struct ath_hal *ah)
379 HAL_HT_RXCLEAR rxclear = 0;
382 val = OS_REG_READ(ah, AR_DIAG_SW);
384 /* control channel */
385 if (val & AR_DIAG_RXCLEAR_CTL_LOW) {
386 rxclear |= HAL_RX_CLEAR_CTL_LOW;
388 /* extension channel */
389 if (val & AR_DIAG_RXCLEAR_EXT_LOW) {
390 rxclear |= HAL_RX_CLEAR_EXT_LOW;
396 * Set Rx clear (control/extension channel)
398 * Useful for forcing the channel to appear busy for
399 * debugging/diagnostics
403 ar5416Set11nRxClear(struct ath_hal *ah, HAL_HT_RXCLEAR rxclear)
405 /* control channel */
406 if (rxclear & HAL_RX_CLEAR_CTL_LOW) {
407 OS_REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RXCLEAR_CTL_LOW);
409 OS_REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_RXCLEAR_CTL_LOW);
411 /* extension channel */
412 if (rxclear & HAL_RX_CLEAR_EXT_LOW) {
413 OS_REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RXCLEAR_EXT_LOW);
415 OS_REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_RXCLEAR_EXT_LOW);
419 /* XXX shouldn't be here! */
420 #define TU_TO_USEC(_tu) ((_tu) << 10)
423 ar5416SetQuiet(struct ath_hal *ah, uint32_t period, uint32_t duration,
424 uint32_t nextStart, HAL_QUIET_FLAG flag)
426 uint32_t period_us = TU_TO_USEC(period); /* convert to us unit */
427 uint32_t nextStart_us = TU_TO_USEC(nextStart); /* convert to us unit */
428 if (flag & HAL_QUIET_ENABLE) {
429 if ((!nextStart) || (flag & HAL_QUIET_ADD_CURRENT_TSF)) {
430 /* Add the nextStart offset to the current TSF */
431 nextStart_us += OS_REG_READ(ah, AR_TSF_L32);
433 if (flag & HAL_QUIET_ADD_SWBA_RESP_TIME) {
434 nextStart_us += ah->ah_config.ah_sw_beacon_response_time;
436 OS_REG_RMW_FIELD(ah, AR_QUIET1, AR_QUIET1_QUIET_ACK_CTS_ENABLE, 1);
437 OS_REG_WRITE(ah, AR_QUIET2, SM(duration, AR_QUIET2_QUIET_DUR));
438 OS_REG_WRITE(ah, AR_QUIET_PERIOD, period_us);
439 OS_REG_WRITE(ah, AR_NEXT_QUIET, nextStart_us);
440 OS_REG_SET_BIT(ah, AR_TIMER_MODE, AR_TIMER_MODE_QUIET);
442 OS_REG_CLR_BIT(ah, AR_TIMER_MODE, AR_TIMER_MODE_QUIET);
449 ar5416GetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
450 uint32_t capability, uint32_t *result)
453 case HAL_CAP_BB_HANG:
454 switch (capability) {
455 case HAL_BB_HANG_RIFS:
456 return (AR_SREV_HOWL(ah) || AR_SREV_SOWL(ah)) ? HAL_OK : HAL_ENOTSUPP;
457 case HAL_BB_HANG_DFS:
458 return (AR_SREV_HOWL(ah) || AR_SREV_SOWL(ah)) ? HAL_OK : HAL_ENOTSUPP;
459 case HAL_BB_HANG_RX_CLEAR:
460 return AR_SREV_MERLIN(ah) ? HAL_OK : HAL_ENOTSUPP;
463 case HAL_CAP_MAC_HANG:
464 return ((ah->ah_macVersion == AR_XSREV_VERSION_OWL_PCI) ||
465 (ah->ah_macVersion == AR_XSREV_VERSION_OWL_PCIE) ||
466 AR_SREV_HOWL(ah) || AR_SREV_SOWL(ah)) ?
467 HAL_OK : HAL_ENOTSUPP;
468 case HAL_CAP_DIVERSITY: /* disable classic fast diversity */
470 case HAL_CAP_ENFORCE_TXOP:
474 return (HAL_ENOTSUPP);
476 !! (AH5212(ah)->ah_miscMode & AR_PCU_TXOP_TBTT_LIMIT_ENA);
481 return ar5212GetCapability(ah, type, capability, result);
485 ar5416SetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
486 u_int32_t capability, u_int32_t setting, HAL_STATUS *status)
488 HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps;
491 case HAL_CAP_RX_CHAINMASK:
492 setting &= ath_hal_eepromGet(ah, AR_EEP_RXMASK, NULL);
493 pCap->halRxChainMask = setting;
494 if (owl_get_ntxchains(setting) > 2)
495 pCap->halRxStreams = 2;
497 pCap->halRxStreams = 1;
499 case HAL_CAP_TX_CHAINMASK:
500 setting &= ath_hal_eepromGet(ah, AR_EEP_TXMASK, NULL);
501 pCap->halTxChainMask = setting;
502 if (owl_get_ntxchains(setting) > 2)
503 pCap->halTxStreams = 2;
505 pCap->halTxStreams = 1;
507 case HAL_CAP_ENFORCE_TXOP:
511 AH5212(ah)->ah_miscMode
512 |= AR_PCU_TXOP_TBTT_LIMIT_ENA;
513 OS_REG_SET_BIT(ah, AR_MISC_MODE,
514 AR_PCU_TXOP_TBTT_LIMIT_ENA);
516 AH5212(ah)->ah_miscMode
517 &= ~AR_PCU_TXOP_TBTT_LIMIT_ENA;
518 OS_REG_CLR_BIT(ah, AR_MISC_MODE,
519 AR_PCU_TXOP_TBTT_LIMIT_ENA);
525 return ar5212SetCapability(ah, type, capability, setting, status);
528 static int ar5416DetectMacHang(struct ath_hal *ah);
529 static int ar5416DetectBBHang(struct ath_hal *ah);
532 ar5416GetDiagState(struct ath_hal *ah, int request,
533 const void *args, uint32_t argsize,
534 void **result, uint32_t *resultsize)
536 struct ath_hal_5416 *ahp = AH5416(ah);
539 if (ath_hal_getdiagstate(ah, request, args, argsize, result, resultsize))
542 case HAL_DIAG_EEPROM:
543 return ath_hal_eepromDiag(ah, request,
544 args, argsize, result, resultsize);
545 case HAL_DIAG_CHECK_HANGS:
546 if (argsize != sizeof(int))
548 hangs = *(const int *) args;
550 if (hangs & HAL_BB_HANGS)
551 ahp->ah_hangs |= ar5416DetectBBHang(ah);
552 /* NB: if BB is hung MAC will be hung too so skip check */
553 if (ahp->ah_hangs == 0 && (hangs & HAL_MAC_HANGS))
554 ahp->ah_hangs |= ar5416DetectMacHang(ah);
555 *result = &ahp->ah_hangs;
556 *resultsize = sizeof(ahp->ah_hangs);
559 return ar5212GetDiagState(ah, request,
560 args, argsize, result, resultsize);
564 ar5416SetRifsDelay(struct ath_hal *ah, const struct ieee80211_channel *chan,
568 HAL_BOOL is_chan_2g = AH_FALSE;
569 HAL_BOOL is_ht40 = AH_FALSE;
572 is_chan_2g = IEEE80211_IS_CHAN_2GHZ(chan);
575 is_ht40 = IEEE80211_IS_CHAN_HT40(chan);
577 /* Only support disabling RIFS delay for now */
578 HALASSERT(enable == AH_FALSE);
580 if (enable == AH_TRUE)
583 /* Change RIFS init delay to 0 */
584 val = OS_REG_READ(ah, AR_PHY_HEAVY_CLIP_FACTOR_RIFS);
585 val &= ~AR_PHY_RIFS_INIT_DELAY;
586 OS_REG_WRITE(ah, AR_PHY_HEAVY_CLIP_FACTOR_RIFS, val);
589 * For Owl, RIFS RX parameters are controlled differently;
590 * it isn't enabled in the inivals by default.
592 * For Sowl/Howl, RIFS RX is enabled in the inivals by default;
593 * the following code sets them back to non-RIFS values.
595 * For > Sowl/Howl, RIFS RX can be left on by default and so
596 * this function shouldn't be called.
598 if ((! AR_SREV_SOWL(ah)) && (! AR_SREV_HOWL(ah)))
601 /* Reset search delay to default values */
604 OS_REG_WRITE(ah, AR_PHY_SEARCH_START_DELAY, 0x268);
606 OS_REG_WRITE(ah, AR_PHY_SEARCH_START_DELAY, 0x134);
609 OS_REG_WRITE(ah, AR_PHY_SEARCH_START_DELAY, 0x370);
611 OS_REG_WRITE(ah, AR_PHY_SEARCH_START_DELAY, 0x1b8);
617 ar5416CompareDbgHang(struct ath_hal *ah, const mac_dbg_regs_t *regs,
618 const hal_mac_hang_check_t *check)
623 if (check->states & dcu_chain_state) {
626 for (i = 0; i < 6; i++) {
627 if (((regs->dma_dbg_4 >> (5*i)) & 0x1f) ==
628 check->dcu_chain_state)
629 found_states |= dcu_chain_state;
631 for (i = 0; i < 4; i++) {
632 if (((regs->dma_dbg_5 >> (5*i)) & 0x1f) ==
633 check->dcu_chain_state)
634 found_states |= dcu_chain_state;
637 if (check->states & dcu_complete_state) {
638 if ((regs->dma_dbg_6 & 0x3) == check->dcu_complete_state)
639 found_states |= dcu_complete_state;
641 if (check->states & qcu_stitch_state) {
642 if (((regs->dma_dbg_3 >> 18) & 0xf) == check->qcu_stitch_state)
643 found_states |= qcu_stitch_state;
645 if (check->states & qcu_fetch_state) {
646 if (((regs->dma_dbg_3 >> 22) & 0xf) == check->qcu_fetch_state)
647 found_states |= qcu_fetch_state;
649 if (check->states & qcu_complete_state) {
650 if (((regs->dma_dbg_3 >> 26) & 0x7) == check->qcu_complete_state)
651 found_states |= qcu_complete_state;
653 return (found_states == check->states);
656 #define NUM_STATUS_READS 50
659 ar5416DetectMacHang(struct ath_hal *ah)
661 static const hal_mac_hang_check_t hang_sig1 = {
662 .dcu_chain_state = 0x6,
663 .dcu_complete_state = 0x1,
664 .states = dcu_chain_state
665 | dcu_complete_state,
667 static const hal_mac_hang_check_t hang_sig2 = {
668 .qcu_stitch_state = 0x9,
669 .qcu_fetch_state = 0x8,
670 .qcu_complete_state = 0x4,
671 .states = qcu_stitch_state
673 | qcu_complete_state,
675 mac_dbg_regs_t mac_dbg;
678 mac_dbg.dma_dbg_3 = OS_REG_READ(ah, AR_DMADBG_3);
679 mac_dbg.dma_dbg_4 = OS_REG_READ(ah, AR_DMADBG_4);
680 mac_dbg.dma_dbg_5 = OS_REG_READ(ah, AR_DMADBG_5);
681 mac_dbg.dma_dbg_6 = OS_REG_READ(ah, AR_DMADBG_6);
682 for (i = 1; i <= NUM_STATUS_READS; i++) {
683 if (mac_dbg.dma_dbg_3 != OS_REG_READ(ah, AR_DMADBG_3) ||
684 mac_dbg.dma_dbg_4 != OS_REG_READ(ah, AR_DMADBG_4) ||
685 mac_dbg.dma_dbg_5 != OS_REG_READ(ah, AR_DMADBG_5) ||
686 mac_dbg.dma_dbg_6 != OS_REG_READ(ah, AR_DMADBG_6))
690 if (ar5416CompareDbgHang(ah, &mac_dbg, &hang_sig1))
691 return HAL_MAC_HANG_SIG1;
692 if (ar5416CompareDbgHang(ah, &mac_dbg, &hang_sig2))
693 return HAL_MAC_HANG_SIG2;
695 HALDEBUG(ah, HAL_DEBUG_HANG, "%s Found an unknown MAC hang signature "
696 "DMADBG_3=0x%x DMADBG_4=0x%x DMADBG_5=0x%x DMADBG_6=0x%x\n",
697 __func__, mac_dbg.dma_dbg_3, mac_dbg.dma_dbg_4, mac_dbg.dma_dbg_5,
704 * Determine if the baseband using the Observation Bus Register
707 ar5416DetectBBHang(struct ath_hal *ah)
709 #define N(a) (sizeof(a)/sizeof(a[0]))
711 * Check the PCU Observation Bus 1 register (0x806c)
712 * NUM_STATUS_READS times
714 * 4 known BB hang signatures -
715 * [1] bits 8,9,11 are 0. State machine state (bits 25-31) is 0x1E
716 * [2] bits 8,9 are 1, bit 11 is 0. State machine state
717 * (bits 25-31) is 0x52
718 * [3] bits 8,9 are 1, bit 11 is 0. State machine state
719 * (bits 25-31) is 0x18
720 * [4] bit 10 is 1, bit 11 is 0. WEP state (bits 12-17) is 0x2,
721 * Rx State (bits 20-24) is 0x7.
723 static const struct {
728 /* Reg Value Reg Mask Hang Code XXX */
729 { 0x1E000000, 0x7E000B00, HAL_BB_HANG_DFS },
730 { 0x52000B00, 0x7E000B00, HAL_BB_HANG_RIFS },
731 { 0x18000B00, 0x7E000B00, HAL_BB_HANG_RX_CLEAR },
732 { 0x00702400, 0x7E7FFFEF, HAL_BB_HANG_RX_CLEAR }
737 hang_sig = OS_REG_READ(ah, AR_OBSERV_1);
738 for (i = 1; i <= NUM_STATUS_READS; i++) {
739 if (hang_sig != OS_REG_READ(ah, AR_OBSERV_1))
742 for (i = 0; i < N(hang_list); i++)
743 if ((hang_sig & hang_list[i].mask) == hang_list[i].val) {
744 HALDEBUG(ah, HAL_DEBUG_HANG,
745 "%s BB hang, signature 0x%x, code 0x%x\n",
746 __func__, hang_sig, hang_list[i].code);
747 return hang_list[i].code;
750 HALDEBUG(ah, HAL_DEBUG_HANG, "%s Found an unknown BB hang signature! "
751 "<0x806c>=0x%x\n", __func__, hang_sig);
756 #undef NUM_STATUS_READS