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: stable/9/sys/dev/ath/ath_hal/ar5416/ar5416_misc.c 229740 2012-01-06 22:18:13Z dim $
18  */
19 #include "opt_ah.h"
20 
21 #include "ah.h"
22 #include "ah_internal.h"
23 #include "ah_devid.h"
24 #ifdef AH_DEBUG
25 #include "ah_desc.h"                    /* NB: for HAL_PHYERR* */
26 #endif
27 
28 #include "ar5416/ar5416.h"
29 #include "ar5416/ar5416reg.h"
30 #include "ar5416/ar5416phy.h"
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
ar5416GetWirelessModes(struct ath_hal * ah)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
ar5416SetLedState(struct ath_hal * ah,HAL_LED_STATE state)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 	uint32_t bits;
79 
80 	if (AR_SREV_HOWL(ah))
81 		return;
82 
83 	bits = OS_REG_READ(ah, AR_MAC_LED);
84 	bits = (bits &~ AR_MAC_LED_MODE)
85 	     | SM(AR_MAC_LED_MODE_POWON, AR_MAC_LED_MODE)
86 #if 1
87 	     | SM(AR_MAC_LED_MODE_NETON, AR_MAC_LED_MODE)
88 #endif
89 	     ;
90 	bits = (bits &~ AR_MAC_LED_ASSOC)
91 	     | SM(ledbits[state & 0x7], AR_MAC_LED_ASSOC);
92 	OS_REG_WRITE(ah, AR_MAC_LED, bits);
93 }
94 
95 /*
96  * Get the current hardware tsf for stamlme
97  */
98 uint64_t
ar5416GetTsf64(struct ath_hal * ah)99 ar5416GetTsf64(struct ath_hal *ah)
100 {
101 	uint32_t low1, low2, u32;
102 
103 	/* sync multi-word read */
104 	low1 = OS_REG_READ(ah, AR_TSF_L32);
105 	u32 = OS_REG_READ(ah, AR_TSF_U32);
106 	low2 = OS_REG_READ(ah, AR_TSF_L32);
107 	if (low2 < low1) {	/* roll over */
108 		/*
109 		 * If we are not preempted this will work.  If we are
110 		 * then we re-reading AR_TSF_U32 does no good as the
111 		 * low bits will be meaningless.  Likewise reading
112 		 * L32, U32, U32, then comparing the last two reads
113 		 * to check for rollover doesn't help if preempted--so
114 		 * we take this approach as it costs one less PCI read
115 		 * which can be noticeable when doing things like
116 		 * timestamping packets in monitor mode.
117 		 */
118 		u32++;
119 	}
120 	return (((uint64_t) u32) << 32) | ((uint64_t) low2);
121 }
122 
123 void
ar5416SetTsf64(struct ath_hal * ah,uint64_t tsf64)124 ar5416SetTsf64(struct ath_hal *ah, uint64_t tsf64)
125 {
126 	OS_REG_WRITE(ah, AR_TSF_L32, tsf64 & 0xffffffff);
127 	OS_REG_WRITE(ah, AR_TSF_U32, (tsf64 >> 32) & 0xffffffff);
128 }
129 
130 /*
131  * Reset the current hardware tsf for stamlme.
132  */
133 void
ar5416ResetTsf(struct ath_hal * ah)134 ar5416ResetTsf(struct ath_hal *ah)
135 {
136 	uint32_t v;
137 	int i;
138 
139 	for (i = 0; i < 10; i++) {
140 		v = OS_REG_READ(ah, AR_SLP32_MODE);
141 		if ((v & AR_SLP32_TSF_WRITE_STATUS) == 0)
142 			break;
143 		OS_DELAY(10);
144 	}
145 	OS_REG_WRITE(ah, AR_RESET_TSF, AR_RESET_TSF_ONCE);
146 }
147 
148 HAL_BOOL
ar5416SetAntennaSwitch(struct ath_hal * ah,HAL_ANT_SETTING settings)149 ar5416SetAntennaSwitch(struct ath_hal *ah, HAL_ANT_SETTING settings)
150 {
151 	return AH_TRUE;
152 }
153 
154 /* Setup decompression for given key index */
155 HAL_BOOL
ar5416SetDecompMask(struct ath_hal * ah,uint16_t keyidx,int en)156 ar5416SetDecompMask(struct ath_hal *ah, uint16_t keyidx, int en)
157 {
158 	return AH_TRUE;
159 }
160 
161 /* Setup coverage class */
162 void
ar5416SetCoverageClass(struct ath_hal * ah,uint8_t coverageclass,int now)163 ar5416SetCoverageClass(struct ath_hal *ah, uint8_t coverageclass, int now)
164 {
165 	AH_PRIVATE(ah)->ah_coverageClass = coverageclass;
166 }
167 
168 /*
169  * Return approximation of extension channel busy over an time interval
170  * 0% (clear) -> 100% (busy)
171  *
172  */
173 uint32_t
ar5416Get11nExtBusy(struct ath_hal * ah)174 ar5416Get11nExtBusy(struct ath_hal *ah)
175 {
176     struct ath_hal_5416 *ahp = AH5416(ah);
177     uint32_t busy; /* percentage */
178     uint32_t cycleCount, ctlBusy, extBusy;
179 
180     ctlBusy = OS_REG_READ(ah, AR_RCCNT);
181     extBusy = OS_REG_READ(ah, AR_EXTRCCNT);
182     cycleCount = OS_REG_READ(ah, AR_CCCNT);
183 
184     if (ahp->ah_cycleCount == 0 || ahp->ah_cycleCount > cycleCount) {
185         /*
186          * Cycle counter wrap (or initial call); it's not possible
187          * to accurately calculate a value because the registers
188          * right shift rather than wrap--so punt and return 0.
189          */
190         busy = 0;
191         HALDEBUG(ah, HAL_DEBUG_ANY, "%s: cycle counter wrap. ExtBusy = 0\n",
192 	    __func__);
193 
194     } else {
195         uint32_t cycleDelta = cycleCount - ahp->ah_cycleCount;
196         uint32_t ctlBusyDelta = ctlBusy - ahp->ah_ctlBusy;
197         uint32_t extBusyDelta = extBusy - ahp->ah_extBusy;
198         uint32_t ctlClearDelta = 0;
199 
200         /* Compute control channel rxclear.
201          * The cycle delta may be less than the control channel delta.
202          * This could be solved by freezing the timers (or an atomic read,
203          * if one was available). Checking for the condition should be
204          * sufficient.
205          */
206         if (cycleDelta > ctlBusyDelta) {
207             ctlClearDelta = cycleDelta - ctlBusyDelta;
208         }
209 
210         /* Compute ratio of extension channel busy to control channel clear
211          * as an approximation to extension channel cleanliness.
212          *
213          * According to the hardware folks, ext rxclear is undefined
214          * if the ctrl rxclear is de-asserted (i.e. busy)
215          */
216         if (ctlClearDelta) {
217             busy = (extBusyDelta * 100) / ctlClearDelta;
218         } else {
219             busy = 100;
220         }
221         if (busy > 100) {
222             busy = 100;
223         }
224 #if 0
225         HALDEBUG(ah, HAL_DEBUG_ANY, "%s: cycleDelta 0x%x, ctlBusyDelta 0x%x, "
226              "extBusyDelta 0x%x, ctlClearDelta 0x%x, "
227              "busy %d\n",
228               __func__, cycleDelta, ctlBusyDelta, extBusyDelta, ctlClearDelta, busy);
229 #endif
230     }
231 
232     ahp->ah_cycleCount = cycleCount;
233     ahp->ah_ctlBusy = ctlBusy;
234     ahp->ah_extBusy = extBusy;
235 
236     return busy;
237 }
238 
239 /*
240  * Configure 20/40 operation
241  *
242  * 20/40 = joint rx clear (control and extension)
243  * 20    = rx clear (control)
244  *
245  * - NOTE: must stop MAC (tx) and requeue 40 MHz packets as 20 MHz when changing
246  *         from 20/40 => 20 only
247  */
248 void
ar5416Set11nMac2040(struct ath_hal * ah,HAL_HT_MACMODE mode)249 ar5416Set11nMac2040(struct ath_hal *ah, HAL_HT_MACMODE mode)
250 {
251     uint32_t macmode;
252 
253     /* Configure MAC for 20/40 operation */
254     if (mode == HAL_HT_MACMODE_2040) {
255         macmode = AR_2040_JOINED_RX_CLEAR;
256     } else {
257         macmode = 0;
258     }
259     OS_REG_WRITE(ah, AR_2040_MODE, macmode);
260 }
261 
262 /*
263  * Get Rx clear (control/extension channel)
264  *
265  * Returns active low (busy) for ctrl/ext channel
266  * Owl 2.0
267  */
268 HAL_HT_RXCLEAR
ar5416Get11nRxClear(struct ath_hal * ah)269 ar5416Get11nRxClear(struct ath_hal *ah)
270 {
271     HAL_HT_RXCLEAR rxclear = 0;
272     uint32_t val;
273 
274     val = OS_REG_READ(ah, AR_DIAG_SW);
275 
276     /* control channel */
277     if (val & AR_DIAG_RXCLEAR_CTL_LOW) {
278         rxclear |= HAL_RX_CLEAR_CTL_LOW;
279     }
280     /* extension channel */
281     if (val & AR_DIAG_RXCLEAR_CTL_LOW) {
282         rxclear |= HAL_RX_CLEAR_EXT_LOW;
283     }
284     return rxclear;
285 }
286 
287 /*
288  * Set Rx clear (control/extension channel)
289  *
290  * Useful for forcing the channel to appear busy for
291  * debugging/diagnostics
292  * Owl 2.0
293  */
294 void
ar5416Set11nRxClear(struct ath_hal * ah,HAL_HT_RXCLEAR rxclear)295 ar5416Set11nRxClear(struct ath_hal *ah, HAL_HT_RXCLEAR rxclear)
296 {
297     /* control channel */
298     if (rxclear & HAL_RX_CLEAR_CTL_LOW) {
299         OS_REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RXCLEAR_CTL_LOW);
300     } else {
301         OS_REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_RXCLEAR_CTL_LOW);
302     }
303     /* extension channel */
304     if (rxclear & HAL_RX_CLEAR_EXT_LOW) {
305         OS_REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RXCLEAR_EXT_LOW);
306     } else {
307         OS_REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_RXCLEAR_EXT_LOW);
308     }
309 }
310 
311 /* XXX shouldn't be here! */
312 #define	TU_TO_USEC(_tu)		((_tu) << 10)
313 
314 HAL_STATUS
ar5416SetQuiet(struct ath_hal * ah,uint32_t period,uint32_t duration,uint32_t nextStart,HAL_QUIET_FLAG flag)315 ar5416SetQuiet(struct ath_hal *ah, uint32_t period, uint32_t duration,
316     uint32_t nextStart, HAL_QUIET_FLAG flag)
317 {
318 	uint32_t period_us = TU_TO_USEC(period); /* convert to us unit */
319 	uint32_t nextStart_us = TU_TO_USEC(nextStart); /* convert to us unit */
320 	if (flag & HAL_QUIET_ENABLE) {
321 		if ((!nextStart) || (flag & HAL_QUIET_ADD_CURRENT_TSF)) {
322 			/* Add the nextStart offset to the current TSF */
323 			nextStart_us += OS_REG_READ(ah, AR_TSF_L32);
324 		}
325 		if (flag & HAL_QUIET_ADD_SWBA_RESP_TIME) {
326 			nextStart_us += ah->ah_config.ah_sw_beacon_response_time;
327 		}
328 		OS_REG_RMW_FIELD(ah, AR_QUIET1, AR_QUIET1_QUIET_ACK_CTS_ENABLE, 1);
329 		OS_REG_WRITE(ah, AR_QUIET2, SM(duration, AR_QUIET2_QUIET_DUR));
330 		OS_REG_WRITE(ah, AR_QUIET_PERIOD, period_us);
331 		OS_REG_WRITE(ah, AR_NEXT_QUIET, nextStart_us);
332 		OS_REG_SET_BIT(ah, AR_TIMER_MODE, AR_TIMER_MODE_QUIET);
333 	} else {
334 		OS_REG_CLR_BIT(ah, AR_TIMER_MODE, AR_TIMER_MODE_QUIET);
335 	}
336 	return HAL_OK;
337 }
338 #undef	TU_TO_USEC
339 
340 HAL_STATUS
ar5416GetCapability(struct ath_hal * ah,HAL_CAPABILITY_TYPE type,uint32_t capability,uint32_t * result)341 ar5416GetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
342         uint32_t capability, uint32_t *result)
343 {
344 	switch (type) {
345 	case HAL_CAP_BB_HANG:
346 		switch (capability) {
347 		case HAL_BB_HANG_RIFS:
348 			return (AR_SREV_HOWL(ah) || AR_SREV_SOWL(ah)) ? HAL_OK : HAL_ENOTSUPP;
349 		case HAL_BB_HANG_DFS:
350 			return (AR_SREV_HOWL(ah) || AR_SREV_SOWL(ah)) ? HAL_OK : HAL_ENOTSUPP;
351 		case HAL_BB_HANG_RX_CLEAR:
352 			return AR_SREV_MERLIN(ah) ? HAL_OK : HAL_ENOTSUPP;
353 		}
354 		break;
355 	case HAL_CAP_MAC_HANG:
356 		return ((ah->ah_macVersion == AR_XSREV_VERSION_OWL_PCI) ||
357 		    (ah->ah_macVersion == AR_XSREV_VERSION_OWL_PCIE) ||
358 		    AR_SREV_HOWL(ah) || AR_SREV_SOWL(ah)) ?
359 			HAL_OK : HAL_ENOTSUPP;
360 	case HAL_CAP_DIVERSITY:		/* disable classic fast diversity */
361 		return HAL_ENXIO;
362 	default:
363 		break;
364 	}
365 	return ar5212GetCapability(ah, type, capability, result);
366 }
367 
368 static int ar5416DetectMacHang(struct ath_hal *ah);
369 static int ar5416DetectBBHang(struct ath_hal *ah);
370 
371 HAL_BOOL
ar5416GetDiagState(struct ath_hal * ah,int request,const void * args,uint32_t argsize,void ** result,uint32_t * resultsize)372 ar5416GetDiagState(struct ath_hal *ah, int request,
373 	const void *args, uint32_t argsize,
374 	void **result, uint32_t *resultsize)
375 {
376 	struct ath_hal_5416 *ahp = AH5416(ah);
377 	int hangs;
378 
379 	if (ath_hal_getdiagstate(ah, request, args, argsize, result, resultsize))
380 		return AH_TRUE;
381 	switch (request) {
382 	case HAL_DIAG_EEPROM:
383 		return ath_hal_eepromDiag(ah, request,
384 		    args, argsize, result, resultsize);
385 	case HAL_DIAG_CHECK_HANGS:
386 		if (argsize != sizeof(int))
387 			return AH_FALSE;
388 		hangs = *(const int *) args;
389 		ahp->ah_hangs = 0;
390 		if (hangs & HAL_BB_HANGS)
391 			ahp->ah_hangs |= ar5416DetectBBHang(ah);
392 		/* NB: if BB is hung MAC will be hung too so skip check */
393 		if (ahp->ah_hangs == 0 && (hangs & HAL_MAC_HANGS))
394 			ahp->ah_hangs |= ar5416DetectMacHang(ah);
395 		*result = &ahp->ah_hangs;
396 		*resultsize = sizeof(ahp->ah_hangs);
397 		return AH_TRUE;
398 	}
399 	return ar5212GetDiagState(ah, request,
400 	    args, argsize, result, resultsize);
401 }
402 
403 typedef struct {
404 	uint32_t dma_dbg_3;
405 	uint32_t dma_dbg_4;
406 	uint32_t dma_dbg_5;
407 	uint32_t dma_dbg_6;
408 } mac_dbg_regs_t;
409 
410 typedef enum {
411 	dcu_chain_state		= 0x1,
412 	dcu_complete_state	= 0x2,
413 	qcu_state		= 0x4,
414 	qcu_fsp_ok		= 0x8,
415 	qcu_fsp_state		= 0x10,
416 	qcu_stitch_state	= 0x20,
417 	qcu_fetch_state		= 0x40,
418 	qcu_complete_state	= 0x80
419 } hal_mac_hangs_t;
420 
421 typedef struct {
422 	int states;
423 	uint8_t dcu_chain_state;
424 	uint8_t dcu_complete_state;
425 	uint8_t qcu_state;
426 	uint8_t qcu_fsp_ok;
427 	uint8_t qcu_fsp_state;
428 	uint8_t qcu_stitch_state;
429 	uint8_t qcu_fetch_state;
430 	uint8_t qcu_complete_state;
431 } hal_mac_hang_check_t;
432 
433 HAL_BOOL
ar5416SetRifsDelay(struct ath_hal * ah,const struct ieee80211_channel * chan,HAL_BOOL enable)434 ar5416SetRifsDelay(struct ath_hal *ah, const struct ieee80211_channel *chan,
435     HAL_BOOL enable)
436 {
437 	uint32_t val;
438 	HAL_BOOL is_chan_2g = AH_FALSE;
439 	HAL_BOOL is_ht40 = AH_FALSE;
440 
441 	if (chan)
442 		is_chan_2g = IEEE80211_IS_CHAN_2GHZ(chan);
443 
444 	if (chan)
445 		is_ht40 = IEEE80211_IS_CHAN_HT40(chan);
446 
447 	/* Only support disabling RIFS delay for now */
448 	HALASSERT(enable == AH_FALSE);
449 
450 	if (enable == AH_TRUE)
451 		return AH_FALSE;
452 
453 	/* Change RIFS init delay to 0 */
454 	val = OS_REG_READ(ah, AR_PHY_HEAVY_CLIP_FACTOR_RIFS);
455 	val &= ~AR_PHY_RIFS_INIT_DELAY;
456 	OS_REG_WRITE(ah, AR_PHY_HEAVY_CLIP_FACTOR_RIFS, val);
457 
458 	/*
459 	 * For Owl, RIFS RX parameters are controlled differently;
460 	 * it isn't enabled in the inivals by default.
461 	 *
462 	 * For Sowl/Howl, RIFS RX is enabled in the inivals by default;
463 	 * the following code sets them back to non-RIFS values.
464 	 *
465 	 * For > Sowl/Howl, RIFS RX can be left on by default and so
466 	 * this function shouldn't be called.
467 	 */
468 	if ((! AR_SREV_SOWL(ah)) && (! AR_SREV_HOWL(ah)))
469 		return AH_TRUE;
470 
471 	/* Reset search delay to default values */
472 	if (is_chan_2g)
473 		if (is_ht40)
474 			OS_REG_WRITE(ah, AR_PHY_SEARCH_START_DELAY, 0x268);
475 		else
476 			OS_REG_WRITE(ah, AR_PHY_SEARCH_START_DELAY, 0x134);
477 	else
478 		if (is_ht40)
479 			OS_REG_WRITE(ah, AR_PHY_SEARCH_START_DELAY, 0x370);
480 		else
481 			OS_REG_WRITE(ah, AR_PHY_SEARCH_START_DELAY, 0x1b8);
482 
483 	return AH_TRUE;
484 }
485 
486 static HAL_BOOL
ar5416CompareDbgHang(struct ath_hal * ah,const mac_dbg_regs_t * regs,const hal_mac_hang_check_t * check)487 ar5416CompareDbgHang(struct ath_hal *ah, const mac_dbg_regs_t *regs,
488     const hal_mac_hang_check_t *check)
489 {
490 	int found_states;
491 
492 	found_states = 0;
493 	if (check->states & dcu_chain_state) {
494 		int i;
495 
496 		for (i = 0; i < 6; i++) {
497 			if (((regs->dma_dbg_4 >> (5*i)) & 0x1f) ==
498 			    check->dcu_chain_state)
499 				found_states |= dcu_chain_state;
500 		}
501 		for (i = 0; i < 4; i++) {
502 			if (((regs->dma_dbg_5 >> (5*i)) & 0x1f) ==
503 			    check->dcu_chain_state)
504 				found_states |= dcu_chain_state;
505 		}
506 	}
507 	if (check->states & dcu_complete_state) {
508 		if ((regs->dma_dbg_6 & 0x3) == check->dcu_complete_state)
509 			found_states |= dcu_complete_state;
510 	}
511 	if (check->states & qcu_stitch_state) {
512 		if (((regs->dma_dbg_3 >> 18) & 0xf) == check->qcu_stitch_state)
513 			found_states |= qcu_stitch_state;
514 	}
515 	if (check->states & qcu_fetch_state) {
516 		if (((regs->dma_dbg_3 >> 22) & 0xf) == check->qcu_fetch_state)
517 			found_states |= qcu_fetch_state;
518 	}
519 	if (check->states & qcu_complete_state) {
520 		if (((regs->dma_dbg_3 >> 26) & 0x7) == check->qcu_complete_state)
521 			found_states |= qcu_complete_state;
522 	}
523 	return (found_states == check->states);
524 }
525 
526 #define NUM_STATUS_READS 50
527 
528 static int
ar5416DetectMacHang(struct ath_hal * ah)529 ar5416DetectMacHang(struct ath_hal *ah)
530 {
531 	static const hal_mac_hang_check_t hang_sig1 = {
532 		.dcu_chain_state	= 0x6,
533 		.dcu_complete_state	= 0x1,
534 		.states			= dcu_chain_state
535 					| dcu_complete_state,
536 	};
537 	static const hal_mac_hang_check_t hang_sig2 = {
538 		.qcu_stitch_state	= 0x9,
539 		.qcu_fetch_state	= 0x8,
540 		.qcu_complete_state	= 0x4,
541 		.states			= qcu_stitch_state
542 					| qcu_fetch_state
543 					| qcu_complete_state,
544         };
545 	mac_dbg_regs_t mac_dbg;
546 	int i;
547 
548 	mac_dbg.dma_dbg_3 = OS_REG_READ(ah, AR_DMADBG_3);
549 	mac_dbg.dma_dbg_4 = OS_REG_READ(ah, AR_DMADBG_4);
550 	mac_dbg.dma_dbg_5 = OS_REG_READ(ah, AR_DMADBG_5);
551 	mac_dbg.dma_dbg_6 = OS_REG_READ(ah, AR_DMADBG_6);
552 	for (i = 1; i <= NUM_STATUS_READS; i++) {
553 		if (mac_dbg.dma_dbg_3 != OS_REG_READ(ah, AR_DMADBG_3) ||
554 		    mac_dbg.dma_dbg_4 != OS_REG_READ(ah, AR_DMADBG_4) ||
555 		    mac_dbg.dma_dbg_5 != OS_REG_READ(ah, AR_DMADBG_5) ||
556 		    mac_dbg.dma_dbg_6 != OS_REG_READ(ah, AR_DMADBG_6))
557 			return 0;
558 	}
559 
560 	if (ar5416CompareDbgHang(ah, &mac_dbg, &hang_sig1))
561 		return HAL_MAC_HANG_SIG1;
562 	if (ar5416CompareDbgHang(ah, &mac_dbg, &hang_sig2))
563 		return HAL_MAC_HANG_SIG2;
564 
565 	HALDEBUG(ah, HAL_DEBUG_HANG, "%s Found an unknown MAC hang signature "
566 	    "DMADBG_3=0x%x DMADBG_4=0x%x DMADBG_5=0x%x DMADBG_6=0x%x\n",
567 	    __func__, mac_dbg.dma_dbg_3, mac_dbg.dma_dbg_4, mac_dbg.dma_dbg_5,
568 	    mac_dbg.dma_dbg_6);
569 
570 	return 0;
571 }
572 
573 /*
574  * Determine if the baseband using the Observation Bus Register
575  */
576 static int
ar5416DetectBBHang(struct ath_hal * ah)577 ar5416DetectBBHang(struct ath_hal *ah)
578 {
579 #define N(a) (sizeof(a)/sizeof(a[0]))
580 	/*
581 	 * Check the PCU Observation Bus 1 register (0x806c)
582 	 * NUM_STATUS_READS times
583 	 *
584 	 * 4 known BB hang signatures -
585 	 * [1] bits 8,9,11 are 0. State machine state (bits 25-31) is 0x1E
586 	 * [2] bits 8,9 are 1, bit 11 is 0. State machine state
587 	 *     (bits 25-31) is 0x52
588 	 * [3] bits 8,9 are 1, bit 11 is 0. State machine state
589 	 *     (bits 25-31) is 0x18
590 	 * [4] bit 10 is 1, bit 11 is 0. WEP state (bits 12-17) is 0x2,
591 	 *     Rx State (bits 20-24) is 0x7.
592 	 */
593 	static const struct {
594 		uint32_t val;
595 		uint32_t mask;
596 		int code;
597 	} hang_list[] = {
598 		/* Reg Value   Reg Mask    Hang Code XXX */
599 		{ 0x1E000000, 0x7E000B00, HAL_BB_HANG_DFS },
600 		{ 0x52000B00, 0x7E000B00, HAL_BB_HANG_RIFS },
601 		{ 0x18000B00, 0x7E000B00, HAL_BB_HANG_RX_CLEAR },
602 		{ 0x00702400, 0x7E7FFFEF, HAL_BB_HANG_RX_CLEAR }
603 	};
604 	uint32_t hang_sig;
605 	int i;
606 
607 	hang_sig = OS_REG_READ(ah, AR_OBSERV_1);
608 	for (i = 1; i <= NUM_STATUS_READS; i++) {
609 		if (hang_sig != OS_REG_READ(ah, AR_OBSERV_1))
610 			return 0;
611 	}
612 	for (i = 0; i < N(hang_list); i++)
613 		if ((hang_sig & hang_list[i].mask) == hang_list[i].val) {
614 			HALDEBUG(ah, HAL_DEBUG_HANG,
615 			    "%s BB hang, signature 0x%x, code 0x%x\n",
616 			    __func__, hang_sig, hang_list[i].code);
617 			return hang_list[i].code;
618 		}
619 
620 	HALDEBUG(ah, HAL_DEBUG_HANG, "%s Found an unknown BB hang signature! "
621 	    "<0x806c>=0x%x\n", __func__, hang_sig);
622 
623 	return 0;
624 #undef N
625 }
626 #undef NUM_STATUS_READS
627 
628 /*
629  * Get the radar parameter values and return them in the pe
630  * structure
631  */
632 void
ar5416GetDfsThresh(struct ath_hal * ah,HAL_PHYERR_PARAM * pe)633 ar5416GetDfsThresh(struct ath_hal *ah, HAL_PHYERR_PARAM *pe)
634 {
635 	uint32_t val, temp;
636 
637 	val = OS_REG_READ(ah, AR_PHY_RADAR_0);
638 
639 	temp = MS(val,AR_PHY_RADAR_0_FIRPWR);
640 	temp |= 0xFFFFFF80;
641 	pe->pe_firpwr = temp;
642 	pe->pe_rrssi = MS(val, AR_PHY_RADAR_0_RRSSI);
643 	pe->pe_height =  MS(val, AR_PHY_RADAR_0_HEIGHT);
644 	pe->pe_prssi = MS(val, AR_PHY_RADAR_0_PRSSI);
645 	pe->pe_inband = MS(val, AR_PHY_RADAR_0_INBAND);
646 
647 	val = OS_REG_READ(ah, AR_PHY_RADAR_1);
648 	temp = val & AR_PHY_RADAR_1_RELPWR_ENA;
649 	pe->pe_relpwr = MS(val, AR_PHY_RADAR_1_RELPWR_THRESH);
650 	if (temp)
651 		pe->pe_relpwr |= HAL_PHYERR_PARAM_ENABLE;
652 	temp = val & AR_PHY_RADAR_1_RELSTEP_CHECK;
653 	pe->pe_relstep = MS(val, AR_PHY_RADAR_1_RELSTEP_THRESH);
654 	if (temp)
655 		pe->pe_enabled = 1;
656 	else
657 		pe->pe_enabled = 0;
658 
659 	pe->pe_maxlen = MS(val, AR_PHY_RADAR_1_MAXLEN);
660 	pe->pe_extchannel = !! (OS_REG_READ(ah, AR_PHY_RADAR_EXT) &
661 	    AR_PHY_RADAR_EXT_ENA);
662 
663 	pe->pe_usefir128 = !! (OS_REG_READ(ah, AR_PHY_RADAR_1) &
664 	    AR_PHY_RADAR_1_USE_FIR128);
665 	pe->pe_blockradar = !! (OS_REG_READ(ah, AR_PHY_RADAR_1) &
666 	    AR_PHY_RADAR_1_BLOCK_CHECK);
667 	pe->pe_enmaxrssi = !! (OS_REG_READ(ah, AR_PHY_RADAR_1) &
668 	    AR_PHY_RADAR_1_MAX_RRSSI);
669 }
670 
671 /*
672  * Enable radar detection and set the radar parameters per the
673  * values in pe
674  */
675 void
ar5416EnableDfs(struct ath_hal * ah,HAL_PHYERR_PARAM * pe)676 ar5416EnableDfs(struct ath_hal *ah, HAL_PHYERR_PARAM *pe)
677 {
678 	uint32_t val;
679 
680 	val = OS_REG_READ(ah, AR_PHY_RADAR_0);
681 
682 	if (pe->pe_firpwr != HAL_PHYERR_PARAM_NOVAL) {
683 		val &= ~AR_PHY_RADAR_0_FIRPWR;
684 		val |= SM(pe->pe_firpwr, AR_PHY_RADAR_0_FIRPWR);
685 	}
686 	if (pe->pe_rrssi != HAL_PHYERR_PARAM_NOVAL) {
687 		val &= ~AR_PHY_RADAR_0_RRSSI;
688 		val |= SM(pe->pe_rrssi, AR_PHY_RADAR_0_RRSSI);
689 	}
690 	if (pe->pe_height != HAL_PHYERR_PARAM_NOVAL) {
691 		val &= ~AR_PHY_RADAR_0_HEIGHT;
692 		val |= SM(pe->pe_height, AR_PHY_RADAR_0_HEIGHT);
693 	}
694 	if (pe->pe_prssi != HAL_PHYERR_PARAM_NOVAL) {
695 		val &= ~AR_PHY_RADAR_0_PRSSI;
696 		val |= SM(pe->pe_prssi, AR_PHY_RADAR_0_PRSSI);
697 	}
698 	if (pe->pe_inband != HAL_PHYERR_PARAM_NOVAL) {
699 		val &= ~AR_PHY_RADAR_0_INBAND;
700 		val |= SM(pe->pe_inband, AR_PHY_RADAR_0_INBAND);
701 	}
702 
703 	/*Enable FFT data*/
704 	val |= AR_PHY_RADAR_0_FFT_ENA;
705 
706 	OS_REG_WRITE(ah, AR_PHY_RADAR_0, val | AR_PHY_RADAR_0_ENA);
707 
708 	if (pe->pe_usefir128 == 1)
709 		OS_REG_CLR_BIT(ah, AR_PHY_RADAR_1, AR_PHY_RADAR_1_USE_FIR128);
710 	else if (pe->pe_usefir128 == 0)
711 		OS_REG_SET_BIT(ah, AR_PHY_RADAR_1, AR_PHY_RADAR_1_USE_FIR128);
712 
713 	if (pe->pe_enmaxrssi == 1)
714 		OS_REG_SET_BIT(ah, AR_PHY_RADAR_1, AR_PHY_RADAR_1_MAX_RRSSI);
715 	else if (pe->pe_enmaxrssi == 0)
716 		OS_REG_CLR_BIT(ah, AR_PHY_RADAR_1, AR_PHY_RADAR_1_MAX_RRSSI);
717 
718 	if (pe->pe_blockradar == 1)
719 		OS_REG_SET_BIT(ah, AR_PHY_RADAR_1, AR_PHY_RADAR_1_BLOCK_CHECK);
720 	else if (pe->pe_blockradar == 0)
721 		OS_REG_CLR_BIT(ah, AR_PHY_RADAR_1, AR_PHY_RADAR_1_BLOCK_CHECK);
722 
723 	if (pe->pe_maxlen != HAL_PHYERR_PARAM_NOVAL) {
724 		val = OS_REG_READ(ah, AR_PHY_RADAR_1);
725 		val &= ~AR_PHY_RADAR_1_MAXLEN;
726 		val |= SM(pe->pe_maxlen, AR_PHY_RADAR_1_MAXLEN);
727 		OS_REG_WRITE(ah, AR_PHY_RADAR_1, val);
728 	}
729 
730 	/*
731 	 * Enable HT/40 if the upper layer asks;
732 	 * it should check the channel is HT/40 and HAL_CAP_EXT_CHAN_DFS
733 	 * is available.
734 	 */
735 	if (pe->pe_extchannel == 1)
736 		OS_REG_SET_BIT(ah, AR_PHY_RADAR_EXT, AR_PHY_RADAR_EXT_ENA);
737 	else if (pe->pe_extchannel == 0)
738 		OS_REG_CLR_BIT(ah, AR_PHY_RADAR_EXT, AR_PHY_RADAR_EXT_ENA);
739 
740 	if (pe->pe_relstep != HAL_PHYERR_PARAM_NOVAL) {
741 		val = OS_REG_READ(ah, AR_PHY_RADAR_1);
742 		val &= ~AR_PHY_RADAR_1_RELSTEP_THRESH;
743 		val |= SM(pe->pe_relstep, AR_PHY_RADAR_1_RELSTEP_THRESH);
744 		OS_REG_WRITE(ah, AR_PHY_RADAR_1, val);
745 	}
746 	if (pe->pe_relpwr != HAL_PHYERR_PARAM_NOVAL) {
747 		val = OS_REG_READ(ah, AR_PHY_RADAR_1);
748 		val &= ~AR_PHY_RADAR_1_RELPWR_THRESH;
749 		val |= SM(pe->pe_relpwr, AR_PHY_RADAR_1_RELPWR_THRESH);
750 		OS_REG_WRITE(ah, AR_PHY_RADAR_1, val);
751 	}
752 }
753 
754 /*
755  * Extract the radar event information from the given phy error.
756  *
757  * Returns AH_TRUE if the phy error was actually a phy error,
758  * AH_FALSE if the phy error wasn't a phy error.
759  */
760 HAL_BOOL
ar5416ProcessRadarEvent(struct ath_hal * ah,struct ath_rx_status * rxs,uint64_t fulltsf,const char * buf,HAL_DFS_EVENT * event)761 ar5416ProcessRadarEvent(struct ath_hal *ah, struct ath_rx_status *rxs,
762     uint64_t fulltsf, const char *buf, HAL_DFS_EVENT *event)
763 {
764 	/*
765 	 * For now, this isn't implemented.
766 	 */
767 	return AH_FALSE;
768 }
769 
770 /*
771  * Return whether fast-clock is currently enabled for this
772  * channel.
773  */
774 HAL_BOOL
ar5416IsFastClockEnabled(struct ath_hal * ah)775 ar5416IsFastClockEnabled(struct ath_hal *ah)
776 {
777 	struct ath_hal_private *ahp = AH_PRIVATE(ah);
778 
779 	return IS_5GHZ_FAST_CLOCK_EN(ah, ahp->ah_curchan);
780 }
781