ath - Reimport fresh from FreeBSD 01-Jan-2014 for re-port
[dragonfly.git] / sys / dev / netif / ath / ath_hal / ar5416 / ar5416_misc.c
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  * Setup the TX/RX chainmasks - this needs to be done before a call
260  * to the reset method as it doesn't update the hardware.
261  */
262 void
263 ar5416SetChainMasks(struct ath_hal *ah, uint32_t tx_chainmask,
264     uint32_t rx_chainmask)
265 {
266         HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps;
267
268         AH5416(ah)->ah_tx_chainmask = tx_chainmask & pCap->halTxChainMask;
269         AH5416(ah)->ah_rx_chainmask = rx_chainmask & pCap->halRxChainMask;
270 }
271
272 /*
273  * Return approximation of extension channel busy over an time interval
274  * 0% (clear) -> 100% (busy)
275  *
276  * XXX TODO: update this to correctly sample all the counters,
277  *           rather than a subset of it.
278  */
279 uint32_t
280 ar5416Get11nExtBusy(struct ath_hal *ah)
281 {
282     struct ath_hal_5416 *ahp = AH5416(ah);
283     uint32_t busy; /* percentage */
284     uint32_t cycleCount, ctlBusy, extBusy;
285
286     ctlBusy = OS_REG_READ(ah, AR_RCCNT);
287     extBusy = OS_REG_READ(ah, AR_EXTRCCNT);
288     cycleCount = OS_REG_READ(ah, AR_CCCNT);
289
290     if (ahp->ah_cycleCount == 0 || ahp->ah_cycleCount > cycleCount) {
291         /*
292          * Cycle counter wrap (or initial call); it's not possible
293          * to accurately calculate a value because the registers
294          * right shift rather than wrap--so punt and return 0.
295          */
296         busy = 0;
297         HALDEBUG(ah, HAL_DEBUG_ANY, "%s: cycle counter wrap. ExtBusy = 0\n",
298             __func__);
299
300     } else {
301         uint32_t cycleDelta = cycleCount - ahp->ah_cycleCount;
302         uint32_t ctlBusyDelta = ctlBusy - ahp->ah_ctlBusy;
303         uint32_t extBusyDelta = extBusy - ahp->ah_extBusy;
304         uint32_t ctlClearDelta = 0;
305
306         /* Compute control channel rxclear.
307          * The cycle delta may be less than the control channel delta.
308          * This could be solved by freezing the timers (or an atomic read,
309          * if one was available). Checking for the condition should be
310          * sufficient.
311          */
312         if (cycleDelta > ctlBusyDelta) {
313             ctlClearDelta = cycleDelta - ctlBusyDelta;
314         }
315
316         /* Compute ratio of extension channel busy to control channel clear
317          * as an approximation to extension channel cleanliness.
318          *
319          * According to the hardware folks, ext rxclear is undefined
320          * if the ctrl rxclear is de-asserted (i.e. busy)
321          */
322         if (ctlClearDelta) {
323             busy = (extBusyDelta * 100) / ctlClearDelta;
324         } else {
325             busy = 100;
326         }
327         if (busy > 100) {
328             busy = 100;
329         }
330 #if 0
331         HALDEBUG(ah, HAL_DEBUG_ANY, "%s: cycleDelta 0x%x, ctlBusyDelta 0x%x, "
332              "extBusyDelta 0x%x, ctlClearDelta 0x%x, "
333              "busy %d\n",
334               __func__, cycleDelta, ctlBusyDelta, extBusyDelta, ctlClearDelta, busy);
335 #endif
336     }
337
338     ahp->ah_cycleCount = cycleCount;
339     ahp->ah_ctlBusy = ctlBusy;
340     ahp->ah_extBusy = extBusy;
341
342     return busy;
343 }
344
345 /*
346  * Configure 20/40 operation
347  *
348  * 20/40 = joint rx clear (control and extension)
349  * 20    = rx clear (control)
350  *
351  * - NOTE: must stop MAC (tx) and requeue 40 MHz packets as 20 MHz when changing
352  *         from 20/40 => 20 only
353  */
354 void
355 ar5416Set11nMac2040(struct ath_hal *ah, HAL_HT_MACMODE mode)
356 {
357     uint32_t macmode;
358
359     /* Configure MAC for 20/40 operation */
360     if (mode == HAL_HT_MACMODE_2040) {
361         macmode = AR_2040_JOINED_RX_CLEAR;
362     } else {
363         macmode = 0;
364     }
365     OS_REG_WRITE(ah, AR_2040_MODE, macmode);
366 }
367
368 /*
369  * Get Rx clear (control/extension channel)
370  *
371  * Returns active low (busy) for ctrl/ext channel
372  * Owl 2.0
373  */
374 HAL_HT_RXCLEAR
375 ar5416Get11nRxClear(struct ath_hal *ah)
376 {
377     HAL_HT_RXCLEAR rxclear = 0;
378     uint32_t val;
379
380     val = OS_REG_READ(ah, AR_DIAG_SW);
381
382     /* control channel */
383     if (val & AR_DIAG_RXCLEAR_CTL_LOW) {
384         rxclear |= HAL_RX_CLEAR_CTL_LOW;
385     }
386     /* extension channel */
387     if (val & AR_DIAG_RXCLEAR_EXT_LOW) {
388         rxclear |= HAL_RX_CLEAR_EXT_LOW;
389     }
390     return rxclear;
391 }
392
393 /*
394  * Set Rx clear (control/extension channel)
395  *
396  * Useful for forcing the channel to appear busy for
397  * debugging/diagnostics
398  * Owl 2.0
399  */
400 void
401 ar5416Set11nRxClear(struct ath_hal *ah, HAL_HT_RXCLEAR rxclear)
402 {
403     /* control channel */
404     if (rxclear & HAL_RX_CLEAR_CTL_LOW) {
405         OS_REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RXCLEAR_CTL_LOW);
406     } else {
407         OS_REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_RXCLEAR_CTL_LOW);
408     }
409     /* extension channel */
410     if (rxclear & HAL_RX_CLEAR_EXT_LOW) {
411         OS_REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RXCLEAR_EXT_LOW);
412     } else {
413         OS_REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_RXCLEAR_EXT_LOW);
414     }
415 }
416
417 /* XXX shouldn't be here! */
418 #define TU_TO_USEC(_tu)         ((_tu) << 10)
419
420 HAL_STATUS
421 ar5416SetQuiet(struct ath_hal *ah, uint32_t period, uint32_t duration,
422     uint32_t nextStart, HAL_QUIET_FLAG flag)
423 {
424         uint32_t period_us = TU_TO_USEC(period); /* convert to us unit */
425         uint32_t nextStart_us = TU_TO_USEC(nextStart); /* convert to us unit */
426         if (flag & HAL_QUIET_ENABLE) {
427                 if ((!nextStart) || (flag & HAL_QUIET_ADD_CURRENT_TSF)) {
428                         /* Add the nextStart offset to the current TSF */
429                         nextStart_us += OS_REG_READ(ah, AR_TSF_L32);
430                 }
431                 if (flag & HAL_QUIET_ADD_SWBA_RESP_TIME) {
432                         nextStart_us += ah->ah_config.ah_sw_beacon_response_time;
433                 }
434                 OS_REG_RMW_FIELD(ah, AR_QUIET1, AR_QUIET1_QUIET_ACK_CTS_ENABLE, 1);
435                 OS_REG_WRITE(ah, AR_QUIET2, SM(duration, AR_QUIET2_QUIET_DUR));
436                 OS_REG_WRITE(ah, AR_QUIET_PERIOD, period_us);
437                 OS_REG_WRITE(ah, AR_NEXT_QUIET, nextStart_us);
438                 OS_REG_SET_BIT(ah, AR_TIMER_MODE, AR_TIMER_MODE_QUIET);
439         } else {
440                 OS_REG_CLR_BIT(ah, AR_TIMER_MODE, AR_TIMER_MODE_QUIET);
441         }
442         return HAL_OK;
443 }
444 #undef  TU_TO_USEC
445
446 HAL_STATUS
447 ar5416GetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
448         uint32_t capability, uint32_t *result)
449 {
450         switch (type) {
451         case HAL_CAP_BB_HANG:
452                 switch (capability) {
453                 case HAL_BB_HANG_RIFS:
454                         return (AR_SREV_HOWL(ah) || AR_SREV_SOWL(ah)) ? HAL_OK : HAL_ENOTSUPP;
455                 case HAL_BB_HANG_DFS:
456                         return (AR_SREV_HOWL(ah) || AR_SREV_SOWL(ah)) ? HAL_OK : HAL_ENOTSUPP;
457                 case HAL_BB_HANG_RX_CLEAR:
458                         return AR_SREV_MERLIN(ah) ? HAL_OK : HAL_ENOTSUPP;
459                 }
460                 break;
461         case HAL_CAP_MAC_HANG:
462                 return ((ah->ah_macVersion == AR_XSREV_VERSION_OWL_PCI) ||
463                     (ah->ah_macVersion == AR_XSREV_VERSION_OWL_PCIE) ||
464                     AR_SREV_HOWL(ah) || AR_SREV_SOWL(ah)) ?
465                         HAL_OK : HAL_ENOTSUPP;
466         case HAL_CAP_DIVERSITY:         /* disable classic fast diversity */
467                 return HAL_ENXIO;
468         case HAL_CAP_ENFORCE_TXOP:
469                 if (capability == 0)
470                         return (HAL_OK);
471                 if (capability != 1)
472                         return (HAL_ENOTSUPP);
473                 (*result) =
474                     !! (AH5212(ah)->ah_miscMode & AR_PCU_TXOP_TBTT_LIMIT_ENA);
475                 return (HAL_OK);
476         default:
477                 break;
478         }
479         return ar5212GetCapability(ah, type, capability, result);
480 }
481
482 HAL_BOOL
483 ar5416SetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
484     u_int32_t capability, u_int32_t setting, HAL_STATUS *status)
485 {
486         HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps;
487
488         switch (type) {
489         case HAL_CAP_RX_CHAINMASK:
490                 setting &= ath_hal_eepromGet(ah, AR_EEP_RXMASK, NULL);
491                 pCap->halRxChainMask = setting;
492                 if (owl_get_ntxchains(setting) > 2)
493                         pCap->halRxStreams = 2;
494                 else
495                         pCap->halRxStreams = 1;
496                 return AH_TRUE;
497         case HAL_CAP_TX_CHAINMASK:
498                 setting &= ath_hal_eepromGet(ah, AR_EEP_TXMASK, NULL);
499                 pCap->halTxChainMask = setting;
500                 if (owl_get_ntxchains(setting) > 2)
501                         pCap->halTxStreams = 2;
502                 else
503                         pCap->halTxStreams = 1;
504                 return AH_TRUE;
505         case HAL_CAP_ENFORCE_TXOP:
506                 if (capability != 1)
507                         return AH_FALSE;
508                 if (setting) {
509                         AH5212(ah)->ah_miscMode
510                             |= AR_PCU_TXOP_TBTT_LIMIT_ENA;
511                         OS_REG_SET_BIT(ah, AR_MISC_MODE,
512                             AR_PCU_TXOP_TBTT_LIMIT_ENA);
513                 } else {
514                         AH5212(ah)->ah_miscMode
515                             &= ~AR_PCU_TXOP_TBTT_LIMIT_ENA;
516                         OS_REG_CLR_BIT(ah, AR_MISC_MODE,
517                             AR_PCU_TXOP_TBTT_LIMIT_ENA);
518                 }
519                 return AH_TRUE;
520         default:
521                 break;
522         }
523         return ar5212SetCapability(ah, type, capability, setting, status);
524 }
525
526 static int ar5416DetectMacHang(struct ath_hal *ah);
527 static int ar5416DetectBBHang(struct ath_hal *ah);
528
529 HAL_BOOL
530 ar5416GetDiagState(struct ath_hal *ah, int request,
531         const void *args, uint32_t argsize,
532         void **result, uint32_t *resultsize)
533 {
534         struct ath_hal_5416 *ahp = AH5416(ah);
535         int hangs;
536
537         if (ath_hal_getdiagstate(ah, request, args, argsize, result, resultsize))
538                 return AH_TRUE;
539         switch (request) {
540         case HAL_DIAG_EEPROM:
541                 return ath_hal_eepromDiag(ah, request,
542                     args, argsize, result, resultsize);
543         case HAL_DIAG_CHECK_HANGS:
544                 if (argsize != sizeof(int))
545                         return AH_FALSE;
546                 hangs = *(const int *) args;
547                 ahp->ah_hangs = 0;
548                 if (hangs & HAL_BB_HANGS)
549                         ahp->ah_hangs |= ar5416DetectBBHang(ah);
550                 /* NB: if BB is hung MAC will be hung too so skip check */
551                 if (ahp->ah_hangs == 0 && (hangs & HAL_MAC_HANGS))
552                         ahp->ah_hangs |= ar5416DetectMacHang(ah);
553                 *result = &ahp->ah_hangs;
554                 *resultsize = sizeof(ahp->ah_hangs);
555                 return AH_TRUE;
556         }
557         return ar5212GetDiagState(ah, request,
558             args, argsize, result, resultsize);
559 }
560
561 HAL_BOOL
562 ar5416SetRifsDelay(struct ath_hal *ah, const struct ieee80211_channel *chan,
563     HAL_BOOL enable)
564 {
565         uint32_t val;
566         HAL_BOOL is_chan_2g = AH_FALSE;
567         HAL_BOOL is_ht40 = AH_FALSE;
568
569         if (chan)
570                 is_chan_2g = IEEE80211_IS_CHAN_2GHZ(chan);
571
572         if (chan)
573                 is_ht40 = IEEE80211_IS_CHAN_HT40(chan);
574
575         /* Only support disabling RIFS delay for now */
576         HALASSERT(enable == AH_FALSE);
577
578         if (enable == AH_TRUE)
579                 return AH_FALSE;
580
581         /* Change RIFS init delay to 0 */
582         val = OS_REG_READ(ah, AR_PHY_HEAVY_CLIP_FACTOR_RIFS);
583         val &= ~AR_PHY_RIFS_INIT_DELAY;
584         OS_REG_WRITE(ah, AR_PHY_HEAVY_CLIP_FACTOR_RIFS, val);
585
586         /*
587          * For Owl, RIFS RX parameters are controlled differently;
588          * it isn't enabled in the inivals by default.
589          *
590          * For Sowl/Howl, RIFS RX is enabled in the inivals by default;
591          * the following code sets them back to non-RIFS values.
592          *
593          * For > Sowl/Howl, RIFS RX can be left on by default and so
594          * this function shouldn't be called.
595          */
596         if ((! AR_SREV_SOWL(ah)) && (! AR_SREV_HOWL(ah)))
597                 return AH_TRUE;
598
599         /* Reset search delay to default values */
600         if (is_chan_2g)
601                 if (is_ht40)
602                         OS_REG_WRITE(ah, AR_PHY_SEARCH_START_DELAY, 0x268);
603                 else
604                         OS_REG_WRITE(ah, AR_PHY_SEARCH_START_DELAY, 0x134);
605         else
606                 if (is_ht40)
607                         OS_REG_WRITE(ah, AR_PHY_SEARCH_START_DELAY, 0x370);
608                 else
609                         OS_REG_WRITE(ah, AR_PHY_SEARCH_START_DELAY, 0x1b8);
610
611         return AH_TRUE;
612 }
613
614 static HAL_BOOL
615 ar5416CompareDbgHang(struct ath_hal *ah, const mac_dbg_regs_t *regs,
616     const hal_mac_hang_check_t *check)
617 {
618         int found_states;
619
620         found_states = 0;
621         if (check->states & dcu_chain_state) {
622                 int i;
623
624                 for (i = 0; i < 6; i++) {
625                         if (((regs->dma_dbg_4 >> (5*i)) & 0x1f) ==
626                             check->dcu_chain_state)
627                                 found_states |= dcu_chain_state;
628                 }
629                 for (i = 0; i < 4; i++) {
630                         if (((regs->dma_dbg_5 >> (5*i)) & 0x1f) ==
631                             check->dcu_chain_state)
632                                 found_states |= dcu_chain_state;
633                 }
634         }
635         if (check->states & dcu_complete_state) { 
636                 if ((regs->dma_dbg_6 & 0x3) == check->dcu_complete_state)
637                         found_states |= dcu_complete_state;
638         }
639         if (check->states & qcu_stitch_state) { 
640                 if (((regs->dma_dbg_3 >> 18) & 0xf) == check->qcu_stitch_state)
641                         found_states |= qcu_stitch_state;
642         }
643         if (check->states & qcu_fetch_state) { 
644                 if (((regs->dma_dbg_3 >> 22) & 0xf) == check->qcu_fetch_state)
645                         found_states |= qcu_fetch_state;
646         }
647         if (check->states & qcu_complete_state) { 
648                 if (((regs->dma_dbg_3 >> 26) & 0x7) == check->qcu_complete_state)
649                         found_states |= qcu_complete_state;
650         }
651         return (found_states == check->states);
652 }
653
654 #define NUM_STATUS_READS 50
655
656 static int
657 ar5416DetectMacHang(struct ath_hal *ah)
658 {
659         static const hal_mac_hang_check_t hang_sig1 = {
660                 .dcu_chain_state        = 0x6,
661                 .dcu_complete_state     = 0x1,
662                 .states                 = dcu_chain_state
663                                         | dcu_complete_state,
664         };
665         static const hal_mac_hang_check_t hang_sig2 = {
666                 .qcu_stitch_state       = 0x9,
667                 .qcu_fetch_state        = 0x8,
668                 .qcu_complete_state     = 0x4,
669                 .states                 = qcu_stitch_state
670                                         | qcu_fetch_state
671                                         | qcu_complete_state,
672         };
673         mac_dbg_regs_t mac_dbg;
674         int i;
675
676         mac_dbg.dma_dbg_3 = OS_REG_READ(ah, AR_DMADBG_3);
677         mac_dbg.dma_dbg_4 = OS_REG_READ(ah, AR_DMADBG_4);
678         mac_dbg.dma_dbg_5 = OS_REG_READ(ah, AR_DMADBG_5);
679         mac_dbg.dma_dbg_6 = OS_REG_READ(ah, AR_DMADBG_6);
680         for (i = 1; i <= NUM_STATUS_READS; i++) {
681                 if (mac_dbg.dma_dbg_3 != OS_REG_READ(ah, AR_DMADBG_3) ||
682                     mac_dbg.dma_dbg_4 != OS_REG_READ(ah, AR_DMADBG_4) ||
683                     mac_dbg.dma_dbg_5 != OS_REG_READ(ah, AR_DMADBG_5) ||
684                     mac_dbg.dma_dbg_6 != OS_REG_READ(ah, AR_DMADBG_6))
685                         return 0;
686         }
687
688         if (ar5416CompareDbgHang(ah, &mac_dbg, &hang_sig1))
689                 return HAL_MAC_HANG_SIG1;
690         if (ar5416CompareDbgHang(ah, &mac_dbg, &hang_sig2))
691                 return HAL_MAC_HANG_SIG2;
692
693         HALDEBUG(ah, HAL_DEBUG_HANG, "%s Found an unknown MAC hang signature "
694             "DMADBG_3=0x%x DMADBG_4=0x%x DMADBG_5=0x%x DMADBG_6=0x%x\n",
695             __func__, mac_dbg.dma_dbg_3, mac_dbg.dma_dbg_4, mac_dbg.dma_dbg_5,
696             mac_dbg.dma_dbg_6);
697
698         return 0;
699 }
700
701 /*
702  * Determine if the baseband using the Observation Bus Register
703  */
704 static int
705 ar5416DetectBBHang(struct ath_hal *ah)
706 {
707 #define N(a) (sizeof(a)/sizeof(a[0]))
708         /*
709          * Check the PCU Observation Bus 1 register (0x806c)
710          * NUM_STATUS_READS times
711          *
712          * 4 known BB hang signatures -
713          * [1] bits 8,9,11 are 0. State machine state (bits 25-31) is 0x1E
714          * [2] bits 8,9 are 1, bit 11 is 0. State machine state
715          *     (bits 25-31) is 0x52
716          * [3] bits 8,9 are 1, bit 11 is 0. State machine state
717          *     (bits 25-31) is 0x18
718          * [4] bit 10 is 1, bit 11 is 0. WEP state (bits 12-17) is 0x2,
719          *     Rx State (bits 20-24) is 0x7.
720          */
721         static const struct {
722                 uint32_t val;
723                 uint32_t mask;
724                 int code;
725         } hang_list[] = {
726                 /* Reg Value   Reg Mask    Hang Code XXX */
727                 { 0x1E000000, 0x7E000B00, HAL_BB_HANG_DFS },
728                 { 0x52000B00, 0x7E000B00, HAL_BB_HANG_RIFS },
729                 { 0x18000B00, 0x7E000B00, HAL_BB_HANG_RX_CLEAR },
730                 { 0x00702400, 0x7E7FFFEF, HAL_BB_HANG_RX_CLEAR }
731         };
732         uint32_t hang_sig;
733         int i;
734
735         hang_sig = OS_REG_READ(ah, AR_OBSERV_1);
736         for (i = 1; i <= NUM_STATUS_READS; i++) {
737                 if (hang_sig != OS_REG_READ(ah, AR_OBSERV_1))
738                         return 0;
739         }
740         for (i = 0; i < N(hang_list); i++)
741                 if ((hang_sig & hang_list[i].mask) == hang_list[i].val) {
742                         HALDEBUG(ah, HAL_DEBUG_HANG,
743                             "%s BB hang, signature 0x%x, code 0x%x\n",
744                             __func__, hang_sig, hang_list[i].code);
745                         return hang_list[i].code;
746                 }
747
748         HALDEBUG(ah, HAL_DEBUG_HANG, "%s Found an unknown BB hang signature! "
749             "<0x806c>=0x%x\n", __func__, hang_sig);
750
751         return 0;
752 #undef N
753 }
754 #undef NUM_STATUS_READS