Home | History | Annotate | Line # | Download | only in ar5416
      1  1.1  alc /*
      2  1.1  alc  * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
      3  1.1  alc  * Copyright (c) 2002-2008 Atheros Communications, Inc.
      4  1.1  alc  *
      5  1.1  alc  * Permission to use, copy, modify, and/or distribute this software for any
      6  1.1  alc  * purpose with or without fee is hereby granted, provided that the above
      7  1.1  alc  * copyright notice and this permission notice appear in all copies.
      8  1.1  alc  *
      9  1.1  alc  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
     10  1.1  alc  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     11  1.1  alc  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     12  1.1  alc  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     13  1.1  alc  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     14  1.1  alc  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     15  1.1  alc  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     16  1.1  alc  *
     17  1.2  wiz  * $Id: ar5416_misc.c,v 1.2 2012/02/12 13:47:19 wiz Exp $
     18  1.1  alc  */
     19  1.1  alc #include "opt_ah.h"
     20  1.1  alc 
     21  1.1  alc #include "ah.h"
     22  1.1  alc #include "ah_internal.h"
     23  1.1  alc #include "ah_devid.h"
     24  1.1  alc #ifdef AH_DEBUG
     25  1.1  alc #include "ah_desc.h"                    /* NB: for HAL_PHYERR* */
     26  1.1  alc #endif
     27  1.1  alc 
     28  1.1  alc #include "ar5416/ar5416.h"
     29  1.1  alc #include "ar5416/ar5416reg.h"
     30  1.1  alc #include "ar5416/ar5416phy.h"
     31  1.1  alc 
     32  1.1  alc /*
     33  1.1  alc  * Return the wireless modes (a,b,g,t) supported by hardware.
     34  1.1  alc  *
     35  1.1  alc  * This value is what is actually supported by the hardware
     36  1.1  alc  * and is unaffected by regulatory/country code settings.
     37  1.1  alc  *
     38  1.1  alc  */
     39  1.1  alc u_int
     40  1.1  alc ar5416GetWirelessModes(struct ath_hal *ah)
     41  1.1  alc {
     42  1.1  alc 	u_int mode;
     43  1.1  alc 
     44  1.1  alc 	mode = ar5212GetWirelessModes(ah);
     45  1.1  alc 	if (mode & HAL_MODE_11A)
     46  1.1  alc 		mode |= HAL_MODE_11NA_HT20
     47  1.1  alc 		     |  HAL_MODE_11NA_HT40PLUS
     48  1.1  alc 		     |  HAL_MODE_11NA_HT40MINUS
     49  1.1  alc 		     ;
     50  1.1  alc 	if (mode & HAL_MODE_11G)
     51  1.1  alc 		mode |= HAL_MODE_11NG_HT20
     52  1.1  alc 		     |  HAL_MODE_11NG_HT40PLUS
     53  1.1  alc 		     |  HAL_MODE_11NG_HT40MINUS
     54  1.1  alc 		     ;
     55  1.1  alc 	return mode;
     56  1.1  alc }
     57  1.1  alc 
     58  1.1  alc /*
     59  1.1  alc  * Change the LED blinking pattern to correspond to the connectivity
     60  1.1  alc  */
     61  1.1  alc void
     62  1.1  alc ar5416SetLedState(struct ath_hal *ah, HAL_LED_STATE state)
     63  1.1  alc {
     64  1.1  alc 	static const uint32_t ledbits[8] = {
     65  1.1  alc 		AR_MAC_LED_ASSOC_NONE,		/* HAL_LED_INIT */
     66  1.1  alc 		AR_MAC_LED_ASSOC_PEND,		/* HAL_LED_SCAN */
     67  1.1  alc 		AR_MAC_LED_ASSOC_PEND,		/* HAL_LED_AUTH */
     68  1.1  alc 		AR_MAC_LED_ASSOC_ACTIVE,	/* HAL_LED_ASSOC*/
     69  1.1  alc 		AR_MAC_LED_ASSOC_ACTIVE,	/* HAL_LED_RUN */
     70  1.1  alc 		AR_MAC_LED_ASSOC_NONE,
     71  1.1  alc 		AR_MAC_LED_ASSOC_NONE,
     72  1.1  alc 		AR_MAC_LED_ASSOC_NONE,
     73  1.1  alc 	};
     74  1.1  alc 	uint32_t bits;
     75  1.1  alc 
     76  1.1  alc 	bits = OS_REG_READ(ah, AR_MAC_LED);
     77  1.1  alc 	bits = (bits &~ AR_MAC_LED_MODE)
     78  1.1  alc 	     | SM(AR_MAC_LED_MODE_POWON, AR_MAC_LED_MODE)
     79  1.1  alc #if 1
     80  1.1  alc 	     | SM(AR_MAC_LED_MODE_NETON, AR_MAC_LED_MODE)
     81  1.1  alc #endif
     82  1.1  alc 	     ;
     83  1.1  alc 	bits = (bits &~ AR_MAC_LED_ASSOC)
     84  1.1  alc 	     | SM(ledbits[state & 0x7], AR_MAC_LED_ASSOC);
     85  1.1  alc 	OS_REG_WRITE(ah, AR_MAC_LED, bits);
     86  1.1  alc }
     87  1.1  alc 
     88  1.1  alc /*
     89  1.1  alc  * Reset the current hardware tsf for stamlme.
     90  1.1  alc  */
     91  1.1  alc void
     92  1.1  alc ar5416ResetTsf(struct ath_hal *ah)
     93  1.1  alc {
     94  1.1  alc 	uint32_t v;
     95  1.1  alc 	int i;
     96  1.1  alc 
     97  1.1  alc 	for (i = 0; i < 10; i++) {
     98  1.1  alc 		v = OS_REG_READ(ah, AR_SLP32_MODE);
     99  1.1  alc 		if ((v & AR_SLP32_TSF_WRITE_STATUS) == 0)
    100  1.1  alc 			break;
    101  1.1  alc 		OS_DELAY(10);
    102  1.1  alc 	}
    103  1.1  alc 	OS_REG_WRITE(ah, AR_RESET_TSF, AR_RESET_TSF_ONCE);
    104  1.1  alc }
    105  1.1  alc 
    106  1.1  alc HAL_BOOL
    107  1.1  alc ar5416SetAntennaSwitch(struct ath_hal *ah, HAL_ANT_SETTING settings)
    108  1.1  alc {
    109  1.1  alc 	return AH_TRUE;
    110  1.1  alc }
    111  1.1  alc 
    112  1.1  alc /* Setup decompression for given key index */
    113  1.1  alc HAL_BOOL
    114  1.1  alc ar5416SetDecompMask(struct ath_hal *ah, uint16_t keyidx, int en)
    115  1.1  alc {
    116  1.2  wiz 	return AH_TRUE;
    117  1.1  alc }
    118  1.1  alc 
    119  1.1  alc /* Setup coverage class */
    120  1.1  alc void
    121  1.1  alc ar5416SetCoverageClass(struct ath_hal *ah, uint8_t coverageclass, int now)
    122  1.1  alc {
    123  1.1  alc }
    124  1.1  alc 
    125  1.1  alc /*
    126  1.1  alc  * Return approximation of extension channel busy over an time interval
    127  1.1  alc  * 0% (clear) -> 100% (busy)
    128  1.1  alc  *
    129  1.1  alc  */
    130  1.1  alc uint32_t
    131  1.1  alc ar5416Get11nExtBusy(struct ath_hal *ah)
    132  1.1  alc {
    133  1.1  alc     struct ath_hal_5416 *ahp = AH5416(ah);
    134  1.1  alc     uint32_t busy; /* percentage */
    135  1.1  alc     uint32_t cycleCount, ctlBusy, extBusy;
    136  1.1  alc 
    137  1.1  alc     ctlBusy = OS_REG_READ(ah, AR_RCCNT);
    138  1.1  alc     extBusy = OS_REG_READ(ah, AR_EXTRCCNT);
    139  1.1  alc     cycleCount = OS_REG_READ(ah, AR_CCCNT);
    140  1.1  alc 
    141  1.1  alc     if (ahp->ah_cycleCount == 0 || ahp->ah_cycleCount > cycleCount) {
    142  1.1  alc         /*
    143  1.1  alc          * Cycle counter wrap (or initial call); it's not possible
    144  1.1  alc          * to accurately calculate a value because the registers
    145  1.1  alc          * right shift rather than wrap--so punt and return 0.
    146  1.1  alc          */
    147  1.1  alc         busy = 0;
    148  1.1  alc         HALDEBUG(ah, HAL_DEBUG_ANY, "%s: cycle counter wrap. ExtBusy = 0\n",
    149  1.1  alc 	    __func__);
    150  1.1  alc 
    151  1.1  alc     } else {
    152  1.1  alc         uint32_t cycleDelta = cycleCount - ahp->ah_cycleCount;
    153  1.1  alc         uint32_t ctlBusyDelta = ctlBusy - ahp->ah_ctlBusy;
    154  1.1  alc         uint32_t extBusyDelta = extBusy - ahp->ah_extBusy;
    155  1.1  alc         uint32_t ctlClearDelta = 0;
    156  1.1  alc 
    157  1.1  alc         /* Compute control channel rxclear.
    158  1.1  alc          * The cycle delta may be less than the control channel delta.
    159  1.1  alc          * This could be solved by freezing the timers (or an atomic read,
    160  1.1  alc          * if one was available). Checking for the condition should be
    161  1.1  alc          * sufficient.
    162  1.1  alc          */
    163  1.1  alc         if (cycleDelta > ctlBusyDelta) {
    164  1.1  alc             ctlClearDelta = cycleDelta - ctlBusyDelta;
    165  1.1  alc         }
    166  1.1  alc 
    167  1.1  alc         /* Compute ratio of extension channel busy to control channel clear
    168  1.1  alc          * as an approximation to extension channel cleanliness.
    169  1.1  alc          *
    170  1.1  alc          * According to the hardware folks, ext rxclear is undefined
    171  1.1  alc          * if the ctrl rxclear is de-asserted (i.e. busy)
    172  1.1  alc          */
    173  1.1  alc         if (ctlClearDelta) {
    174  1.1  alc             busy = (extBusyDelta * 100) / ctlClearDelta;
    175  1.1  alc         } else {
    176  1.1  alc             busy = 100;
    177  1.1  alc         }
    178  1.1  alc         if (busy > 100) {
    179  1.1  alc             busy = 100;
    180  1.1  alc         }
    181  1.1  alc #if 0
    182  1.1  alc         HALDEBUG(ah, HAL_DEBUG_ANY, "%s: cycleDelta 0x%x, ctlBusyDelta 0x%x, "
    183  1.1  alc              "extBusyDelta 0x%x, ctlClearDelta 0x%x, "
    184  1.1  alc              "busy %d\n",
    185  1.1  alc               __func__, cycleDelta, ctlBusyDelta, extBusyDelta, ctlClearDelta, busy);
    186  1.1  alc #endif
    187  1.1  alc     }
    188  1.1  alc 
    189  1.1  alc     ahp->ah_cycleCount = cycleCount;
    190  1.1  alc     ahp->ah_ctlBusy = ctlBusy;
    191  1.1  alc     ahp->ah_extBusy = extBusy;
    192  1.1  alc 
    193  1.1  alc     return busy;
    194  1.1  alc }
    195  1.1  alc 
    196  1.1  alc /*
    197  1.1  alc  * Configure 20/40 operation
    198  1.1  alc  *
    199  1.1  alc  * 20/40 = joint rx clear (control and extension)
    200  1.1  alc  * 20    = rx clear (control)
    201  1.1  alc  *
    202  1.1  alc  * - NOTE: must stop MAC (tx) and requeue 40 MHz packets as 20 MHz when changing
    203  1.1  alc  *         from 20/40 => 20 only
    204  1.1  alc  */
    205  1.1  alc void
    206  1.1  alc ar5416Set11nMac2040(struct ath_hal *ah, HAL_HT_MACMODE mode)
    207  1.1  alc {
    208  1.1  alc     uint32_t macmode;
    209  1.1  alc 
    210  1.1  alc     /* Configure MAC for 20/40 operation */
    211  1.1  alc     if (mode == HAL_HT_MACMODE_2040) {
    212  1.1  alc         macmode = AR_2040_JOINED_RX_CLEAR;
    213  1.1  alc     } else {
    214  1.1  alc         macmode = 0;
    215  1.1  alc     }
    216  1.1  alc     OS_REG_WRITE(ah, AR_2040_MODE, macmode);
    217  1.1  alc }
    218  1.1  alc 
    219  1.1  alc /*
    220  1.1  alc  * Get Rx clear (control/extension channel)
    221  1.1  alc  *
    222  1.1  alc  * Returns active low (busy) for ctrl/ext channel
    223  1.1  alc  * Owl 2.0
    224  1.1  alc  */
    225  1.1  alc HAL_HT_RXCLEAR
    226  1.1  alc ar5416Get11nRxClear(struct ath_hal *ah)
    227  1.1  alc {
    228  1.1  alc     HAL_HT_RXCLEAR rxclear = 0;
    229  1.1  alc     uint32_t val;
    230  1.1  alc 
    231  1.1  alc     val = OS_REG_READ(ah, AR_DIAG_SW);
    232  1.1  alc 
    233  1.1  alc     /* control channel */
    234  1.1  alc     if (val & AR_DIAG_RXCLEAR_CTL_LOW) {
    235  1.1  alc         rxclear |= HAL_RX_CLEAR_CTL_LOW;
    236  1.1  alc     }
    237  1.1  alc     /* extension channel */
    238  1.1  alc     if (val & AR_DIAG_RXCLEAR_CTL_LOW) {
    239  1.1  alc         rxclear |= HAL_RX_CLEAR_EXT_LOW;
    240  1.1  alc     }
    241  1.1  alc     return rxclear;
    242  1.1  alc }
    243  1.1  alc 
    244  1.1  alc /*
    245  1.1  alc  * Set Rx clear (control/extension channel)
    246  1.1  alc  *
    247  1.1  alc  * Useful for forcing the channel to appear busy for
    248  1.1  alc  * debugging/diagnostics
    249  1.1  alc  * Owl 2.0
    250  1.1  alc  */
    251  1.1  alc void
    252  1.1  alc ar5416Set11nRxClear(struct ath_hal *ah, HAL_HT_RXCLEAR rxclear)
    253  1.1  alc {
    254  1.1  alc     /* control channel */
    255  1.1  alc     if (rxclear & HAL_RX_CLEAR_CTL_LOW) {
    256  1.1  alc         OS_REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RXCLEAR_CTL_LOW);
    257  1.1  alc     } else {
    258  1.1  alc         OS_REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_RXCLEAR_CTL_LOW);
    259  1.1  alc     }
    260  1.1  alc     /* extension channel */
    261  1.1  alc     if (rxclear & HAL_RX_CLEAR_EXT_LOW) {
    262  1.1  alc         OS_REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RXCLEAR_EXT_LOW);
    263  1.1  alc     } else {
    264  1.1  alc         OS_REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_RXCLEAR_EXT_LOW);
    265  1.1  alc     }
    266  1.1  alc }
    267  1.1  alc 
    268  1.1  alc HAL_STATUS
    269  1.1  alc ar5416GetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
    270  1.1  alc         uint32_t capability, uint32_t *result)
    271  1.1  alc {
    272  1.1  alc 	switch (type) {
    273  1.1  alc 	case HAL_CAP_BB_HANG:
    274  1.1  alc 		switch (capability) {
    275  1.1  alc 		case HAL_BB_HANG_RIFS:
    276  1.1  alc 			return AR_SREV_SOWL(ah) ? HAL_OK : HAL_ENOTSUPP;
    277  1.1  alc 		case HAL_BB_HANG_DFS:
    278  1.1  alc 			return AR_SREV_SOWL(ah) ? HAL_OK : HAL_ENOTSUPP;
    279  1.1  alc 		case HAL_BB_HANG_RX_CLEAR:
    280  1.1  alc 			return AR_SREV_MERLIN(ah) ? HAL_OK : HAL_ENOTSUPP;
    281  1.1  alc 		}
    282  1.1  alc 		break;
    283  1.1  alc 	case HAL_CAP_MAC_HANG:
    284  1.1  alc 		return ((ah->ah_macVersion == AR_XSREV_VERSION_OWL_PCI) ||
    285  1.1  alc 		    (ah->ah_macVersion == AR_XSREV_VERSION_OWL_PCIE) ||
    286  1.1  alc 		    AR_SREV_SOWL(ah)) ?
    287  1.1  alc 			HAL_OK : HAL_ENOTSUPP;
    288  1.1  alc 	default:
    289  1.1  alc 		break;
    290  1.1  alc 	}
    291  1.1  alc 	return ar5212GetCapability(ah, type, capability, result);
    292  1.1  alc }
    293  1.1  alc 
    294  1.1  alc static int ar5416DetectMacHang(struct ath_hal *ah);
    295  1.1  alc static int ar5416DetectBBHang(struct ath_hal *ah);
    296  1.1  alc 
    297  1.1  alc HAL_BOOL
    298  1.1  alc ar5416GetDiagState(struct ath_hal *ah, int request,
    299  1.1  alc 	const void *args, uint32_t argsize,
    300  1.1  alc 	void **result, uint32_t *resultsize)
    301  1.1  alc {
    302  1.1  alc 	struct ath_hal_5416 *ahp = AH5416(ah);
    303  1.1  alc 	int hangs;
    304  1.1  alc 
    305  1.1  alc 	if (ath_hal_getdiagstate(ah, request, args, argsize, result, resultsize))
    306  1.1  alc 		return AH_TRUE;
    307  1.1  alc 	switch (request) {
    308  1.1  alc 	case HAL_DIAG_EEPROM:
    309  1.1  alc 		return ath_hal_eepromDiag(ah, request,
    310  1.1  alc 		    args, argsize, result, resultsize);
    311  1.1  alc 	case HAL_DIAG_CHECK_HANGS:
    312  1.1  alc 		if (argsize != sizeof(int))
    313  1.1  alc 			return AH_FALSE;
    314  1.1  alc 		hangs = *(const int *) args;
    315  1.1  alc 		ahp->ah_hangs = 0;
    316  1.1  alc 		if (hangs & HAL_BB_HANGS)
    317  1.1  alc 			ahp->ah_hangs |= ar5416DetectBBHang(ah);
    318  1.1  alc 		/* NB: if BB is hung MAC will be hung too so skip check */
    319  1.1  alc 		if (ahp->ah_hangs == 0 && (hangs & HAL_MAC_HANGS))
    320  1.1  alc 			ahp->ah_hangs |= ar5416DetectMacHang(ah);
    321  1.1  alc 		*result = &ahp->ah_hangs;
    322  1.1  alc 		*resultsize = sizeof(ahp->ah_hangs);
    323  1.1  alc 		return AH_TRUE;
    324  1.1  alc 	}
    325  1.1  alc 	return ar5212GetDiagState(ah, request,
    326  1.1  alc 	    args, argsize, result, resultsize);
    327  1.1  alc }
    328  1.1  alc 
    329  1.1  alc typedef struct {
    330  1.1  alc 	uint32_t dma_dbg_3;
    331  1.1  alc 	uint32_t dma_dbg_4;
    332  1.1  alc 	uint32_t dma_dbg_5;
    333  1.1  alc 	uint32_t dma_dbg_6;
    334  1.1  alc } mac_dbg_regs_t;
    335  1.1  alc 
    336  1.1  alc typedef enum {
    337  1.1  alc 	dcu_chain_state		= 0x1,
    338  1.1  alc 	dcu_complete_state	= 0x2,
    339  1.1  alc 	qcu_state		= 0x4,
    340  1.1  alc 	qcu_fsp_ok		= 0x8,
    341  1.1  alc 	qcu_fsp_state		= 0x10,
    342  1.1  alc 	qcu_stitch_state	= 0x20,
    343  1.1  alc 	qcu_fetch_state		= 0x40,
    344  1.1  alc 	qcu_complete_state	= 0x80
    345  1.1  alc } hal_mac_hangs_t;
    346  1.1  alc 
    347  1.1  alc typedef struct {
    348  1.1  alc 	int states;
    349  1.1  alc 	uint8_t dcu_chain_state;
    350  1.1  alc 	uint8_t dcu_complete_state;
    351  1.1  alc 	uint8_t qcu_state;
    352  1.1  alc 	uint8_t qcu_fsp_ok;
    353  1.1  alc 	uint8_t qcu_fsp_state;
    354  1.1  alc 	uint8_t qcu_stitch_state;
    355  1.1  alc 	uint8_t qcu_fetch_state;
    356  1.1  alc 	uint8_t qcu_complete_state;
    357  1.1  alc } hal_mac_hang_check_t;
    358  1.1  alc 
    359  1.1  alc static HAL_BOOL
    360  1.1  alc ar5416CompareDbgHang(struct ath_hal *ah, const mac_dbg_regs_t *regs,
    361  1.1  alc     const hal_mac_hang_check_t *check)
    362  1.1  alc {
    363  1.1  alc 	int found_states;
    364  1.1  alc 
    365  1.1  alc 	found_states = 0;
    366  1.1  alc 	if (check->states & dcu_chain_state) {
    367  1.1  alc 		int i;
    368  1.1  alc 
    369  1.1  alc 		for (i = 0; i < 6; i++) {
    370  1.1  alc 			if (((regs->dma_dbg_4 >> (5*i)) & 0x1f) ==
    371  1.1  alc 			    check->dcu_chain_state)
    372  1.1  alc 				found_states |= dcu_chain_state;
    373  1.1  alc 		}
    374  1.1  alc 		for (i = 0; i < 4; i++) {
    375  1.1  alc 			if (((regs->dma_dbg_5 >> (5*i)) & 0x1f) ==
    376  1.1  alc 			    check->dcu_chain_state)
    377  1.1  alc 				found_states |= dcu_chain_state;
    378  1.1  alc 		}
    379  1.1  alc 	}
    380  1.1  alc 	if (check->states & dcu_complete_state) {
    381  1.1  alc 		if ((regs->dma_dbg_6 & 0x3) == check->dcu_complete_state)
    382  1.1  alc 			found_states |= dcu_complete_state;
    383  1.1  alc 	}
    384  1.1  alc 	if (check->states & qcu_stitch_state) {
    385  1.1  alc 		if (((regs->dma_dbg_3 >> 18) & 0xf) == check->qcu_stitch_state)
    386  1.1  alc 			found_states |= qcu_stitch_state;
    387  1.1  alc 	}
    388  1.1  alc 	if (check->states & qcu_fetch_state) {
    389  1.1  alc 		if (((regs->dma_dbg_3 >> 22) & 0xf) == check->qcu_fetch_state)
    390  1.1  alc 			found_states |= qcu_fetch_state;
    391  1.1  alc 	}
    392  1.1  alc 	if (check->states & qcu_complete_state) {
    393  1.1  alc 		if (((regs->dma_dbg_3 >> 26) & 0x7) == check->qcu_complete_state)
    394  1.1  alc 			found_states |= qcu_complete_state;
    395  1.1  alc 	}
    396  1.1  alc 	return (found_states == check->states);
    397  1.1  alc }
    398  1.1  alc 
    399  1.1  alc #define NUM_STATUS_READS 50
    400  1.1  alc 
    401  1.1  alc static int
    402  1.1  alc ar5416DetectMacHang(struct ath_hal *ah)
    403  1.1  alc {
    404  1.1  alc 	static const hal_mac_hang_check_t hang_sig1 = {
    405  1.1  alc 		.dcu_chain_state	= 0x6,
    406  1.1  alc 		.dcu_complete_state	= 0x1,
    407  1.1  alc 		.states			= dcu_chain_state
    408  1.1  alc 					| dcu_complete_state,
    409  1.1  alc 	};
    410  1.1  alc 	static const hal_mac_hang_check_t hang_sig2 = {
    411  1.1  alc 		.qcu_stitch_state	= 0x9,
    412  1.1  alc 		.qcu_fetch_state	= 0x8,
    413  1.1  alc 		.qcu_complete_state	= 0x4,
    414  1.1  alc 		.states			= qcu_stitch_state
    415  1.1  alc 					| qcu_fetch_state
    416  1.1  alc 					| qcu_complete_state,
    417  1.1  alc         };
    418  1.1  alc 	mac_dbg_regs_t mac_dbg;
    419  1.1  alc 	int i;
    420  1.1  alc 
    421  1.1  alc 	mac_dbg.dma_dbg_3 = OS_REG_READ(ah, AR_DMADBG_3);
    422  1.1  alc 	mac_dbg.dma_dbg_4 = OS_REG_READ(ah, AR_DMADBG_4);
    423  1.1  alc 	mac_dbg.dma_dbg_5 = OS_REG_READ(ah, AR_DMADBG_5);
    424  1.1  alc 	mac_dbg.dma_dbg_6 = OS_REG_READ(ah, AR_DMADBG_6);
    425  1.1  alc 	for (i = 1; i <= NUM_STATUS_READS; i++) {
    426  1.1  alc 		if (mac_dbg.dma_dbg_3 != OS_REG_READ(ah, AR_DMADBG_3) ||
    427  1.1  alc 		    mac_dbg.dma_dbg_4 != OS_REG_READ(ah, AR_DMADBG_4) ||
    428  1.1  alc 		    mac_dbg.dma_dbg_5 != OS_REG_READ(ah, AR_DMADBG_5) ||
    429  1.1  alc 		    mac_dbg.dma_dbg_6 != OS_REG_READ(ah, AR_DMADBG_6))
    430  1.1  alc 			return 0;
    431  1.1  alc 	}
    432  1.1  alc 
    433  1.1  alc 	if (ar5416CompareDbgHang(ah, &mac_dbg, &hang_sig1))
    434  1.1  alc 		return HAL_MAC_HANG_SIG1;
    435  1.1  alc 	if (ar5416CompareDbgHang(ah, &mac_dbg, &hang_sig2))
    436  1.1  alc 		return HAL_MAC_HANG_SIG2;
    437  1.1  alc 
    438  1.1  alc 	HALDEBUG(ah, HAL_DEBUG_ANY, "%s Found an unknown MAC hang signature "
    439  1.1  alc 	    "DMADBG_3=0x%x DMADBG_4=0x%x DMADBG_5=0x%x DMADBG_6=0x%x\n",
    440  1.1  alc 	    __func__, mac_dbg.dma_dbg_3, mac_dbg.dma_dbg_4, mac_dbg.dma_dbg_5,
    441  1.1  alc 	    mac_dbg.dma_dbg_6);
    442  1.1  alc 
    443  1.1  alc 	return HAL_MAC_HANG_UNKNOWN;
    444  1.1  alc }
    445  1.1  alc 
    446  1.1  alc /*
    447  1.1  alc  * Determine if the baseband using the Observation Bus Register
    448  1.1  alc  */
    449  1.1  alc static int
    450  1.1  alc ar5416DetectBBHang(struct ath_hal *ah)
    451  1.1  alc {
    452  1.1  alc #define N(a) (sizeof(a)/sizeof(a[0]))
    453  1.1  alc 	/*
    454  1.1  alc 	 * Check the PCU Observation Bus 1 register (0x806c)
    455  1.1  alc 	 * NUM_STATUS_READS times
    456  1.1  alc 	 *
    457  1.1  alc 	 * 4 known BB hang signatures -
    458  1.1  alc 	 * [1] bits 8,9,11 are 0. State machine state (bits 25-31) is 0x1E
    459  1.1  alc 	 * [2] bits 8,9 are 1, bit 11 is 0. State machine state
    460  1.1  alc 	 *     (bits 25-31) is 0x52
    461  1.1  alc 	 * [3] bits 8,9 are 1, bit 11 is 0. State machine state
    462  1.1  alc 	 *     (bits 25-31) is 0x18
    463  1.1  alc 	 * [4] bit 10 is 1, bit 11 is 0. WEP state (bits 12-17) is 0x2,
    464  1.1  alc 	 *     Rx State (bits 20-24) is 0x7.
    465  1.1  alc 	 */
    466  1.1  alc 	static const struct {
    467  1.1  alc 		uint32_t val;
    468  1.1  alc 		uint32_t mask;
    469  1.1  alc 		int code;
    470  1.1  alc 	} hang_list[] = {
    471  1.1  alc 		/* Reg Value   Reg Mask    Hang Code XXX */
    472  1.1  alc 		{ 0x1E000000, 0x7E000B00, HAL_BB_HANG_DFS },
    473  1.1  alc 		{ 0x52000B00, 0x7E000B00, HAL_BB_HANG_RIFS },
    474  1.1  alc 		{ 0x18000B00, 0x7E000B00, HAL_BB_HANG_RX_CLEAR },
    475  1.1  alc 		{ 0x00702400, 0x7E7FFFEF, HAL_BB_HANG_RX_CLEAR }
    476  1.1  alc 	};
    477  1.1  alc 	uint32_t hang_sig;
    478  1.1  alc 	int i;
    479  1.1  alc 
    480  1.1  alc 	hang_sig = OS_REG_READ(ah, AR_OBSERV_1);
    481  1.1  alc 	for (i = 1; i <= NUM_STATUS_READS; i++) {
    482  1.1  alc 		if (hang_sig != OS_REG_READ(ah, AR_OBSERV_1))
    483  1.1  alc 			return 0;
    484  1.1  alc 	}
    485  1.1  alc 	for (i = 0; i < N(hang_list); i++)
    486  1.1  alc 		if ((hang_sig & hang_list[i].mask) == hang_list[i].val) {
    487  1.1  alc 			HALDEBUG(ah, HAL_DEBUG_ANY,
    488  1.1  alc 			    "%s BB hang, signature 0x%x, code 0x%x\n",
    489  1.1  alc 			    __func__, hang_sig, hang_list[i].code);
    490  1.1  alc 			return hang_list[i].code;
    491  1.1  alc 		}
    492  1.1  alc 
    493  1.1  alc 	HALDEBUG(ah, HAL_DEBUG_ANY, "%s Found an unknown BB hang signature! "
    494  1.1  alc 	    "<0x806c>=0x%x\n", __func__, hang_sig);
    495  1.1  alc 
    496  1.1  alc 	return HAL_BB_HANG_UNKNOWN;
    497  1.1  alc #undef N
    498  1.1  alc }
    499  1.1  alc #undef NUM_STATUS_READS
    500