xref: /freebsd-src/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_interrupts.c (revision ab3b48eaa21ed33fdc9035eae792ad6d5f29c69d)
176bd547bSAdrian Chadd /*
276bd547bSAdrian Chadd  * Copyright (c) 2013 Qualcomm Atheros, Inc.
376bd547bSAdrian Chadd  *
476bd547bSAdrian Chadd  * Permission to use, copy, modify, and/or distribute this software for any
576bd547bSAdrian Chadd  * purpose with or without fee is hereby granted, provided that the above
676bd547bSAdrian Chadd  * copyright notice and this permission notice appear in all copies.
776bd547bSAdrian Chadd  *
876bd547bSAdrian Chadd  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
976bd547bSAdrian Chadd  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
1076bd547bSAdrian Chadd  * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
1176bd547bSAdrian Chadd  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
1276bd547bSAdrian Chadd  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
1376bd547bSAdrian Chadd  * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
1476bd547bSAdrian Chadd  * PERFORMANCE OF THIS SOFTWARE.
1576bd547bSAdrian Chadd  */
1676bd547bSAdrian Chadd 
1776bd547bSAdrian Chadd #include "opt_ah.h"
1876bd547bSAdrian Chadd 
1976bd547bSAdrian Chadd #include "ah.h"
2076bd547bSAdrian Chadd #include "ah_internal.h"
2176bd547bSAdrian Chadd 
2276bd547bSAdrian Chadd #include "ar9300/ar9300.h"
2376bd547bSAdrian Chadd #include "ar9300/ar9300reg.h"
2476bd547bSAdrian Chadd #include "ar9300/ar9300phy.h"
2576bd547bSAdrian Chadd 
2676bd547bSAdrian Chadd /*
2776bd547bSAdrian Chadd  * Checks to see if an interrupt is pending on our NIC
2876bd547bSAdrian Chadd  *
2976bd547bSAdrian Chadd  * Returns: TRUE    if an interrupt is pending
3076bd547bSAdrian Chadd  *          FALSE   if not
3176bd547bSAdrian Chadd  */
3276bd547bSAdrian Chadd HAL_BOOL
ar9300_is_interrupt_pending(struct ath_hal * ah)3376bd547bSAdrian Chadd ar9300_is_interrupt_pending(struct ath_hal *ah)
3476bd547bSAdrian Chadd {
3576bd547bSAdrian Chadd     u_int32_t sync_en_def = AR9300_INTR_SYNC_DEFAULT;
3676bd547bSAdrian Chadd     u_int32_t host_isr;
3776bd547bSAdrian Chadd 
3876bd547bSAdrian Chadd     /*
3976bd547bSAdrian Chadd      * Some platforms trigger our ISR before applying power to
4076bd547bSAdrian Chadd      * the card, so make sure.
4176bd547bSAdrian Chadd      */
4276bd547bSAdrian Chadd     host_isr = OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_ASYNC_CAUSE));
4376bd547bSAdrian Chadd     if ((host_isr & AR_INTR_ASYNC_USED) && (host_isr != AR_INTR_SPURIOUS)) {
4476bd547bSAdrian Chadd         return AH_TRUE;
4576bd547bSAdrian Chadd     }
4676bd547bSAdrian Chadd 
4776bd547bSAdrian Chadd     host_isr = OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_CAUSE));
4876bd547bSAdrian Chadd     if (AR_SREV_POSEIDON(ah)) {
4976bd547bSAdrian Chadd         sync_en_def = AR9300_INTR_SYNC_DEF_NO_HOST1_PERR;
5076bd547bSAdrian Chadd     }
5176bd547bSAdrian Chadd     else if (AR_SREV_WASP(ah)) {
5276bd547bSAdrian Chadd         sync_en_def = AR9340_INTR_SYNC_DEFAULT;
5376bd547bSAdrian Chadd     }
5476bd547bSAdrian Chadd 
5576bd547bSAdrian Chadd     if ((host_isr & (sync_en_def | AR_INTR_SYNC_MASK_GPIO)) &&
5676bd547bSAdrian Chadd         (host_isr != AR_INTR_SPURIOUS)) {
5776bd547bSAdrian Chadd         return AH_TRUE;
5876bd547bSAdrian Chadd     }
5976bd547bSAdrian Chadd 
6076bd547bSAdrian Chadd     return AH_FALSE;
6176bd547bSAdrian Chadd }
6276bd547bSAdrian Chadd 
6376bd547bSAdrian Chadd /*
6476bd547bSAdrian Chadd  * Reads the Interrupt Status Register value from the NIC, thus deasserting
6576bd547bSAdrian Chadd  * the interrupt line, and returns both the masked and unmasked mapped ISR
6676bd547bSAdrian Chadd  * values.  The value returned is mapped to abstract the hw-specific bit
6776bd547bSAdrian Chadd  * locations in the Interrupt Status Register.
6876bd547bSAdrian Chadd  *
6976bd547bSAdrian Chadd  * Returns: A hardware-abstracted bitmap of all non-masked-out
7076bd547bSAdrian Chadd  *          interrupts pending, as well as an unmasked value
7176bd547bSAdrian Chadd  */
7276bd547bSAdrian Chadd #define MAP_ISR_S2_HAL_CST          6 /* Carrier sense timeout */
7376bd547bSAdrian Chadd #define MAP_ISR_S2_HAL_GTT          6 /* Global transmit timeout */
7476bd547bSAdrian Chadd #define MAP_ISR_S2_HAL_TIM          3 /* TIM */
7576bd547bSAdrian Chadd #define MAP_ISR_S2_HAL_CABEND       0 /* CABEND */
7676bd547bSAdrian Chadd #define MAP_ISR_S2_HAL_DTIMSYNC     7 /* DTIMSYNC */
7776bd547bSAdrian Chadd #define MAP_ISR_S2_HAL_DTIM         7 /* DTIM */
7876bd547bSAdrian Chadd #define MAP_ISR_S2_HAL_TSFOOR       4 /* Rx TSF out of range */
7976bd547bSAdrian Chadd #define MAP_ISR_S2_HAL_BBPANIC      6 /* Panic watchdog IRQ from BB */
8076bd547bSAdrian Chadd HAL_BOOL
ar9300_get_pending_interrupts(struct ath_hal * ah,HAL_INT * masked,HAL_INT_TYPE type,u_int8_t msi,HAL_BOOL nortc)8176bd547bSAdrian Chadd ar9300_get_pending_interrupts(
8276bd547bSAdrian Chadd     struct ath_hal *ah,
8376bd547bSAdrian Chadd     HAL_INT *masked,
8476bd547bSAdrian Chadd     HAL_INT_TYPE type,
8576bd547bSAdrian Chadd     u_int8_t msi,
8676bd547bSAdrian Chadd     HAL_BOOL nortc)
8776bd547bSAdrian Chadd {
8876bd547bSAdrian Chadd     struct ath_hal_9300 *ahp = AH9300(ah);
8976bd547bSAdrian Chadd     HAL_BOOL  ret_val = AH_TRUE;
9076bd547bSAdrian Chadd     u_int32_t isr = 0;
9176bd547bSAdrian Chadd     u_int32_t mask2 = 0;
9276bd547bSAdrian Chadd     u_int32_t sync_cause = 0;
9376bd547bSAdrian Chadd     u_int32_t async_cause;
9476bd547bSAdrian Chadd     u_int32_t msi_pend_addr_mask = 0;
9576bd547bSAdrian Chadd     u_int32_t sync_en_def = AR9300_INTR_SYNC_DEFAULT;
9676bd547bSAdrian Chadd     HAL_CAPABILITIES *p_cap = &AH_PRIVATE(ah)->ah_caps;
9776bd547bSAdrian Chadd 
9876bd547bSAdrian Chadd     *masked = 0;
9976bd547bSAdrian Chadd 
10076bd547bSAdrian Chadd     if (!nortc) {
10176bd547bSAdrian Chadd         if (HAL_INT_MSI == type) {
10276bd547bSAdrian Chadd             if (msi == HAL_MSIVEC_RXHP) {
10376bd547bSAdrian Chadd                 OS_REG_WRITE(ah, AR_ISR, AR_ISR_HP_RXOK);
10476bd547bSAdrian Chadd                 *masked = HAL_INT_RXHP;
10576bd547bSAdrian Chadd                 goto end;
10676bd547bSAdrian Chadd             } else if (msi == HAL_MSIVEC_RXLP) {
10776bd547bSAdrian Chadd                 OS_REG_WRITE(ah, AR_ISR,
10876bd547bSAdrian Chadd                     (AR_ISR_LP_RXOK | AR_ISR_RXMINTR | AR_ISR_RXINTM));
10976bd547bSAdrian Chadd                 *masked = HAL_INT_RXLP;
11076bd547bSAdrian Chadd                 goto end;
11176bd547bSAdrian Chadd             } else if (msi == HAL_MSIVEC_TX) {
11276bd547bSAdrian Chadd                 OS_REG_WRITE(ah, AR_ISR, AR_ISR_TXOK);
11376bd547bSAdrian Chadd                 *masked = HAL_INT_TX;
11476bd547bSAdrian Chadd                 goto end;
11576bd547bSAdrian Chadd             } else if (msi == HAL_MSIVEC_MISC) {
11676bd547bSAdrian Chadd                 /*
11776bd547bSAdrian Chadd                  * For the misc MSI event fall through and determine the cause.
11876bd547bSAdrian Chadd                  */
11976bd547bSAdrian Chadd             }
12076bd547bSAdrian Chadd         }
12176bd547bSAdrian Chadd     }
12276bd547bSAdrian Chadd 
12376bd547bSAdrian Chadd     /* Make sure mac interrupt is pending in async interrupt cause register */
12476bd547bSAdrian Chadd     async_cause = OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_ASYNC_CAUSE));
12576bd547bSAdrian Chadd     if (async_cause & AR_INTR_ASYNC_USED) {
12676bd547bSAdrian Chadd         /*
12776bd547bSAdrian Chadd          * RTC may not be on since it runs on a slow 32khz clock
12876bd547bSAdrian Chadd          * so check its status to be sure
12976bd547bSAdrian Chadd          */
13076bd547bSAdrian Chadd         if (!nortc &&
13176bd547bSAdrian Chadd             (OS_REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M) ==
13276bd547bSAdrian Chadd              AR_RTC_STATUS_ON)
13376bd547bSAdrian Chadd         {
13476bd547bSAdrian Chadd             isr = OS_REG_READ(ah, AR_ISR);
13576bd547bSAdrian Chadd         }
13676bd547bSAdrian Chadd     }
13776bd547bSAdrian Chadd 
13876bd547bSAdrian Chadd     if (AR_SREV_POSEIDON(ah)) {
13976bd547bSAdrian Chadd         sync_en_def = AR9300_INTR_SYNC_DEF_NO_HOST1_PERR;
14076bd547bSAdrian Chadd     }
14176bd547bSAdrian Chadd     else if (AR_SREV_WASP(ah)) {
14276bd547bSAdrian Chadd         sync_en_def = AR9340_INTR_SYNC_DEFAULT;
14376bd547bSAdrian Chadd     }
14476bd547bSAdrian Chadd 
145a32a326bSAdrian Chadd     /* Store away the async and sync cause registers */
146a32a326bSAdrian Chadd     /* XXX Do this before the filtering done below */
147a32a326bSAdrian Chadd #ifdef	AH_INTERRUPT_DEBUGGING
148a32a326bSAdrian Chadd 	ah->ah_intrstate[0] = OS_REG_READ(ah, AR_ISR);
149a32a326bSAdrian Chadd 	ah->ah_intrstate[1] = OS_REG_READ(ah, AR_ISR_S0);
150a32a326bSAdrian Chadd 	ah->ah_intrstate[2] = OS_REG_READ(ah, AR_ISR_S1);
151a32a326bSAdrian Chadd 	ah->ah_intrstate[3] = OS_REG_READ(ah, AR_ISR_S2);
152a32a326bSAdrian Chadd 	ah->ah_intrstate[4] = OS_REG_READ(ah, AR_ISR_S3);
153a32a326bSAdrian Chadd 	ah->ah_intrstate[5] = OS_REG_READ(ah, AR_ISR_S4);
154a32a326bSAdrian Chadd 	ah->ah_intrstate[6] = OS_REG_READ(ah, AR_ISR_S5);
155a32a326bSAdrian Chadd 
156a32a326bSAdrian Chadd 	/* XXX double reading? */
157a32a326bSAdrian Chadd 	ah->ah_syncstate = OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_CAUSE));
158a32a326bSAdrian Chadd #endif
159a32a326bSAdrian Chadd 
16076bd547bSAdrian Chadd     sync_cause =
16176bd547bSAdrian Chadd         OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_CAUSE)) &
16276bd547bSAdrian Chadd         (sync_en_def | AR_INTR_SYNC_MASK_GPIO);
16376bd547bSAdrian Chadd 
16476bd547bSAdrian Chadd     if (!isr && !sync_cause && !async_cause) {
16576bd547bSAdrian Chadd         ret_val = AH_FALSE;
16676bd547bSAdrian Chadd         goto end;
16776bd547bSAdrian Chadd     }
16876bd547bSAdrian Chadd 
169e113789bSAdrian Chadd     HALDEBUG(ah, HAL_DEBUG_INTERRUPT,
170e113789bSAdrian Chadd         "%s: isr=0x%x, sync_cause=0x%x, async_cause=0x%x\n",
171e113789bSAdrian Chadd 	__func__,
172e113789bSAdrian Chadd 	isr,
173e113789bSAdrian Chadd 	sync_cause,
174e113789bSAdrian Chadd 	async_cause);
175e113789bSAdrian Chadd 
17676bd547bSAdrian Chadd     if (isr) {
17776bd547bSAdrian Chadd         if (isr & AR_ISR_BCNMISC) {
17876bd547bSAdrian Chadd             u_int32_t isr2;
17976bd547bSAdrian Chadd             isr2 = OS_REG_READ(ah, AR_ISR_S2);
18076bd547bSAdrian Chadd 
18176bd547bSAdrian Chadd             /* Translate ISR bits to HAL values */
18276bd547bSAdrian Chadd             mask2 |= ((isr2 & AR_ISR_S2_TIM) >> MAP_ISR_S2_HAL_TIM);
18376bd547bSAdrian Chadd             mask2 |= ((isr2 & AR_ISR_S2_DTIM) >> MAP_ISR_S2_HAL_DTIM);
18476bd547bSAdrian Chadd             mask2 |= ((isr2 & AR_ISR_S2_DTIMSYNC) >> MAP_ISR_S2_HAL_DTIMSYNC);
18576bd547bSAdrian Chadd             mask2 |= ((isr2 & AR_ISR_S2_CABEND) >> MAP_ISR_S2_HAL_CABEND);
18676bd547bSAdrian Chadd             mask2 |= ((isr2 & AR_ISR_S2_GTT) << MAP_ISR_S2_HAL_GTT);
18776bd547bSAdrian Chadd             mask2 |= ((isr2 & AR_ISR_S2_CST) << MAP_ISR_S2_HAL_CST);
18876bd547bSAdrian Chadd             mask2 |= ((isr2 & AR_ISR_S2_TSFOOR) >> MAP_ISR_S2_HAL_TSFOOR);
18976bd547bSAdrian Chadd             mask2 |= ((isr2 & AR_ISR_S2_BBPANIC) >> MAP_ISR_S2_HAL_BBPANIC);
19076bd547bSAdrian Chadd 
191e113789bSAdrian Chadd             if (!p_cap->halIsrRacSupport) {
19276bd547bSAdrian Chadd                 /*
19376bd547bSAdrian Chadd                  * EV61133 (missing interrupts due to ISR_RAC):
19476bd547bSAdrian Chadd                  * If not using ISR_RAC, clear interrupts by writing to ISR_S2.
19576bd547bSAdrian Chadd                  * This avoids a race condition where a new BCNMISC interrupt
19676bd547bSAdrian Chadd                  * could come in between reading the ISR and clearing the
19776bd547bSAdrian Chadd                  * interrupt via the primary ISR.  We therefore clear the
19876bd547bSAdrian Chadd                  * interrupt via the secondary, which avoids this race.
19976bd547bSAdrian Chadd                  */
20076bd547bSAdrian Chadd                 OS_REG_WRITE(ah, AR_ISR_S2, isr2);
20176bd547bSAdrian Chadd                 isr &= ~AR_ISR_BCNMISC;
20276bd547bSAdrian Chadd             }
20376bd547bSAdrian Chadd         }
20476bd547bSAdrian Chadd 
20576bd547bSAdrian Chadd         /* Use AR_ISR_RAC only if chip supports it.
20676bd547bSAdrian Chadd          * See EV61133 (missing interrupts due to ISR_RAC)
20776bd547bSAdrian Chadd          */
208e113789bSAdrian Chadd         if (p_cap->halIsrRacSupport) {
20976bd547bSAdrian Chadd             isr = OS_REG_READ(ah, AR_ISR_RAC);
21076bd547bSAdrian Chadd         }
21176bd547bSAdrian Chadd         if (isr == 0xffffffff) {
21276bd547bSAdrian Chadd             *masked = 0;
21376bd547bSAdrian Chadd             ret_val = AH_FALSE;
21476bd547bSAdrian Chadd             goto end;
21576bd547bSAdrian Chadd         }
21676bd547bSAdrian Chadd 
21776bd547bSAdrian Chadd         *masked = isr & HAL_INT_COMMON;
21876bd547bSAdrian Chadd 
21976bd547bSAdrian Chadd         /*
22076bd547bSAdrian Chadd          * When interrupt mitigation is switched on, we fake a normal RX or TX
22176bd547bSAdrian Chadd          * interrupt when we received a mitigated interrupt. This way, the upper
22276bd547bSAdrian Chadd          * layer do not need to know about feature.
22376bd547bSAdrian Chadd          */
22476bd547bSAdrian Chadd         if (ahp->ah_intr_mitigation_rx) {
22576bd547bSAdrian Chadd             /* Only Rx interrupt mitigation. No Tx intr. mitigation. */
22676bd547bSAdrian Chadd             if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM)) {
22776bd547bSAdrian Chadd                 *masked |= HAL_INT_RXLP;
22876bd547bSAdrian Chadd             }
22976bd547bSAdrian Chadd         }
23076bd547bSAdrian Chadd         if (ahp->ah_intr_mitigation_tx) {
23176bd547bSAdrian Chadd             if (isr & (AR_ISR_TXMINTR | AR_ISR_TXINTM)) {
23276bd547bSAdrian Chadd                 *masked |= HAL_INT_TX;
23376bd547bSAdrian Chadd             }
23476bd547bSAdrian Chadd         }
23576bd547bSAdrian Chadd 
23676bd547bSAdrian Chadd         if (isr & (AR_ISR_LP_RXOK | AR_ISR_RXERR)) {
23776bd547bSAdrian Chadd             *masked |= HAL_INT_RXLP;
23876bd547bSAdrian Chadd         }
23976bd547bSAdrian Chadd         if (isr & AR_ISR_HP_RXOK) {
24076bd547bSAdrian Chadd             *masked |= HAL_INT_RXHP;
24176bd547bSAdrian Chadd         }
24276bd547bSAdrian Chadd         if (isr & (AR_ISR_TXOK | AR_ISR_TXERR | AR_ISR_TXEOL)) {
24376bd547bSAdrian Chadd             *masked |= HAL_INT_TX;
24476bd547bSAdrian Chadd 
245e113789bSAdrian Chadd             if (!p_cap->halIsrRacSupport) {
24676bd547bSAdrian Chadd                 u_int32_t s0, s1;
24776bd547bSAdrian Chadd                 /*
24876bd547bSAdrian Chadd                  * EV61133 (missing interrupts due to ISR_RAC):
24976bd547bSAdrian Chadd                  * If not using ISR_RAC, clear interrupts by writing to
25076bd547bSAdrian Chadd                  * ISR_S0/S1.
25176bd547bSAdrian Chadd                  * This avoids a race condition where a new interrupt
25276bd547bSAdrian Chadd                  * could come in between reading the ISR and clearing the
25376bd547bSAdrian Chadd                  * interrupt via the primary ISR.  We therefore clear the
25476bd547bSAdrian Chadd                  * interrupt via the secondary, which avoids this race.
25576bd547bSAdrian Chadd                  */
25676bd547bSAdrian Chadd                 s0 = OS_REG_READ(ah, AR_ISR_S0);
25776bd547bSAdrian Chadd                 OS_REG_WRITE(ah, AR_ISR_S0, s0);
25876bd547bSAdrian Chadd                 s1 = OS_REG_READ(ah, AR_ISR_S1);
25976bd547bSAdrian Chadd                 OS_REG_WRITE(ah, AR_ISR_S1, s1);
26076bd547bSAdrian Chadd 
26176bd547bSAdrian Chadd                 isr &= ~(AR_ISR_TXOK | AR_ISR_TXERR | AR_ISR_TXEOL);
26276bd547bSAdrian Chadd             }
26376bd547bSAdrian Chadd         }
26476bd547bSAdrian Chadd 
26576bd547bSAdrian Chadd         /*
26676bd547bSAdrian Chadd          * Do not treat receive overflows as fatal for owl.
26776bd547bSAdrian Chadd          */
26876bd547bSAdrian Chadd         if (isr & AR_ISR_RXORN) {
26976bd547bSAdrian Chadd #if __PKT_SERIOUS_ERRORS__
27076bd547bSAdrian Chadd             HALDEBUG(ah, HAL_DEBUG_INTERRUPT,
27176bd547bSAdrian Chadd                 "%s: receive FIFO overrun interrupt\n", __func__);
27276bd547bSAdrian Chadd #endif
27376bd547bSAdrian Chadd         }
27476bd547bSAdrian Chadd 
27576bd547bSAdrian Chadd #if 0
27676bd547bSAdrian Chadd         /* XXX Verify if this is fixed for Osprey */
277e113789bSAdrian Chadd         if (!p_cap->halAutoSleepSupport) {
27876bd547bSAdrian Chadd             u_int32_t isr5 = OS_REG_READ(ah, AR_ISR_S5_S);
27976bd547bSAdrian Chadd             if (isr5 & AR_ISR_S5_TIM_TIMER) {
28076bd547bSAdrian Chadd                 *masked |= HAL_INT_TIM_TIMER;
28176bd547bSAdrian Chadd             }
28276bd547bSAdrian Chadd         }
28376bd547bSAdrian Chadd #endif
28476bd547bSAdrian Chadd         if (isr & AR_ISR_GENTMR) {
28576bd547bSAdrian Chadd             u_int32_t s5;
28676bd547bSAdrian Chadd 
287e113789bSAdrian Chadd             if (p_cap->halIsrRacSupport) {
28876bd547bSAdrian Chadd                 /* Use secondary shadow registers if using ISR_RAC */
28976bd547bSAdrian Chadd                 s5 = OS_REG_READ(ah, AR_ISR_S5_S);
29076bd547bSAdrian Chadd             } else {
29176bd547bSAdrian Chadd                 s5 = OS_REG_READ(ah, AR_ISR_S5);
29276bd547bSAdrian Chadd             }
29376bd547bSAdrian Chadd             if (isr & AR_ISR_GENTMR) {
29476bd547bSAdrian Chadd 
29576bd547bSAdrian Chadd                 HALDEBUG(ah, HAL_DEBUG_INTERRUPT,
29676bd547bSAdrian Chadd                     "%s: GENTIMER, ISR_RAC=0x%x ISR_S2_S=0x%x\n", __func__,
29776bd547bSAdrian Chadd                     isr, s5);
29876bd547bSAdrian Chadd                 ahp->ah_intr_gen_timer_trigger =
29976bd547bSAdrian Chadd                     MS(s5, AR_ISR_S5_GENTIMER_TRIG);
30076bd547bSAdrian Chadd                 ahp->ah_intr_gen_timer_thresh =
30176bd547bSAdrian Chadd                     MS(s5, AR_ISR_S5_GENTIMER_THRESH);
30276bd547bSAdrian Chadd                 if (ahp->ah_intr_gen_timer_trigger) {
30376bd547bSAdrian Chadd                     *masked |= HAL_INT_GENTIMER;
30476bd547bSAdrian Chadd                 }
30576bd547bSAdrian Chadd             }
306e113789bSAdrian Chadd             if (!p_cap->halIsrRacSupport) {
30776bd547bSAdrian Chadd                 /*
30876bd547bSAdrian Chadd                  * EV61133 (missing interrupts due to ISR_RAC):
30976bd547bSAdrian Chadd                  * If not using ISR_RAC, clear interrupts by writing to ISR_S5.
31076bd547bSAdrian Chadd                  * This avoids a race condition where a new interrupt
31176bd547bSAdrian Chadd                  * could come in between reading the ISR and clearing the
31276bd547bSAdrian Chadd                  * interrupt via the primary ISR.  We therefore clear the
31376bd547bSAdrian Chadd                  * interrupt via the secondary, which avoids this race.
31476bd547bSAdrian Chadd                  */
31576bd547bSAdrian Chadd                 OS_REG_WRITE(ah, AR_ISR_S5, s5);
31676bd547bSAdrian Chadd                 isr &= ~AR_ISR_GENTMR;
31776bd547bSAdrian Chadd             }
31876bd547bSAdrian Chadd         }
31976bd547bSAdrian Chadd 
32076bd547bSAdrian Chadd         *masked |= mask2;
32176bd547bSAdrian Chadd 
322e113789bSAdrian Chadd         if (!p_cap->halIsrRacSupport) {
32376bd547bSAdrian Chadd             /*
32476bd547bSAdrian Chadd              * EV61133 (missing interrupts due to ISR_RAC):
32576bd547bSAdrian Chadd              * If not using ISR_RAC, clear the interrupts we've read by
32676bd547bSAdrian Chadd              * writing back ones in these locations to the primary ISR
32776bd547bSAdrian Chadd              * (except for interrupts that have a secondary isr register -
32876bd547bSAdrian Chadd              * see above).
32976bd547bSAdrian Chadd              */
33076bd547bSAdrian Chadd             OS_REG_WRITE(ah, AR_ISR, isr);
33176bd547bSAdrian Chadd 
33276bd547bSAdrian Chadd             /* Flush prior write */
33376bd547bSAdrian Chadd             (void) OS_REG_READ(ah, AR_ISR);
33476bd547bSAdrian Chadd         }
33576bd547bSAdrian Chadd 
33676bd547bSAdrian Chadd #ifdef AH_SUPPORT_AR9300
33776bd547bSAdrian Chadd         if (*masked & HAL_INT_BBPANIC) {
33876bd547bSAdrian Chadd             ar9300_handle_bb_panic(ah);
33976bd547bSAdrian Chadd         }
34076bd547bSAdrian Chadd #endif
34176bd547bSAdrian Chadd     }
34276bd547bSAdrian Chadd 
34376bd547bSAdrian Chadd     if (async_cause) {
34476bd547bSAdrian Chadd         if (nortc) {
34576bd547bSAdrian Chadd             OS_REG_WRITE(ah,
34676bd547bSAdrian Chadd                 AR_HOSTIF_REG(ah, AR_INTR_ASYNC_CAUSE_CLR), async_cause);
34776bd547bSAdrian Chadd             /* Flush prior write */
34876bd547bSAdrian Chadd             (void) OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_ASYNC_CAUSE_CLR));
34976bd547bSAdrian Chadd         } else {
35076bd547bSAdrian Chadd #ifdef ATH_GPIO_USE_ASYNC_CAUSE
35176bd547bSAdrian Chadd             if (async_cause & AR_INTR_ASYNC_CAUSE_GPIO) {
35276bd547bSAdrian Chadd                 ahp->ah_gpio_cause = (async_cause & AR_INTR_ASYNC_CAUSE_GPIO) >>
35376bd547bSAdrian Chadd                                      AR_INTR_ASYNC_ENABLE_GPIO_S;
35476bd547bSAdrian Chadd                 *masked |= HAL_INT_GPIO;
35576bd547bSAdrian Chadd             }
35676bd547bSAdrian Chadd #endif
35776bd547bSAdrian Chadd         }
35876bd547bSAdrian Chadd 
35976bd547bSAdrian Chadd #if ATH_SUPPORT_MCI
36076bd547bSAdrian Chadd         if ((async_cause & AR_INTR_ASYNC_CAUSE_MCI) &&
361e113789bSAdrian Chadd             p_cap->halMciSupport)
36276bd547bSAdrian Chadd         {
36376bd547bSAdrian Chadd             u_int32_t int_raw, int_rx_msg;
36476bd547bSAdrian Chadd 
36576bd547bSAdrian Chadd             int_rx_msg = OS_REG_READ(ah, AR_MCI_INTERRUPT_RX_MSG_RAW);
36676bd547bSAdrian Chadd             int_raw = OS_REG_READ(ah, AR_MCI_INTERRUPT_RAW);
36776bd547bSAdrian Chadd 
36876bd547bSAdrian Chadd             if ((int_raw == 0xdeadbeef) || (int_rx_msg == 0xdeadbeef))
36976bd547bSAdrian Chadd             {
37076bd547bSAdrian Chadd                 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
37176bd547bSAdrian Chadd                     "(MCI) Get 0xdeadbeef during MCI int processing"
37276bd547bSAdrian Chadd                     "new int_raw=0x%08x, new rx_msg_raw=0x%08x, "
37376bd547bSAdrian Chadd                     "int_raw=0x%08x, rx_msg_raw=0x%08x\n",
37476bd547bSAdrian Chadd                     int_raw, int_rx_msg, ahp->ah_mci_int_raw,
37576bd547bSAdrian Chadd                     ahp->ah_mci_int_rx_msg);
37676bd547bSAdrian Chadd             }
37776bd547bSAdrian Chadd             else {
37876bd547bSAdrian Chadd                 if (ahp->ah_mci_int_raw || ahp->ah_mci_int_rx_msg) {
37976bd547bSAdrian Chadd                     ahp->ah_mci_int_rx_msg |= int_rx_msg;
38076bd547bSAdrian Chadd                     ahp->ah_mci_int_raw |= int_raw;
38176bd547bSAdrian Chadd                 }
38276bd547bSAdrian Chadd                 else {
38376bd547bSAdrian Chadd                     ahp->ah_mci_int_rx_msg = int_rx_msg;
38476bd547bSAdrian Chadd                     ahp->ah_mci_int_raw = int_raw;
38576bd547bSAdrian Chadd                 }
38676bd547bSAdrian Chadd 
38776bd547bSAdrian Chadd                 *masked |= HAL_INT_MCI;
38876bd547bSAdrian Chadd                 ahp->ah_mci_rx_status = OS_REG_READ(ah, AR_MCI_RX_STATUS);
38976bd547bSAdrian Chadd                 if (int_rx_msg & AR_MCI_INTERRUPT_RX_MSG_CONT_INFO) {
39076bd547bSAdrian Chadd                     ahp->ah_mci_cont_status =
39176bd547bSAdrian Chadd                                     OS_REG_READ(ah, AR_MCI_CONT_STATUS);
392*ab3b48eaSAdrian Chadd                     HALDEBUG(ah, HAL_DEBUG_BT_COEX,
393*ab3b48eaSAdrian Chadd                         "(MCI) cont_status=0x%08x\n", ahp->ah_mci_cont_status);
39476bd547bSAdrian Chadd                 }
39576bd547bSAdrian Chadd                 OS_REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW,
39676bd547bSAdrian Chadd                     int_rx_msg);
39776bd547bSAdrian Chadd                 OS_REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, int_raw);
39876bd547bSAdrian Chadd 
39976bd547bSAdrian Chadd                 HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s:AR_INTR_SYNC_MCI\n", __func__);
40076bd547bSAdrian Chadd             }
40176bd547bSAdrian Chadd         }
40276bd547bSAdrian Chadd #endif
40376bd547bSAdrian Chadd     }
40476bd547bSAdrian Chadd 
40576bd547bSAdrian Chadd     if (sync_cause) {
40676bd547bSAdrian Chadd         int host1_fatal, host1_perr, radm_cpl_timeout, local_timeout;
40776bd547bSAdrian Chadd 
40876bd547bSAdrian Chadd         host1_fatal = AR_SREV_WASP(ah) ?
40976bd547bSAdrian Chadd             AR9340_INTR_SYNC_HOST1_FATAL : AR9300_INTR_SYNC_HOST1_FATAL;
41076bd547bSAdrian Chadd         host1_perr = AR_SREV_WASP(ah) ?
41176bd547bSAdrian Chadd             AR9340_INTR_SYNC_HOST1_PERR : AR9300_INTR_SYNC_HOST1_PERR;
41276bd547bSAdrian Chadd         radm_cpl_timeout = AR_SREV_WASP(ah) ?
41376bd547bSAdrian Chadd             0x0 : AR9300_INTR_SYNC_RADM_CPL_TIMEOUT;
41476bd547bSAdrian Chadd         local_timeout = AR_SREV_WASP(ah) ?
41576bd547bSAdrian Chadd             AR9340_INTR_SYNC_LOCAL_TIMEOUT : AR9300_INTR_SYNC_LOCAL_TIMEOUT;
41676bd547bSAdrian Chadd 
41776bd547bSAdrian Chadd         if (sync_cause & host1_fatal) {
41876bd547bSAdrian Chadd #if __PKT_SERIOUS_ERRORS__
41976bd547bSAdrian Chadd             HALDEBUG(ah, HAL_DEBUG_UNMASKABLE,
42076bd547bSAdrian Chadd                 "%s: received PCI FATAL interrupt\n", __func__);
42176bd547bSAdrian Chadd #endif
42276bd547bSAdrian Chadd            *masked |= HAL_INT_FATAL; /* Set FATAL INT flag here;*/
42376bd547bSAdrian Chadd         }
42476bd547bSAdrian Chadd         if (sync_cause & host1_perr) {
42576bd547bSAdrian Chadd #if __PKT_SERIOUS_ERRORS__
42676bd547bSAdrian Chadd             HALDEBUG(ah, HAL_DEBUG_UNMASKABLE,
42776bd547bSAdrian Chadd                 "%s: received PCI PERR interrupt\n", __func__);
42876bd547bSAdrian Chadd #endif
42976bd547bSAdrian Chadd         }
43076bd547bSAdrian Chadd 
43176bd547bSAdrian Chadd         if (sync_cause & radm_cpl_timeout) {
43276bd547bSAdrian Chadd             HALDEBUG(ah, HAL_DEBUG_INTERRUPT,
43376bd547bSAdrian Chadd                 "%s: AR_INTR_SYNC_RADM_CPL_TIMEOUT\n",
43476bd547bSAdrian Chadd                 __func__);
43576bd547bSAdrian Chadd 
43676bd547bSAdrian Chadd             OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_RC), AR_RC_HOSTIF);
43776bd547bSAdrian Chadd             OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_RC), 0);
43876bd547bSAdrian Chadd             *masked |= HAL_INT_FATAL;
43976bd547bSAdrian Chadd         }
44076bd547bSAdrian Chadd         if (sync_cause & local_timeout) {
44176bd547bSAdrian Chadd             HALDEBUG(ah, HAL_DEBUG_INTERRUPT,
44276bd547bSAdrian Chadd                 "%s: AR_INTR_SYNC_LOCAL_TIMEOUT\n",
44376bd547bSAdrian Chadd                 __func__);
44476bd547bSAdrian Chadd         }
44576bd547bSAdrian Chadd 
44676bd547bSAdrian Chadd #ifndef ATH_GPIO_USE_ASYNC_CAUSE
44776bd547bSAdrian Chadd         if (sync_cause & AR_INTR_SYNC_MASK_GPIO) {
44876bd547bSAdrian Chadd             ahp->ah_gpio_cause = (sync_cause & AR_INTR_SYNC_MASK_GPIO) >>
44976bd547bSAdrian Chadd                                  AR_INTR_SYNC_ENABLE_GPIO_S;
45076bd547bSAdrian Chadd             *masked |= HAL_INT_GPIO;
45176bd547bSAdrian Chadd             HALDEBUG(ah, HAL_DEBUG_INTERRUPT,
45276bd547bSAdrian Chadd                 "%s: AR_INTR_SYNC_GPIO\n", __func__);
45376bd547bSAdrian Chadd         }
45476bd547bSAdrian Chadd #endif
45576bd547bSAdrian Chadd 
45676bd547bSAdrian Chadd         OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_CAUSE_CLR), sync_cause);
45776bd547bSAdrian Chadd         /* Flush prior write */
45876bd547bSAdrian Chadd         (void) OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_CAUSE_CLR));
45976bd547bSAdrian Chadd     }
46076bd547bSAdrian Chadd 
46176bd547bSAdrian Chadd end:
46276bd547bSAdrian Chadd     if (HAL_INT_MSI == type) {
46376bd547bSAdrian Chadd         /*
46476bd547bSAdrian Chadd          * WAR for Bug EV#75887
46576bd547bSAdrian Chadd          * In normal case, SW read HOST_INTF_PCIE_MSI (0x40A4) and write
46676bd547bSAdrian Chadd          * into ah_msi_reg.  Then use value of ah_msi_reg to set bit#25
46776bd547bSAdrian Chadd          * when want to enable HW write the cfg_msi_pending.
46876bd547bSAdrian Chadd          * Sometimes, driver get MSI interrupt before read 0x40a4 and
46976bd547bSAdrian Chadd          * ah_msi_reg is initialization value (0x0).
47076bd547bSAdrian Chadd          * We don't know why "MSI interrupt earlier than driver read" now...
47176bd547bSAdrian Chadd          */
47276bd547bSAdrian Chadd         if (!ahp->ah_msi_reg) {
47376bd547bSAdrian Chadd             ahp->ah_msi_reg = OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_PCIE_MSI));
47476bd547bSAdrian Chadd         }
47576bd547bSAdrian Chadd         if (AR_SREV_POSEIDON(ah)) {
47676bd547bSAdrian Chadd             msi_pend_addr_mask = AR_PCIE_MSI_HW_INT_PENDING_ADDR_MSI_64;
47776bd547bSAdrian Chadd         } else {
47876bd547bSAdrian Chadd             msi_pend_addr_mask = AR_PCIE_MSI_HW_INT_PENDING_ADDR;
47976bd547bSAdrian Chadd         }
48076bd547bSAdrian Chadd         OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_PCIE_MSI),
48176bd547bSAdrian Chadd             ((ahp->ah_msi_reg | AR_PCIE_MSI_ENABLE) & msi_pend_addr_mask));
48276bd547bSAdrian Chadd 
48376bd547bSAdrian Chadd     }
48476bd547bSAdrian Chadd 
48576bd547bSAdrian Chadd     return ret_val;
48676bd547bSAdrian Chadd }
48776bd547bSAdrian Chadd 
48876bd547bSAdrian Chadd HAL_INT
ar9300_get_interrupts(struct ath_hal * ah)48976bd547bSAdrian Chadd ar9300_get_interrupts(struct ath_hal *ah)
49076bd547bSAdrian Chadd {
49176bd547bSAdrian Chadd     return AH9300(ah)->ah_mask_reg;
49276bd547bSAdrian Chadd }
49376bd547bSAdrian Chadd 
49476bd547bSAdrian Chadd /*
49576bd547bSAdrian Chadd  * Atomically enables NIC interrupts.  Interrupts are passed in
49676bd547bSAdrian Chadd  * via the enumerated bitmask in ints.
49776bd547bSAdrian Chadd  */
49876bd547bSAdrian Chadd HAL_INT
ar9300_set_interrupts(struct ath_hal * ah,HAL_INT ints,HAL_BOOL nortc)49976bd547bSAdrian Chadd ar9300_set_interrupts(struct ath_hal *ah, HAL_INT ints, HAL_BOOL nortc)
50076bd547bSAdrian Chadd {
50176bd547bSAdrian Chadd     struct ath_hal_9300 *ahp = AH9300(ah);
50276bd547bSAdrian Chadd     u_int32_t omask = ahp->ah_mask_reg;
50376bd547bSAdrian Chadd     u_int32_t mask, mask2, msi_mask = 0;
50476bd547bSAdrian Chadd     u_int32_t msi_pend_addr_mask = 0;
50576bd547bSAdrian Chadd     u_int32_t sync_en_def = AR9300_INTR_SYNC_DEFAULT;
50676bd547bSAdrian Chadd     HAL_CAPABILITIES *p_cap = &AH_PRIVATE(ah)->ah_caps;
50776bd547bSAdrian Chadd 
50876bd547bSAdrian Chadd     HALDEBUG(ah, HAL_DEBUG_INTERRUPT,
50976bd547bSAdrian Chadd         "%s: 0x%x => 0x%x\n", __func__, omask, ints);
51076bd547bSAdrian Chadd 
51176bd547bSAdrian Chadd     if (omask & HAL_INT_GLOBAL) {
51276bd547bSAdrian Chadd         HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: disable IER\n", __func__);
51376bd547bSAdrian Chadd 
514e113789bSAdrian Chadd         if (ah->ah_config.ath_hal_enable_msi) {
51576bd547bSAdrian Chadd             OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_INTR_PRIO_ASYNC_ENABLE), 0);
51676bd547bSAdrian Chadd             /* flush write to HW */
51776bd547bSAdrian Chadd             (void)OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_PRIO_ASYNC_ENABLE));
51876bd547bSAdrian Chadd         }
51976bd547bSAdrian Chadd 
52076bd547bSAdrian Chadd         if (!nortc) {
52176bd547bSAdrian Chadd             OS_REG_WRITE(ah, AR_IER, AR_IER_DISABLE);
52276bd547bSAdrian Chadd             (void) OS_REG_READ(ah, AR_IER);   /* flush write to HW */
52376bd547bSAdrian Chadd         }
52476bd547bSAdrian Chadd 
52576bd547bSAdrian Chadd         OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_ENABLE), 0);
52676bd547bSAdrian Chadd         /* flush write to HW */
52776bd547bSAdrian Chadd         (void) OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_ENABLE));
52876bd547bSAdrian Chadd         OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_INTR_ASYNC_ENABLE), 0);
52976bd547bSAdrian Chadd         /* flush write to HW */
53076bd547bSAdrian Chadd         (void) OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_ASYNC_ENABLE));
53176bd547bSAdrian Chadd     }
53276bd547bSAdrian Chadd 
53376bd547bSAdrian Chadd     if (!nortc) {
53476bd547bSAdrian Chadd         /* reference count for global IER */
53576bd547bSAdrian Chadd         if (ints & HAL_INT_GLOBAL) {
53676bd547bSAdrian Chadd #ifdef AH_DEBUG
53776bd547bSAdrian Chadd             HALDEBUG(ah, HAL_DEBUG_INTERRUPT,
53876bd547bSAdrian Chadd                 "%s: Request HAL_INT_GLOBAL ENABLED\n", __func__);
539e113789bSAdrian Chadd #if 0
54076bd547bSAdrian Chadd             if (OS_ATOMIC_READ(&ahp->ah_ier_ref_count) == 0) {
54176bd547bSAdrian Chadd                 HALDEBUG(ah, HAL_DEBUG_UNMASKABLE,
54276bd547bSAdrian Chadd                     "%s: WARNING: ah_ier_ref_count is 0 "
54376bd547bSAdrian Chadd                     "and attempting to enable IER\n",
54476bd547bSAdrian Chadd                     __func__);
54576bd547bSAdrian Chadd             }
54676bd547bSAdrian Chadd #endif
547e113789bSAdrian Chadd #endif
548e113789bSAdrian Chadd #if 0
54976bd547bSAdrian Chadd             if (OS_ATOMIC_READ(&ahp->ah_ier_ref_count) > 0) {
55076bd547bSAdrian Chadd                 OS_ATOMIC_DEC(&ahp->ah_ier_ref_count);
55176bd547bSAdrian Chadd             }
552e113789bSAdrian Chadd #endif
55376bd547bSAdrian Chadd         } else {
55476bd547bSAdrian Chadd             HALDEBUG(ah, HAL_DEBUG_INTERRUPT,
55576bd547bSAdrian Chadd                 "%s: Request HAL_INT_GLOBAL DISABLED\n", __func__);
55676bd547bSAdrian Chadd             OS_ATOMIC_INC(&ahp->ah_ier_ref_count);
55776bd547bSAdrian Chadd         }
55876bd547bSAdrian Chadd         HALDEBUG(ah, HAL_DEBUG_INTERRUPT,
55976bd547bSAdrian Chadd             "%s: ah_ier_ref_count = %d\n", __func__, ahp->ah_ier_ref_count);
56076bd547bSAdrian Chadd 
56176bd547bSAdrian Chadd         mask = ints & HAL_INT_COMMON;
56276bd547bSAdrian Chadd         mask2 = 0;
56376bd547bSAdrian Chadd         msi_mask = 0;
56476bd547bSAdrian Chadd 
56576bd547bSAdrian Chadd         if (ints & HAL_INT_TX) {
56676bd547bSAdrian Chadd             if (ahp->ah_intr_mitigation_tx) {
56776bd547bSAdrian Chadd                 mask |= AR_IMR_TXMINTR | AR_IMR_TXINTM;
56876bd547bSAdrian Chadd             } else if (ahp->ah_tx_ok_interrupt_mask) {
56976bd547bSAdrian Chadd                 mask |= AR_IMR_TXOK;
57076bd547bSAdrian Chadd             }
57176bd547bSAdrian Chadd             msi_mask |= AR_INTR_PRIO_TX;
57276bd547bSAdrian Chadd             if (ahp->ah_tx_err_interrupt_mask) {
57376bd547bSAdrian Chadd                 mask |= AR_IMR_TXERR;
57476bd547bSAdrian Chadd             }
57576bd547bSAdrian Chadd             if (ahp->ah_tx_eol_interrupt_mask) {
57676bd547bSAdrian Chadd                 mask |= AR_IMR_TXEOL;
57776bd547bSAdrian Chadd             }
57876bd547bSAdrian Chadd         }
57976bd547bSAdrian Chadd         if (ints & HAL_INT_RX) {
58076bd547bSAdrian Chadd             mask |= AR_IMR_RXERR | AR_IMR_RXOK_HP;
58176bd547bSAdrian Chadd             if (ahp->ah_intr_mitigation_rx) {
58276bd547bSAdrian Chadd                 mask &= ~(AR_IMR_RXOK_LP);
58376bd547bSAdrian Chadd                 mask |=  AR_IMR_RXMINTR | AR_IMR_RXINTM;
58476bd547bSAdrian Chadd             } else {
58576bd547bSAdrian Chadd                 mask |= AR_IMR_RXOK_LP;
58676bd547bSAdrian Chadd             }
58776bd547bSAdrian Chadd             msi_mask |= AR_INTR_PRIO_RXLP | AR_INTR_PRIO_RXHP;
588e113789bSAdrian Chadd             if (! p_cap->halAutoSleepSupport) {
58976bd547bSAdrian Chadd                 mask |= AR_IMR_GENTMR;
59076bd547bSAdrian Chadd             }
59176bd547bSAdrian Chadd         }
59276bd547bSAdrian Chadd 
59376bd547bSAdrian Chadd         if (ints & (HAL_INT_BMISC)) {
59476bd547bSAdrian Chadd             mask |= AR_IMR_BCNMISC;
59576bd547bSAdrian Chadd             if (ints & HAL_INT_TIM) {
59676bd547bSAdrian Chadd                 mask2 |= AR_IMR_S2_TIM;
59776bd547bSAdrian Chadd             }
59876bd547bSAdrian Chadd             if (ints & HAL_INT_DTIM) {
59976bd547bSAdrian Chadd                 mask2 |= AR_IMR_S2_DTIM;
60076bd547bSAdrian Chadd             }
60176bd547bSAdrian Chadd             if (ints & HAL_INT_DTIMSYNC) {
60276bd547bSAdrian Chadd                 mask2 |= AR_IMR_S2_DTIMSYNC;
60376bd547bSAdrian Chadd             }
60476bd547bSAdrian Chadd             if (ints & HAL_INT_CABEND) {
60576bd547bSAdrian Chadd                 mask2 |= (AR_IMR_S2_CABEND);
60676bd547bSAdrian Chadd             }
60776bd547bSAdrian Chadd             if (ints & HAL_INT_TSFOOR) {
60876bd547bSAdrian Chadd                 mask2 |= AR_IMR_S2_TSFOOR;
60976bd547bSAdrian Chadd             }
61076bd547bSAdrian Chadd         }
61176bd547bSAdrian Chadd 
61276bd547bSAdrian Chadd         if (ints & (HAL_INT_GTT | HAL_INT_CST)) {
61376bd547bSAdrian Chadd             mask |= AR_IMR_BCNMISC;
61476bd547bSAdrian Chadd             if (ints & HAL_INT_GTT) {
61576bd547bSAdrian Chadd                 mask2 |= AR_IMR_S2_GTT;
61676bd547bSAdrian Chadd             }
61776bd547bSAdrian Chadd             if (ints & HAL_INT_CST) {
61876bd547bSAdrian Chadd                 mask2 |= AR_IMR_S2_CST;
61976bd547bSAdrian Chadd             }
62076bd547bSAdrian Chadd         }
62176bd547bSAdrian Chadd 
62276bd547bSAdrian Chadd         if (ints & HAL_INT_BBPANIC) {
62376bd547bSAdrian Chadd             /* EV92527 - MAC secondary interrupt must enable AR_IMR_BCNMISC */
62476bd547bSAdrian Chadd             mask |= AR_IMR_BCNMISC;
62576bd547bSAdrian Chadd             mask2 |= AR_IMR_S2_BBPANIC;
62676bd547bSAdrian Chadd         }
62776bd547bSAdrian Chadd 
62876bd547bSAdrian Chadd         if (ints & HAL_INT_GENTIMER) {
62976bd547bSAdrian Chadd             HALDEBUG(ah, HAL_DEBUG_INTERRUPT,
63076bd547bSAdrian Chadd                 "%s: enabling gen timer\n", __func__);
63176bd547bSAdrian Chadd             mask |= AR_IMR_GENTMR;
63276bd547bSAdrian Chadd         }
63376bd547bSAdrian Chadd 
63476bd547bSAdrian Chadd         /* Write the new IMR and store off our SW copy. */
63576bd547bSAdrian Chadd         HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: new IMR 0x%x\n", __func__, mask);
63676bd547bSAdrian Chadd         OS_REG_WRITE(ah, AR_IMR, mask);
63776bd547bSAdrian Chadd         ahp->ah_mask2Reg &= ~(AR_IMR_S2_TIM |
63876bd547bSAdrian Chadd                         AR_IMR_S2_DTIM |
63976bd547bSAdrian Chadd                         AR_IMR_S2_DTIMSYNC |
64076bd547bSAdrian Chadd                         AR_IMR_S2_CABEND |
64176bd547bSAdrian Chadd                         AR_IMR_S2_CABTO  |
64276bd547bSAdrian Chadd                         AR_IMR_S2_TSFOOR |
64376bd547bSAdrian Chadd                         AR_IMR_S2_GTT |
64476bd547bSAdrian Chadd                         AR_IMR_S2_CST |
64576bd547bSAdrian Chadd                         AR_IMR_S2_BBPANIC);
64676bd547bSAdrian Chadd         ahp->ah_mask2Reg |= mask2;
64776bd547bSAdrian Chadd         OS_REG_WRITE(ah, AR_IMR_S2, ahp->ah_mask2Reg );
64876bd547bSAdrian Chadd         ahp->ah_mask_reg = ints;
64976bd547bSAdrian Chadd 
650e113789bSAdrian Chadd         if (! p_cap->halAutoSleepSupport) {
65176bd547bSAdrian Chadd             if (ints & HAL_INT_TIM_TIMER) {
65276bd547bSAdrian Chadd                 OS_REG_SET_BIT(ah, AR_IMR_S5, AR_IMR_S5_TIM_TIMER);
65376bd547bSAdrian Chadd             }
65476bd547bSAdrian Chadd             else {
65576bd547bSAdrian Chadd                 OS_REG_CLR_BIT(ah, AR_IMR_S5, AR_IMR_S5_TIM_TIMER);
65676bd547bSAdrian Chadd             }
65776bd547bSAdrian Chadd         }
65876bd547bSAdrian Chadd     }
65976bd547bSAdrian Chadd 
66076bd547bSAdrian Chadd     /* Re-enable interrupts if they were enabled before. */
66176bd547bSAdrian Chadd #if HAL_INTR_REFCOUNT_DISABLE
66276bd547bSAdrian Chadd     if ((ints & HAL_INT_GLOBAL)) {
66376bd547bSAdrian Chadd #else
66476bd547bSAdrian Chadd     if ((ints & HAL_INT_GLOBAL) && (OS_ATOMIC_READ(&ahp->ah_ier_ref_count) == 0)) {
66576bd547bSAdrian Chadd #endif
66676bd547bSAdrian Chadd         HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: enable IER\n", __func__);
66776bd547bSAdrian Chadd 
66876bd547bSAdrian Chadd         if (!nortc) {
66976bd547bSAdrian Chadd             OS_REG_WRITE(ah, AR_IER, AR_IER_ENABLE);
67076bd547bSAdrian Chadd         }
67176bd547bSAdrian Chadd 
67276bd547bSAdrian Chadd         mask = AR_INTR_MAC_IRQ;
67376bd547bSAdrian Chadd #ifdef ATH_GPIO_USE_ASYNC_CAUSE
67476bd547bSAdrian Chadd         if (ints & HAL_INT_GPIO) {
67576bd547bSAdrian Chadd             if (ahp->ah_gpio_mask) {
67676bd547bSAdrian Chadd                 mask |= SM(ahp->ah_gpio_mask, AR_INTR_ASYNC_MASK_GPIO);
67776bd547bSAdrian Chadd             }
67876bd547bSAdrian Chadd         }
67976bd547bSAdrian Chadd #endif
68076bd547bSAdrian Chadd 
68176bd547bSAdrian Chadd #if ATH_SUPPORT_MCI
68276bd547bSAdrian Chadd         if (ints & HAL_INT_MCI) {
68376bd547bSAdrian Chadd             mask |= AR_INTR_ASYNC_MASK_MCI;
68476bd547bSAdrian Chadd         }
68576bd547bSAdrian Chadd #endif
68676bd547bSAdrian Chadd 
68776bd547bSAdrian Chadd         OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_INTR_ASYNC_ENABLE), mask);
68876bd547bSAdrian Chadd         OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_INTR_ASYNC_MASK), mask);
68976bd547bSAdrian Chadd 
690e113789bSAdrian Chadd         if (ah->ah_config.ath_hal_enable_msi) {
69176bd547bSAdrian Chadd             OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_INTR_PRIO_ASYNC_ENABLE),
69276bd547bSAdrian Chadd                 msi_mask);
69376bd547bSAdrian Chadd             OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_INTR_PRIO_ASYNC_MASK),
69476bd547bSAdrian Chadd                 msi_mask);
69576bd547bSAdrian Chadd             if (AR_SREV_POSEIDON(ah)) {
69676bd547bSAdrian Chadd                 msi_pend_addr_mask = AR_PCIE_MSI_HW_INT_PENDING_ADDR_MSI_64;
69776bd547bSAdrian Chadd             } else {
69876bd547bSAdrian Chadd                 msi_pend_addr_mask = AR_PCIE_MSI_HW_INT_PENDING_ADDR;
69976bd547bSAdrian Chadd             }
70076bd547bSAdrian Chadd             OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_PCIE_MSI),
70176bd547bSAdrian Chadd                 ((ahp->ah_msi_reg | AR_PCIE_MSI_ENABLE) & msi_pend_addr_mask));
70276bd547bSAdrian Chadd         }
70376bd547bSAdrian Chadd 
70476bd547bSAdrian Chadd         /*
70576bd547bSAdrian Chadd          * debug - enable to see all synchronous interrupts status
70676bd547bSAdrian Chadd          * Enable synchronous GPIO interrupts as well, since some async
70776bd547bSAdrian Chadd          * GPIO interrupts don't wake the chip up.
70876bd547bSAdrian Chadd          */
70976bd547bSAdrian Chadd         mask = 0;
71076bd547bSAdrian Chadd #ifndef ATH_GPIO_USE_ASYNC_CAUSE
71176bd547bSAdrian Chadd         if (ints & HAL_INT_GPIO) {
71276bd547bSAdrian Chadd             mask |= SM(ahp->ah_gpio_mask, AR_INTR_SYNC_MASK_GPIO);
71376bd547bSAdrian Chadd         }
71476bd547bSAdrian Chadd #endif
71576bd547bSAdrian Chadd         if (AR_SREV_POSEIDON(ah)) {
71676bd547bSAdrian Chadd             sync_en_def = AR9300_INTR_SYNC_DEF_NO_HOST1_PERR;
71776bd547bSAdrian Chadd         }
71876bd547bSAdrian Chadd         else if (AR_SREV_WASP(ah)) {
71976bd547bSAdrian Chadd             sync_en_def = AR9340_INTR_SYNC_DEFAULT;
72076bd547bSAdrian Chadd         }
72176bd547bSAdrian Chadd 
72276bd547bSAdrian Chadd         OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_ENABLE),
72376bd547bSAdrian Chadd             (sync_en_def | mask));
72476bd547bSAdrian Chadd         OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_MASK),
72576bd547bSAdrian Chadd             (sync_en_def | mask));
72676bd547bSAdrian Chadd 
72776bd547bSAdrian Chadd         HALDEBUG(ah,  HAL_DEBUG_INTERRUPT,
72876bd547bSAdrian Chadd             "AR_IMR 0x%x IER 0x%x\n",
72976bd547bSAdrian Chadd             OS_REG_READ(ah, AR_IMR), OS_REG_READ(ah, AR_IER));
73076bd547bSAdrian Chadd     }
73176bd547bSAdrian Chadd 
73276bd547bSAdrian Chadd     return omask;
73376bd547bSAdrian Chadd }
73476bd547bSAdrian Chadd 
73576bd547bSAdrian Chadd void
73676bd547bSAdrian Chadd ar9300_set_intr_mitigation_timer(
73776bd547bSAdrian Chadd     struct ath_hal* ah,
73876bd547bSAdrian Chadd     HAL_INT_MITIGATION reg,
73976bd547bSAdrian Chadd     u_int32_t value)
74076bd547bSAdrian Chadd {
74176bd547bSAdrian Chadd #ifdef AR5416_INT_MITIGATION
74276bd547bSAdrian Chadd     switch (reg) {
74376bd547bSAdrian Chadd     case HAL_INT_THRESHOLD:
74476bd547bSAdrian Chadd         OS_REG_WRITE(ah, AR_MIRT, 0);
74576bd547bSAdrian Chadd         break;
74676bd547bSAdrian Chadd     case HAL_INT_RX_LASTPKT:
74776bd547bSAdrian Chadd         OS_REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_LAST, value);
74876bd547bSAdrian Chadd         break;
74976bd547bSAdrian Chadd     case HAL_INT_RX_FIRSTPKT:
75076bd547bSAdrian Chadd         OS_REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_FIRST, value);
75176bd547bSAdrian Chadd         break;
75276bd547bSAdrian Chadd     case HAL_INT_TX_LASTPKT:
75376bd547bSAdrian Chadd         OS_REG_RMW_FIELD(ah, AR_TIMT, AR_TIMT_LAST, value);
75476bd547bSAdrian Chadd         break;
75576bd547bSAdrian Chadd     case HAL_INT_TX_FIRSTPKT:
75676bd547bSAdrian Chadd         OS_REG_RMW_FIELD(ah, AR_TIMT, AR_TIMT_FIRST, value);
75776bd547bSAdrian Chadd         break;
75876bd547bSAdrian Chadd     default:
75976bd547bSAdrian Chadd         break;
76076bd547bSAdrian Chadd     }
76176bd547bSAdrian Chadd #endif
76276bd547bSAdrian Chadd }
76376bd547bSAdrian Chadd 
76476bd547bSAdrian Chadd u_int32_t
76576bd547bSAdrian Chadd ar9300_get_intr_mitigation_timer(struct ath_hal* ah, HAL_INT_MITIGATION reg)
76676bd547bSAdrian Chadd {
76776bd547bSAdrian Chadd     u_int32_t val = 0;
76876bd547bSAdrian Chadd #ifdef AR5416_INT_MITIGATION
76976bd547bSAdrian Chadd     switch (reg) {
77076bd547bSAdrian Chadd     case HAL_INT_THRESHOLD:
77176bd547bSAdrian Chadd         val = OS_REG_READ(ah, AR_MIRT);
77276bd547bSAdrian Chadd         break;
77376bd547bSAdrian Chadd     case HAL_INT_RX_LASTPKT:
77476bd547bSAdrian Chadd         val = OS_REG_READ(ah, AR_RIMT) & 0xFFFF;
77576bd547bSAdrian Chadd         break;
77676bd547bSAdrian Chadd     case HAL_INT_RX_FIRSTPKT:
77776bd547bSAdrian Chadd         val = OS_REG_READ(ah, AR_RIMT) >> 16;
77876bd547bSAdrian Chadd         break;
77976bd547bSAdrian Chadd     case HAL_INT_TX_LASTPKT:
78076bd547bSAdrian Chadd         val = OS_REG_READ(ah, AR_TIMT) & 0xFFFF;
78176bd547bSAdrian Chadd         break;
78276bd547bSAdrian Chadd     case HAL_INT_TX_FIRSTPKT:
78376bd547bSAdrian Chadd         val = OS_REG_READ(ah, AR_TIMT) >> 16;
78476bd547bSAdrian Chadd         break;
78576bd547bSAdrian Chadd     default:
78676bd547bSAdrian Chadd         break;
78776bd547bSAdrian Chadd     }
78876bd547bSAdrian Chadd #endif
78976bd547bSAdrian Chadd     return val;
79076bd547bSAdrian Chadd }
791