1 1.1 alc /* 2 1.1 alc * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting 3 1.1 alc * Copyright (c) 2002-2008 Atheros Communications, Inc. 4 1.1 alc * 5 1.1 alc * Permission to use, copy, modify, and/or distribute this software for any 6 1.1 alc * purpose with or without fee is hereby granted, provided that the above 7 1.1 alc * copyright notice and this permission notice appear in all copies. 8 1.1 alc * 9 1.1 alc * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 1.1 alc * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 1.1 alc * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 1.1 alc * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 1.1 alc * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 1.1 alc * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 1.1 alc * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 1.1 alc * 17 1.2 cegger * $Id: ar5212_interrupts.c,v 1.2 2011/03/07 11:25:43 cegger Exp $ 18 1.1 alc */ 19 1.1 alc #include "opt_ah.h" 20 1.1 alc 21 1.1 alc #include "ah.h" 22 1.1 alc #include "ah_internal.h" 23 1.1 alc 24 1.1 alc #include "ar5212/ar5212.h" 25 1.1 alc #include "ar5212/ar5212reg.h" 26 1.1 alc #include "ar5212/ar5212phy.h" 27 1.1 alc 28 1.1 alc 29 1.1 alc /* 30 1.1 alc * Checks to see if an interrupt is pending on our NIC 31 1.1 alc * 32 1.1 alc * Returns: TRUE if an interrupt is pending 33 1.1 alc * FALSE if not 34 1.1 alc */ 35 1.1 alc HAL_BOOL 36 1.1 alc ar5212IsInterruptPending(struct ath_hal *ah) 37 1.1 alc { 38 1.1 alc /* 39 1.1 alc * Some platforms trigger our ISR before applying power to 40 1.1 alc * the card, so make sure the INTPEND is really 1, not 0xffffffff. 41 1.1 alc */ 42 1.1 alc return (OS_REG_READ(ah, AR_INTPEND) == AR_INTPEND_TRUE); 43 1.1 alc } 44 1.1 alc 45 1.1 alc /* 46 1.1 alc * Reads the Interrupt Status Register value from the NIC, thus deasserting 47 1.1 alc * the interrupt line, and returns both the masked and unmasked mapped ISR 48 1.1 alc * values. The value returned is mapped to abstract the hw-specific bit 49 1.1 alc * locations in the Interrupt Status Register. 50 1.1 alc * 51 1.1 alc * Returns: A hardware-abstracted bitmap of all non-masked-out 52 1.1 alc * interrupts pending, as well as an unmasked value 53 1.1 alc */ 54 1.1 alc HAL_BOOL 55 1.1 alc ar5212GetPendingInterrupts(struct ath_hal *ah, HAL_INT *masked) 56 1.1 alc { 57 1.1 alc uint32_t isr, isr0, isr1; 58 1.2 cegger uint32_t mask2; 59 1.1 alc struct ath_hal_5212 *ahp = AH5212(ah); 60 1.1 alc 61 1.1 alc isr = OS_REG_READ(ah, AR_ISR); 62 1.2 cegger mask2 = 0; 63 1.1 alc if (isr & AR_ISR_BCNMISC) { 64 1.1 alc uint32_t isr2; 65 1.1 alc isr2 = OS_REG_READ(ah, AR_ISR_S2); 66 1.1 alc if (isr2 & AR_ISR_S2_TIM) 67 1.1 alc mask2 |= HAL_INT_TIM; 68 1.1 alc if (isr2 & AR_ISR_S2_DTIM) 69 1.1 alc mask2 |= HAL_INT_DTIM; 70 1.1 alc if (isr2 & AR_ISR_S2_DTIMSYNC) 71 1.1 alc mask2 |= HAL_INT_DTIMSYNC; 72 1.2 cegger if (isr2 & AR_ISR_S2_CABEND) 73 1.1 alc mask2 |= HAL_INT_CABEND; 74 1.2 cegger if (isr2 & AR_ISR_S2_TBTT) 75 1.2 cegger mask2 |= HAL_INT_TBTT; 76 1.1 alc } 77 1.1 alc isr = OS_REG_READ(ah, AR_ISR_RAC); 78 1.1 alc if (isr == 0xffffffff) { 79 1.1 alc *masked = 0; 80 1.2 cegger return AH_FALSE; 81 1.1 alc } 82 1.1 alc 83 1.1 alc *masked = isr & HAL_INT_COMMON; 84 1.1 alc 85 1.1 alc if (isr & AR_ISR_HIUERR) 86 1.1 alc *masked |= HAL_INT_FATAL; 87 1.1 alc if (isr & (AR_ISR_RXOK | AR_ISR_RXERR)) 88 1.1 alc *masked |= HAL_INT_RX; 89 1.1 alc if (isr & (AR_ISR_TXOK | AR_ISR_TXDESC | AR_ISR_TXERR | AR_ISR_TXEOL)) { 90 1.1 alc *masked |= HAL_INT_TX; 91 1.1 alc isr0 = OS_REG_READ(ah, AR_ISR_S0_S); 92 1.1 alc ahp->ah_intrTxqs |= MS(isr0, AR_ISR_S0_QCU_TXOK); 93 1.1 alc ahp->ah_intrTxqs |= MS(isr0, AR_ISR_S0_QCU_TXDESC); 94 1.1 alc isr1 = OS_REG_READ(ah, AR_ISR_S1_S); 95 1.1 alc ahp->ah_intrTxqs |= MS(isr1, AR_ISR_S1_QCU_TXERR); 96 1.1 alc ahp->ah_intrTxqs |= MS(isr1, AR_ISR_S1_QCU_TXEOL); 97 1.1 alc } 98 1.1 alc 99 1.1 alc /* 100 1.1 alc * Receive overrun is usually non-fatal on Oahu/Spirit. 101 1.1 alc * BUT on some parts rx could fail and the chip must be reset. 102 1.1 alc * So we force a hardware reset in all cases. 103 1.1 alc */ 104 1.1 alc if ((isr & AR_ISR_RXORN) && AH_PRIVATE(ah)->ah_rxornIsFatal) { 105 1.1 alc HALDEBUG(ah, HAL_DEBUG_ANY, 106 1.1 alc "%s: receive FIFO overrun interrupt\n", __func__); 107 1.1 alc *masked |= HAL_INT_FATAL; 108 1.1 alc } 109 1.1 alc *masked |= mask2; 110 1.1 alc 111 1.1 alc /* 112 1.1 alc * On fatal errors collect ISR state for debugging. 113 1.1 alc */ 114 1.1 alc if (*masked & HAL_INT_FATAL) { 115 1.1 alc AH_PRIVATE(ah)->ah_fatalState[0] = isr; 116 1.1 alc AH_PRIVATE(ah)->ah_fatalState[1] = OS_REG_READ(ah, AR_ISR_S0_S); 117 1.1 alc AH_PRIVATE(ah)->ah_fatalState[2] = OS_REG_READ(ah, AR_ISR_S1_S); 118 1.1 alc AH_PRIVATE(ah)->ah_fatalState[3] = OS_REG_READ(ah, AR_ISR_S2_S); 119 1.1 alc AH_PRIVATE(ah)->ah_fatalState[4] = OS_REG_READ(ah, AR_ISR_S3_S); 120 1.1 alc AH_PRIVATE(ah)->ah_fatalState[5] = OS_REG_READ(ah, AR_ISR_S4_S); 121 1.1 alc HALDEBUG(ah, HAL_DEBUG_ANY, 122 1.1 alc "%s: fatal error, ISR_RAC=0x%x ISR_S2_S=0x%x\n", 123 1.1 alc __func__, isr, AH_PRIVATE(ah)->ah_fatalState[3]); 124 1.1 alc } 125 1.1 alc return AH_TRUE; 126 1.1 alc } 127 1.1 alc 128 1.1 alc HAL_INT 129 1.1 alc ar5212GetInterrupts(struct ath_hal *ah) 130 1.1 alc { 131 1.1 alc return AH5212(ah)->ah_maskReg; 132 1.1 alc } 133 1.1 alc 134 1.1 alc /* 135 1.1 alc * Atomically enables NIC interrupts. Interrupts are passed in 136 1.1 alc * via the enumerated bitmask in ints. 137 1.1 alc */ 138 1.1 alc HAL_INT 139 1.1 alc ar5212SetInterrupts(struct ath_hal *ah, HAL_INT ints) 140 1.1 alc { 141 1.1 alc struct ath_hal_5212 *ahp = AH5212(ah); 142 1.1 alc uint32_t omask = ahp->ah_maskReg; 143 1.2 cegger uint32_t mask, mask2; 144 1.1 alc 145 1.1 alc HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: 0x%x => 0x%x\n", 146 1.1 alc __func__, omask, ints); 147 1.1 alc 148 1.1 alc if (omask & HAL_INT_GLOBAL) { 149 1.1 alc HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: disable IER\n", __func__); 150 1.1 alc OS_REG_WRITE(ah, AR_IER, AR_IER_DISABLE); 151 1.1 alc (void) OS_REG_READ(ah, AR_IER); /* flush write to HW */ 152 1.1 alc } 153 1.1 alc 154 1.1 alc mask = ints & HAL_INT_COMMON; 155 1.1 alc mask2 = 0; 156 1.1 alc if (ints & HAL_INT_TX) { 157 1.1 alc if (ahp->ah_txOkInterruptMask) 158 1.1 alc mask |= AR_IMR_TXOK; 159 1.1 alc if (ahp->ah_txErrInterruptMask) 160 1.1 alc mask |= AR_IMR_TXERR; 161 1.1 alc if (ahp->ah_txDescInterruptMask) 162 1.1 alc mask |= AR_IMR_TXDESC; 163 1.1 alc if (ahp->ah_txEolInterruptMask) 164 1.1 alc mask |= AR_IMR_TXEOL; 165 1.1 alc } 166 1.1 alc if (ints & HAL_INT_RX) 167 1.1 alc mask |= AR_IMR_RXOK | AR_IMR_RXERR | AR_IMR_RXDESC; 168 1.1 alc if (ints & (HAL_INT_BMISC)) { 169 1.1 alc mask |= AR_IMR_BCNMISC; 170 1.1 alc if (ints & HAL_INT_TIM) 171 1.1 alc mask2 |= AR_IMR_S2_TIM; 172 1.1 alc if (ints & HAL_INT_DTIM) 173 1.1 alc mask2 |= AR_IMR_S2_DTIM; 174 1.1 alc if (ints & HAL_INT_DTIMSYNC) 175 1.1 alc mask2 |= AR_IMR_S2_DTIMSYNC; 176 1.1 alc if (ints & HAL_INT_CABEND) 177 1.2 cegger mask2 |= AR_IMR_S2_CABEND; 178 1.2 cegger if (ints & HAL_INT_TBTT) 179 1.2 cegger mask2 |= AR_IMR_S2_TBTT; 180 1.1 alc } 181 1.1 alc if (ints & HAL_INT_FATAL) { 182 1.1 alc /* 183 1.1 alc * NB: ar5212Reset sets MCABT+SSERR+DPERR in AR_IMR_S2 184 1.1 alc * so enabling HIUERR enables delivery. 185 1.1 alc */ 186 1.1 alc mask |= AR_IMR_HIUERR; 187 1.1 alc } 188 1.1 alc 189 1.1 alc /* Write the new IMR and store off our SW copy. */ 190 1.1 alc HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: new IMR 0x%x\n", __func__, mask); 191 1.1 alc OS_REG_WRITE(ah, AR_IMR, mask); 192 1.2 cegger OS_REG_WRITE(ah, AR_IMR_S2, 193 1.2 cegger (OS_REG_READ(ah, AR_IMR_S2) & ~AR_IMR_SR2_BCNMISC) | mask2); 194 1.1 alc ahp->ah_maskReg = ints; 195 1.1 alc 196 1.1 alc /* Re-enable interrupts if they were enabled before. */ 197 1.1 alc if (ints & HAL_INT_GLOBAL) { 198 1.1 alc HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: enable IER\n", __func__); 199 1.1 alc OS_REG_WRITE(ah, AR_IER, AR_IER_ENABLE); 200 1.1 alc } 201 1.1 alc return omask; 202 1.1 alc } 203