118334Speter/* 218334Speter * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting 318334Speter * Copyright (c) 2002-2004 Atheros Communications, Inc. 418334Speter * 518334Speter * Permission to use, copy, modify, and/or distribute this software for any 618334Speter * purpose with or without fee is hereby granted, provided that the above 718334Speter * copyright notice and this permission notice appear in all copies. 818334Speter * 918334Speter * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 1018334Speter * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 1118334Speter * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 1218334Speter * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 1318334Speter * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 1418334Speter * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 1518334Speter * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 1618334Speter * 1718334Speter * $FreeBSD: releng/10.2/sys/dev/ath/ath_hal/ar5210/ar5210_interrupts.c 192397 2009-05-19 17:35:15Z sam $ 1818334Speter */ 1918334Speter#include "opt_ah.h" 2018334Speter 2118334Speter#include "ah.h" 2218334Speter#include "ah_internal.h" 2318334Speter 2418334Speter#include "ar5210/ar5210.h" 2518334Speter#include "ar5210/ar5210reg.h" 2618334Speter 2718334Speter/* 2818334Speter * Return non-zero if an interrupt is pending. 2918334Speter */ 3018334SpeterHAL_BOOL 3118334Speterar5210IsInterruptPending(struct ath_hal *ah) 3218334Speter{ 3318334Speter return (OS_REG_READ(ah, AR_INTPEND) ? AH_TRUE : AH_FALSE); 3418334Speter} 3518334Speter 3618334Speter/* 3718334Speter * Read the Interrupt Status Register value and return 3818334Speter * an abstracted bitmask of the data found in the ISR. 3918334Speter * Note that reading the ISR clear pending interrupts. 4018334Speter */ 4118334SpeterHAL_BOOL 4218334Speterar5210GetPendingInterrupts(struct ath_hal *ah, HAL_INT *masked) 4318334Speter{ 4418334Speter#define AR_FATAL_INT \ 4518334Speter (AR_ISR_MCABT_INT | AR_ISR_SSERR_INT | AR_ISR_DPERR_INT | AR_ISR_RXORN_INT) 4618334Speter struct ath_hal_5210 *ahp = AH5210(ah); 4718334Speter uint32_t isr; 4818334Speter 4918334Speter isr = OS_REG_READ(ah, AR_ISR); 5018334Speter if (isr == 0xffffffff) { 5118334Speter *masked = 0; 5218334Speter return AH_FALSE; 5318334Speter } 5418334Speter 5518334Speter /* 5618334Speter * Mask interrupts that have no device-independent 5718334Speter * representation; these are added back below. We 5818334Speter * also masked with the abstracted IMR to insure no 5918334Speter * status bits leak through that weren't requested 6018334Speter * (e.g. RXNOFRM) and that might confuse the caller. 6118334Speter */ 6218334Speter *masked = (isr & (HAL_INT_COMMON - HAL_INT_BNR)) & ahp->ah_maskReg; 6318334Speter 6418334Speter if (isr & AR_FATAL_INT) 6518334Speter *masked |= HAL_INT_FATAL; 6618334Speter if (isr & (AR_ISR_RXOK_INT | AR_ISR_RXERR_INT)) 6718334Speter *masked |= HAL_INT_RX; 6818334Speter if (isr & (AR_ISR_TXOK_INT | AR_ISR_TXDESC_INT | AR_ISR_TXERR_INT | AR_ISR_TXEOL_INT)) 6918334Speter *masked |= HAL_INT_TX; 7018334Speter 7118334Speter /* 7218334Speter * On fatal errors collect ISR state for debugging. 7318334Speter */ 7418334Speter if (*masked & HAL_INT_FATAL) { 7518334Speter AH_PRIVATE(ah)->ah_fatalState[0] = isr; 7618334Speter } 7718334Speter 7818334Speter return AH_TRUE; 7918334Speter#undef AR_FATAL_INT 8018334Speter} 8118334Speter 8218334SpeterHAL_INT 8318334Speterar5210GetInterrupts(struct ath_hal *ah) 8418334Speter{ 8518334Speter return AH5210(ah)->ah_maskReg; 8618334Speter} 8718334Speter 8818334SpeterHAL_INT 8918334Speterar5210SetInterrupts(struct ath_hal *ah, HAL_INT ints) 9018334Speter{ 9118334Speter struct ath_hal_5210 *ahp = AH5210(ah); 9218334Speter uint32_t omask = ahp->ah_maskReg; 9318334Speter uint32_t mask; 9418334Speter 9518334Speter HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: 0x%x => 0x%x\n", 9618334Speter __func__, omask, ints); 9718334Speter 9818334Speter /* 9918334Speter * Disable interrupts here before reading & modifying 10018334Speter * the mask so that the ISR does not modify the mask 10118334Speter * out from under us. 10218334Speter */ 10318334Speter if (omask & HAL_INT_GLOBAL) { 10418334Speter HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: disable IER\n", __func__); 10518334Speter OS_REG_WRITE(ah, AR_IER, AR_IER_DISABLE); 10618334Speter } 10718334Speter 10818334Speter mask = ints & (HAL_INT_COMMON - HAL_INT_BNR); 10918334Speter if (ints & HAL_INT_RX) 11018334Speter mask |= AR_IMR_RXOK_INT | AR_IMR_RXERR_INT; 11118334Speter if (ints & HAL_INT_TX) { 11218334Speter if (ahp->ah_txOkInterruptMask) 11318334Speter mask |= AR_IMR_TXOK_INT; 11418334Speter if (ahp->ah_txErrInterruptMask) 11518334Speter mask |= AR_IMR_TXERR_INT; 11618334Speter if (ahp->ah_txDescInterruptMask) 11718334Speter mask |= AR_IMR_TXDESC_INT; 11818334Speter if (ahp->ah_txEolInterruptMask) 11918334Speter mask |= AR_IMR_TXEOL_INT; 12018334Speter } 12118334Speter 12218334Speter /* Write the new IMR and store off our SW copy. */ 12318334Speter HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: new IMR 0x%x\n", __func__, mask); 12418334Speter OS_REG_WRITE(ah, AR_IMR, mask); 12518334Speter ahp->ah_maskReg = ints; 12618334Speter 12718334Speter /* Re-enable interrupts as appropriate. */ 12818334Speter if (ints & HAL_INT_GLOBAL) { 12918334Speter HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: enable IER\n", __func__); 13018334Speter OS_REG_WRITE(ah, AR_IER, AR_IER_ENABLE); 13118334Speter } 13218334Speter 13318334Speter return omask; 13418334Speter} 13518334Speter