xref: /freebsd/sys/dev/ath/ath_hal/ar5416/ar5416_misc.c (revision aa77200569e397d6ff1fdb4d255d0fa254d0a128)
1 /*
2  * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
3  * Copyright (c) 2002-2008 Atheros Communications, Inc.
4  *
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.
8  *
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.
16  *
17  * $FreeBSD$
18  */
19 #include "opt_ah.h"
20 
21 #include "ah.h"
22 #include "ah_internal.h"
23 #include "ah_devid.h"
24 #include "ah_desc.h"                    /* NB: for HAL_PHYERR* */
25 
26 #include "ar5416/ar5416.h"
27 #include "ar5416/ar5416reg.h"
28 #include "ar5416/ar5416phy.h"
29 
30 #include "ah_eeprom_v14.h"	/* for owl_get_ntxchains() */
31 
32 /*
33  * Return the wireless modes (a,b,g,n,t) supported by hardware.
34  *
35  * This value is what is actually supported by the hardware
36  * and is unaffected by regulatory/country code settings.
37  *
38  */
39 u_int
40 ar5416GetWirelessModes(struct ath_hal *ah)
41 {
42 	u_int mode;
43 	struct ath_hal_private *ahpriv = AH_PRIVATE(ah);
44 	HAL_CAPABILITIES *pCap = &ahpriv->ah_caps;
45 
46 	mode = ar5212GetWirelessModes(ah);
47 
48 	/* Only enable HT modes if the NIC supports HT */
49 	if (pCap->halHTSupport == AH_TRUE && (mode & HAL_MODE_11A))
50 		mode |= HAL_MODE_11NA_HT20
51 		     |  HAL_MODE_11NA_HT40PLUS
52 		     |  HAL_MODE_11NA_HT40MINUS
53 		     ;
54 	if (pCap->halHTSupport == AH_TRUE && (mode & HAL_MODE_11G))
55 		mode |= HAL_MODE_11NG_HT20
56 		     |  HAL_MODE_11NG_HT40PLUS
57 		     |  HAL_MODE_11NG_HT40MINUS
58 		     ;
59 	return mode;
60 }
61 
62 /*
63  * Change the LED blinking pattern to correspond to the connectivity
64  */
65 void
66 ar5416SetLedState(struct ath_hal *ah, HAL_LED_STATE state)
67 {
68 	static const uint32_t ledbits[8] = {
69 		AR_MAC_LED_ASSOC_NONE,		/* HAL_LED_INIT */
70 		AR_MAC_LED_ASSOC_PEND,		/* HAL_LED_SCAN */
71 		AR_MAC_LED_ASSOC_PEND,		/* HAL_LED_AUTH */
72 		AR_MAC_LED_ASSOC_ACTIVE,	/* HAL_LED_ASSOC*/
73 		AR_MAC_LED_ASSOC_ACTIVE,	/* HAL_LED_RUN */
74 		AR_MAC_LED_ASSOC_NONE,
75 		AR_MAC_LED_ASSOC_NONE,
76 		AR_MAC_LED_ASSOC_NONE,
77 	};
78 
79 	if (AR_SREV_HOWL(ah))
80 		return;
81 
82 	/*
83 	 * Set the blink operating mode.
84 	 */
85 	OS_REG_RMW_FIELD(ah, AR_MAC_LED,
86 	    AR_MAC_LED_ASSOC, ledbits[state & 0x7]);
87 
88 	/* XXX Blink slow mode? */
89 	/* XXX Blink threshold? */
90 	/* XXX Blink sleep hystersis? */
91 
92 	/*
93 	 * Set the LED blink configuration to be proportional
94 	 * to the current TX and RX filter bytes.  (Ie, RX'ed
95 	 * frames that don't match the filter are ignored.)
96 	 * This means that higher TX/RX throughput will result
97 	 * in the blink rate increasing.
98 	 */
99 	OS_REG_RMW_FIELD(ah, AR_MAC_LED, AR_MAC_LED_MODE,
100 	    AR_MAC_LED_MODE_PROP);
101 }
102 
103 /*
104  * Get the current hardware tsf for stamlme
105  */
106 uint64_t
107 ar5416GetTsf64(struct ath_hal *ah)
108 {
109 	uint32_t low1, low2, u32;
110 
111 	/* sync multi-word read */
112 	low1 = OS_REG_READ(ah, AR_TSF_L32);
113 	u32 = OS_REG_READ(ah, AR_TSF_U32);
114 	low2 = OS_REG_READ(ah, AR_TSF_L32);
115 	if (low2 < low1) {	/* roll over */
116 		/*
117 		 * If we are not preempted this will work.  If we are
118 		 * then we re-reading AR_TSF_U32 does no good as the
119 		 * low bits will be meaningless.  Likewise reading
120 		 * L32, U32, U32, then comparing the last two reads
121 		 * to check for rollover doesn't help if preempted--so
122 		 * we take this approach as it costs one less PCI read
123 		 * which can be noticeable when doing things like
124 		 * timestamping packets in monitor mode.
125 		 */
126 		u32++;
127 	}
128 	return (((uint64_t) u32) << 32) | ((uint64_t) low2);
129 }
130 
131 /*
132  * Update the TSF.
133  *
134  * The full TSF is only updated once the upper 32 bits have
135  * been written.  Writing only the lower 32 bits of the TSF
136  * will not actually correctly update the TSF.
137  *
138  * The #if 0'ed code is to check whether the previous TSF
139  * reset or write has completed before writing to the
140  * TSF.  Strictly speaking, it should be also checked before
141  * reading the TSF as the write/reset may not have completed.
142  */
143 void
144 ar5416SetTsf64(struct ath_hal *ah, uint64_t tsf64)
145 {
146 	/* XXX check if this is correct! */
147 #if 0
148 	int i;
149 	uint32_t v;
150 
151 	for (i = 0; i < 10; i++) {
152 		v = OS_REG_READ(ah, AR_SLP32_MODE);
153 		if ((v & AR_SLP32_TSF_WRITE_STATUS) == 0)
154 			break;
155 		OS_DELAY(10);
156 	}
157 	if (i == 10)
158 		ath_hal_printf(ah, "%s: couldn't slew things right!\n", __func__);
159 #endif
160 
161 	OS_REG_WRITE(ah, AR_TSF_L32, tsf64 & 0xffffffff);
162 	OS_REG_WRITE(ah, AR_TSF_U32, (tsf64 >> 32) & 0xffffffff);
163 }
164 
165 /*
166  * Reset the current hardware tsf for stamlme.
167  */
168 void
169 ar5416ResetTsf(struct ath_hal *ah)
170 {
171 	uint32_t v;
172 	int i;
173 
174 	for (i = 0; i < 10; i++) {
175 		v = OS_REG_READ(ah, AR_SLP32_MODE);
176 		if ((v & AR_SLP32_TSF_WRITE_STATUS) == 0)
177 			break;
178 		OS_DELAY(10);
179 	}
180 	OS_REG_WRITE(ah, AR_RESET_TSF, AR_RESET_TSF_ONCE);
181 }
182 
183 uint32_t
184 ar5416GetCurRssi(struct ath_hal *ah)
185 {
186 	if (AR_SREV_OWL(ah))
187 		return (OS_REG_READ(ah, AR_PHY_CURRENT_RSSI) & 0xff);
188 	return (OS_REG_READ(ah, AR9130_PHY_CURRENT_RSSI) & 0xff);
189 }
190 
191 HAL_BOOL
192 ar5416SetAntennaSwitch(struct ath_hal *ah, HAL_ANT_SETTING settings)
193 {
194 	return AH_TRUE;
195 }
196 
197 /* Setup decompression for given key index */
198 HAL_BOOL
199 ar5416SetDecompMask(struct ath_hal *ah, uint16_t keyidx, int en)
200 {
201 	return AH_TRUE;
202 }
203 
204 /* Setup coverage class */
205 void
206 ar5416SetCoverageClass(struct ath_hal *ah, uint8_t coverageclass, int now)
207 {
208 
209 	ar5212SetCoverageClass(ah, coverageclass, now);
210 }
211 
212 /*
213  * Return the busy for rx_frame, rx_clear, and tx_frame
214  */
215 HAL_BOOL
216 ar5416GetMibCycleCounts(struct ath_hal *ah, HAL_SURVEY_SAMPLE *hsample)
217 {
218 	struct ath_hal_5416 *ahp = AH5416(ah);
219 	u_int32_t good = AH_TRUE;
220 
221 	/* XXX freeze/unfreeze mib counters */
222 	uint32_t rc = OS_REG_READ(ah, AR_RCCNT);
223 	uint32_t ec = OS_REG_READ(ah, AR_EXTRCCNT);
224 	uint32_t rf = OS_REG_READ(ah, AR_RFCNT);
225 	uint32_t tf = OS_REG_READ(ah, AR_TFCNT);
226 	uint32_t cc = OS_REG_READ(ah, AR_CCCNT); /* read cycles last */
227 
228 	if (ahp->ah_cycleCount == 0 || ahp->ah_cycleCount > cc) {
229 		/*
230 		 * Cycle counter wrap (or initial call); it's not possible
231 		 * to accurately calculate a value because the registers
232 		 * right shift rather than wrap--so punt and return 0.
233 		 */
234 		HALDEBUG(ah, HAL_DEBUG_ANY,
235 			    "%s: cycle counter wrap. ExtBusy = 0\n", __func__);
236 			good = AH_FALSE;
237 	} else {
238 		hsample->cycle_count = cc - ahp->ah_cycleCount;
239 		hsample->chan_busy = rc - ahp->ah_ctlBusy;
240 		hsample->ext_chan_busy = ec - ahp->ah_extBusy;
241 		hsample->rx_busy = rf - ahp->ah_rxBusy;
242 		hsample->tx_busy = tf - ahp->ah_txBusy;
243 	}
244 
245 	/*
246 	 * Keep a copy of the MIB results so the next sample has something
247 	 * to work from.
248 	 */
249 	ahp->ah_cycleCount = cc;
250 	ahp->ah_rxBusy = rf;
251 	ahp->ah_ctlBusy = rc;
252 	ahp->ah_txBusy = tf;
253 	ahp->ah_extBusy = ec;
254 
255 	return (good);
256 }
257 
258 /*
259  * Return approximation of extension channel busy over an time interval
260  * 0% (clear) -> 100% (busy)
261  *
262  * XXX TODO: update this to correctly sample all the counters,
263  *           rather than a subset of it.
264  */
265 uint32_t
266 ar5416Get11nExtBusy(struct ath_hal *ah)
267 {
268     struct ath_hal_5416 *ahp = AH5416(ah);
269     uint32_t busy; /* percentage */
270     uint32_t cycleCount, ctlBusy, extBusy;
271 
272     ctlBusy = OS_REG_READ(ah, AR_RCCNT);
273     extBusy = OS_REG_READ(ah, AR_EXTRCCNT);
274     cycleCount = OS_REG_READ(ah, AR_CCCNT);
275 
276     if (ahp->ah_cycleCount == 0 || ahp->ah_cycleCount > cycleCount) {
277         /*
278          * Cycle counter wrap (or initial call); it's not possible
279          * to accurately calculate a value because the registers
280          * right shift rather than wrap--so punt and return 0.
281          */
282         busy = 0;
283         HALDEBUG(ah, HAL_DEBUG_ANY, "%s: cycle counter wrap. ExtBusy = 0\n",
284 	    __func__);
285 
286     } else {
287         uint32_t cycleDelta = cycleCount - ahp->ah_cycleCount;
288         uint32_t ctlBusyDelta = ctlBusy - ahp->ah_ctlBusy;
289         uint32_t extBusyDelta = extBusy - ahp->ah_extBusy;
290         uint32_t ctlClearDelta = 0;
291 
292         /* Compute control channel rxclear.
293          * The cycle delta may be less than the control channel delta.
294          * This could be solved by freezing the timers (or an atomic read,
295          * if one was available). Checking for the condition should be
296          * sufficient.
297          */
298         if (cycleDelta > ctlBusyDelta) {
299             ctlClearDelta = cycleDelta - ctlBusyDelta;
300         }
301 
302         /* Compute ratio of extension channel busy to control channel clear
303          * as an approximation to extension channel cleanliness.
304          *
305          * According to the hardware folks, ext rxclear is undefined
306          * if the ctrl rxclear is de-asserted (i.e. busy)
307          */
308         if (ctlClearDelta) {
309             busy = (extBusyDelta * 100) / ctlClearDelta;
310         } else {
311             busy = 100;
312         }
313         if (busy > 100) {
314             busy = 100;
315         }
316 #if 0
317         HALDEBUG(ah, HAL_DEBUG_ANY, "%s: cycleDelta 0x%x, ctlBusyDelta 0x%x, "
318              "extBusyDelta 0x%x, ctlClearDelta 0x%x, "
319              "busy %d\n",
320               __func__, cycleDelta, ctlBusyDelta, extBusyDelta, ctlClearDelta, busy);
321 #endif
322     }
323 
324     ahp->ah_cycleCount = cycleCount;
325     ahp->ah_ctlBusy = ctlBusy;
326     ahp->ah_extBusy = extBusy;
327 
328     return busy;
329 }
330 
331 /*
332  * Configure 20/40 operation
333  *
334  * 20/40 = joint rx clear (control and extension)
335  * 20    = rx clear (control)
336  *
337  * - NOTE: must stop MAC (tx) and requeue 40 MHz packets as 20 MHz when changing
338  *         from 20/40 => 20 only
339  */
340 void
341 ar5416Set11nMac2040(struct ath_hal *ah, HAL_HT_MACMODE mode)
342 {
343     uint32_t macmode;
344 
345     /* Configure MAC for 20/40 operation */
346     if (mode == HAL_HT_MACMODE_2040) {
347         macmode = AR_2040_JOINED_RX_CLEAR;
348     } else {
349         macmode = 0;
350     }
351     OS_REG_WRITE(ah, AR_2040_MODE, macmode);
352 }
353 
354 /*
355  * Get Rx clear (control/extension channel)
356  *
357  * Returns active low (busy) for ctrl/ext channel
358  * Owl 2.0
359  */
360 HAL_HT_RXCLEAR
361 ar5416Get11nRxClear(struct ath_hal *ah)
362 {
363     HAL_HT_RXCLEAR rxclear = 0;
364     uint32_t val;
365 
366     val = OS_REG_READ(ah, AR_DIAG_SW);
367 
368     /* control channel */
369     if (val & AR_DIAG_RXCLEAR_CTL_LOW) {
370         rxclear |= HAL_RX_CLEAR_CTL_LOW;
371     }
372     /* extension channel */
373     if (val & AR_DIAG_RXCLEAR_EXT_LOW) {
374         rxclear |= HAL_RX_CLEAR_EXT_LOW;
375     }
376     return rxclear;
377 }
378 
379 /*
380  * Set Rx clear (control/extension channel)
381  *
382  * Useful for forcing the channel to appear busy for
383  * debugging/diagnostics
384  * Owl 2.0
385  */
386 void
387 ar5416Set11nRxClear(struct ath_hal *ah, HAL_HT_RXCLEAR rxclear)
388 {
389     /* control channel */
390     if (rxclear & HAL_RX_CLEAR_CTL_LOW) {
391         OS_REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RXCLEAR_CTL_LOW);
392     } else {
393         OS_REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_RXCLEAR_CTL_LOW);
394     }
395     /* extension channel */
396     if (rxclear & HAL_RX_CLEAR_EXT_LOW) {
397         OS_REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RXCLEAR_EXT_LOW);
398     } else {
399         OS_REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_RXCLEAR_EXT_LOW);
400     }
401 }
402 
403 /* XXX shouldn't be here! */
404 #define	TU_TO_USEC(_tu)		((_tu) << 10)
405 
406 HAL_STATUS
407 ar5416SetQuiet(struct ath_hal *ah, uint32_t period, uint32_t duration,
408     uint32_t nextStart, HAL_QUIET_FLAG flag)
409 {
410 	uint32_t period_us = TU_TO_USEC(period); /* convert to us unit */
411 	uint32_t nextStart_us = TU_TO_USEC(nextStart); /* convert to us unit */
412 	if (flag & HAL_QUIET_ENABLE) {
413 		if ((!nextStart) || (flag & HAL_QUIET_ADD_CURRENT_TSF)) {
414 			/* Add the nextStart offset to the current TSF */
415 			nextStart_us += OS_REG_READ(ah, AR_TSF_L32);
416 		}
417 		if (flag & HAL_QUIET_ADD_SWBA_RESP_TIME) {
418 			nextStart_us += ah->ah_config.ah_sw_beacon_response_time;
419 		}
420 		OS_REG_RMW_FIELD(ah, AR_QUIET1, AR_QUIET1_QUIET_ACK_CTS_ENABLE, 1);
421 		OS_REG_WRITE(ah, AR_QUIET2, SM(duration, AR_QUIET2_QUIET_DUR));
422 		OS_REG_WRITE(ah, AR_QUIET_PERIOD, period_us);
423 		OS_REG_WRITE(ah, AR_NEXT_QUIET, nextStart_us);
424 		OS_REG_SET_BIT(ah, AR_TIMER_MODE, AR_TIMER_MODE_QUIET);
425 	} else {
426 		OS_REG_CLR_BIT(ah, AR_TIMER_MODE, AR_TIMER_MODE_QUIET);
427 	}
428 	return HAL_OK;
429 }
430 #undef	TU_TO_USEC
431 
432 HAL_STATUS
433 ar5416GetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
434         uint32_t capability, uint32_t *result)
435 {
436 	switch (type) {
437 	case HAL_CAP_BB_HANG:
438 		switch (capability) {
439 		case HAL_BB_HANG_RIFS:
440 			return (AR_SREV_HOWL(ah) || AR_SREV_SOWL(ah)) ? HAL_OK : HAL_ENOTSUPP;
441 		case HAL_BB_HANG_DFS:
442 			return (AR_SREV_HOWL(ah) || AR_SREV_SOWL(ah)) ? HAL_OK : HAL_ENOTSUPP;
443 		case HAL_BB_HANG_RX_CLEAR:
444 			return AR_SREV_MERLIN(ah) ? HAL_OK : HAL_ENOTSUPP;
445 		}
446 		break;
447 	case HAL_CAP_MAC_HANG:
448 		return ((ah->ah_macVersion == AR_XSREV_VERSION_OWL_PCI) ||
449 		    (ah->ah_macVersion == AR_XSREV_VERSION_OWL_PCIE) ||
450 		    AR_SREV_HOWL(ah) || AR_SREV_SOWL(ah)) ?
451 			HAL_OK : HAL_ENOTSUPP;
452 	case HAL_CAP_DIVERSITY:		/* disable classic fast diversity */
453 		return HAL_ENXIO;
454 	case HAL_CAP_ENFORCE_TXOP:
455 		(*result) =
456 		    !! (AH5212(ah)->ah_miscMode & AR_PCU_TXOP_TBTT_LIMIT_ENA);
457 		return (HAL_OK);
458 	default:
459 		break;
460 	}
461 	return ar5212GetCapability(ah, type, capability, result);
462 }
463 
464 HAL_BOOL
465 ar5416SetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
466     u_int32_t capability, u_int32_t setting, HAL_STATUS *status)
467 {
468 	HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps;
469 
470 	switch (type) {
471 	case HAL_CAP_RX_CHAINMASK:
472 		setting &= ath_hal_eepromGet(ah, AR_EEP_RXMASK, NULL);
473 		pCap->halRxChainMask = setting;
474 		if (owl_get_ntxchains(setting) > 2)
475 			pCap->halRxStreams = 2;
476 		else
477 			pCap->halRxStreams = 1;
478 		return AH_TRUE;
479 	case HAL_CAP_TX_CHAINMASK:
480 		setting &= ath_hal_eepromGet(ah, AR_EEP_TXMASK, NULL);
481 		pCap->halTxChainMask = setting;
482 		if (owl_get_ntxchains(setting) > 2)
483 			pCap->halTxStreams = 2;
484 		else
485 			pCap->halTxStreams = 1;
486 		return AH_TRUE;
487 	case HAL_CAP_ENFORCE_TXOP:
488 		if (setting) {
489 			AH5212(ah)->ah_miscMode
490 			    |= AR_PCU_TXOP_TBTT_LIMIT_ENA;
491 			OS_REG_SET_BIT(ah, AR_MISC_MODE,
492 			    AR_PCU_TXOP_TBTT_LIMIT_ENA);
493 		} else {
494 			AH5212(ah)->ah_miscMode
495 			    &= ~AR_PCU_TXOP_TBTT_LIMIT_ENA;
496 			OS_REG_CLR_BIT(ah, AR_MISC_MODE,
497 			    AR_PCU_TXOP_TBTT_LIMIT_ENA);
498 		}
499 		return AH_TRUE;
500 	default:
501 		break;
502 	}
503 	return ar5212SetCapability(ah, type, capability, setting, status);
504 }
505 
506 static int ar5416DetectMacHang(struct ath_hal *ah);
507 static int ar5416DetectBBHang(struct ath_hal *ah);
508 
509 HAL_BOOL
510 ar5416GetDiagState(struct ath_hal *ah, int request,
511 	const void *args, uint32_t argsize,
512 	void **result, uint32_t *resultsize)
513 {
514 	struct ath_hal_5416 *ahp = AH5416(ah);
515 	int hangs;
516 
517 	if (ath_hal_getdiagstate(ah, request, args, argsize, result, resultsize))
518 		return AH_TRUE;
519 	switch (request) {
520 	case HAL_DIAG_EEPROM:
521 		return ath_hal_eepromDiag(ah, request,
522 		    args, argsize, result, resultsize);
523 	case HAL_DIAG_CHECK_HANGS:
524 		if (argsize != sizeof(int))
525 			return AH_FALSE;
526 		hangs = *(const int *) args;
527 		ahp->ah_hangs = 0;
528 		if (hangs & HAL_BB_HANGS)
529 			ahp->ah_hangs |= ar5416DetectBBHang(ah);
530 		/* NB: if BB is hung MAC will be hung too so skip check */
531 		if (ahp->ah_hangs == 0 && (hangs & HAL_MAC_HANGS))
532 			ahp->ah_hangs |= ar5416DetectMacHang(ah);
533 		*result = &ahp->ah_hangs;
534 		*resultsize = sizeof(ahp->ah_hangs);
535 		return AH_TRUE;
536 	}
537 	return ar5212GetDiagState(ah, request,
538 	    args, argsize, result, resultsize);
539 }
540 
541 HAL_BOOL
542 ar5416SetRifsDelay(struct ath_hal *ah, const struct ieee80211_channel *chan,
543     HAL_BOOL enable)
544 {
545 	uint32_t val;
546 	HAL_BOOL is_chan_2g = AH_FALSE;
547 	HAL_BOOL is_ht40 = AH_FALSE;
548 
549 	if (chan)
550 		is_chan_2g = IEEE80211_IS_CHAN_2GHZ(chan);
551 
552 	if (chan)
553 		is_ht40 = IEEE80211_IS_CHAN_HT40(chan);
554 
555 	/* Only support disabling RIFS delay for now */
556 	HALASSERT(enable == AH_FALSE);
557 
558 	if (enable == AH_TRUE)
559 		return AH_FALSE;
560 
561 	/* Change RIFS init delay to 0 */
562 	val = OS_REG_READ(ah, AR_PHY_HEAVY_CLIP_FACTOR_RIFS);
563 	val &= ~AR_PHY_RIFS_INIT_DELAY;
564 	OS_REG_WRITE(ah, AR_PHY_HEAVY_CLIP_FACTOR_RIFS, val);
565 
566 	/*
567 	 * For Owl, RIFS RX parameters are controlled differently;
568 	 * it isn't enabled in the inivals by default.
569 	 *
570 	 * For Sowl/Howl, RIFS RX is enabled in the inivals by default;
571 	 * the following code sets them back to non-RIFS values.
572 	 *
573 	 * For > Sowl/Howl, RIFS RX can be left on by default and so
574 	 * this function shouldn't be called.
575 	 */
576 	if ((! AR_SREV_SOWL(ah)) && (! AR_SREV_HOWL(ah)))
577 		return AH_TRUE;
578 
579 	/* Reset search delay to default values */
580 	if (is_chan_2g)
581 		if (is_ht40)
582 			OS_REG_WRITE(ah, AR_PHY_SEARCH_START_DELAY, 0x268);
583 		else
584 			OS_REG_WRITE(ah, AR_PHY_SEARCH_START_DELAY, 0x134);
585 	else
586 		if (is_ht40)
587 			OS_REG_WRITE(ah, AR_PHY_SEARCH_START_DELAY, 0x370);
588 		else
589 			OS_REG_WRITE(ah, AR_PHY_SEARCH_START_DELAY, 0x1b8);
590 
591 	return AH_TRUE;
592 }
593 
594 static HAL_BOOL
595 ar5416CompareDbgHang(struct ath_hal *ah, const mac_dbg_regs_t *regs,
596     const hal_mac_hang_check_t *check)
597 {
598 	int found_states;
599 
600 	found_states = 0;
601 	if (check->states & dcu_chain_state) {
602 		int i;
603 
604 		for (i = 0; i < 6; i++) {
605 			if (((regs->dma_dbg_4 >> (5*i)) & 0x1f) ==
606 			    check->dcu_chain_state)
607 				found_states |= dcu_chain_state;
608 		}
609 		for (i = 0; i < 4; i++) {
610 			if (((regs->dma_dbg_5 >> (5*i)) & 0x1f) ==
611 			    check->dcu_chain_state)
612 				found_states |= dcu_chain_state;
613 		}
614 	}
615 	if (check->states & dcu_complete_state) {
616 		if ((regs->dma_dbg_6 & 0x3) == check->dcu_complete_state)
617 			found_states |= dcu_complete_state;
618 	}
619 	if (check->states & qcu_stitch_state) {
620 		if (((regs->dma_dbg_3 >> 18) & 0xf) == check->qcu_stitch_state)
621 			found_states |= qcu_stitch_state;
622 	}
623 	if (check->states & qcu_fetch_state) {
624 		if (((regs->dma_dbg_3 >> 22) & 0xf) == check->qcu_fetch_state)
625 			found_states |= qcu_fetch_state;
626 	}
627 	if (check->states & qcu_complete_state) {
628 		if (((regs->dma_dbg_3 >> 26) & 0x7) == check->qcu_complete_state)
629 			found_states |= qcu_complete_state;
630 	}
631 	return (found_states == check->states);
632 }
633 
634 #define NUM_STATUS_READS 50
635 
636 static int
637 ar5416DetectMacHang(struct ath_hal *ah)
638 {
639 	static const hal_mac_hang_check_t hang_sig1 = {
640 		.dcu_chain_state	= 0x6,
641 		.dcu_complete_state	= 0x1,
642 		.states			= dcu_chain_state
643 					| dcu_complete_state,
644 	};
645 	static const hal_mac_hang_check_t hang_sig2 = {
646 		.qcu_stitch_state	= 0x9,
647 		.qcu_fetch_state	= 0x8,
648 		.qcu_complete_state	= 0x4,
649 		.states			= qcu_stitch_state
650 					| qcu_fetch_state
651 					| qcu_complete_state,
652         };
653 	mac_dbg_regs_t mac_dbg;
654 	int i;
655 
656 	mac_dbg.dma_dbg_3 = OS_REG_READ(ah, AR_DMADBG_3);
657 	mac_dbg.dma_dbg_4 = OS_REG_READ(ah, AR_DMADBG_4);
658 	mac_dbg.dma_dbg_5 = OS_REG_READ(ah, AR_DMADBG_5);
659 	mac_dbg.dma_dbg_6 = OS_REG_READ(ah, AR_DMADBG_6);
660 	for (i = 1; i <= NUM_STATUS_READS; i++) {
661 		if (mac_dbg.dma_dbg_3 != OS_REG_READ(ah, AR_DMADBG_3) ||
662 		    mac_dbg.dma_dbg_4 != OS_REG_READ(ah, AR_DMADBG_4) ||
663 		    mac_dbg.dma_dbg_5 != OS_REG_READ(ah, AR_DMADBG_5) ||
664 		    mac_dbg.dma_dbg_6 != OS_REG_READ(ah, AR_DMADBG_6))
665 			return 0;
666 	}
667 
668 	if (ar5416CompareDbgHang(ah, &mac_dbg, &hang_sig1))
669 		return HAL_MAC_HANG_SIG1;
670 	if (ar5416CompareDbgHang(ah, &mac_dbg, &hang_sig2))
671 		return HAL_MAC_HANG_SIG2;
672 
673 	HALDEBUG(ah, HAL_DEBUG_HANG, "%s Found an unknown MAC hang signature "
674 	    "DMADBG_3=0x%x DMADBG_4=0x%x DMADBG_5=0x%x DMADBG_6=0x%x\n",
675 	    __func__, mac_dbg.dma_dbg_3, mac_dbg.dma_dbg_4, mac_dbg.dma_dbg_5,
676 	    mac_dbg.dma_dbg_6);
677 
678 	return 0;
679 }
680 
681 /*
682  * Determine if the baseband using the Observation Bus Register
683  */
684 static int
685 ar5416DetectBBHang(struct ath_hal *ah)
686 {
687 #define N(a) (sizeof(a)/sizeof(a[0]))
688 	/*
689 	 * Check the PCU Observation Bus 1 register (0x806c)
690 	 * NUM_STATUS_READS times
691 	 *
692 	 * 4 known BB hang signatures -
693 	 * [1] bits 8,9,11 are 0. State machine state (bits 25-31) is 0x1E
694 	 * [2] bits 8,9 are 1, bit 11 is 0. State machine state
695 	 *     (bits 25-31) is 0x52
696 	 * [3] bits 8,9 are 1, bit 11 is 0. State machine state
697 	 *     (bits 25-31) is 0x18
698 	 * [4] bit 10 is 1, bit 11 is 0. WEP state (bits 12-17) is 0x2,
699 	 *     Rx State (bits 20-24) is 0x7.
700 	 */
701 	static const struct {
702 		uint32_t val;
703 		uint32_t mask;
704 		int code;
705 	} hang_list[] = {
706 		/* Reg Value   Reg Mask    Hang Code XXX */
707 		{ 0x1E000000, 0x7E000B00, HAL_BB_HANG_DFS },
708 		{ 0x52000B00, 0x7E000B00, HAL_BB_HANG_RIFS },
709 		{ 0x18000B00, 0x7E000B00, HAL_BB_HANG_RX_CLEAR },
710 		{ 0x00702400, 0x7E7FFFEF, HAL_BB_HANG_RX_CLEAR }
711 	};
712 	uint32_t hang_sig;
713 	int i;
714 
715 	hang_sig = OS_REG_READ(ah, AR_OBSERV_1);
716 	for (i = 1; i <= NUM_STATUS_READS; i++) {
717 		if (hang_sig != OS_REG_READ(ah, AR_OBSERV_1))
718 			return 0;
719 	}
720 	for (i = 0; i < N(hang_list); i++)
721 		if ((hang_sig & hang_list[i].mask) == hang_list[i].val) {
722 			HALDEBUG(ah, HAL_DEBUG_HANG,
723 			    "%s BB hang, signature 0x%x, code 0x%x\n",
724 			    __func__, hang_sig, hang_list[i].code);
725 			return hang_list[i].code;
726 		}
727 
728 	HALDEBUG(ah, HAL_DEBUG_HANG, "%s Found an unknown BB hang signature! "
729 	    "<0x806c>=0x%x\n", __func__, hang_sig);
730 
731 	return 0;
732 #undef N
733 }
734 #undef NUM_STATUS_READS
735