|
@@ -32,6 +32,138 @@ static void ar9003_hw_get_desc_link(void *ds, u32 **ds_link)
|
|
|
|
|
|
static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
|
|
|
{
|
|
|
+ u32 isr = 0;
|
|
|
+ u32 mask2 = 0;
|
|
|
+ struct ath9k_hw_capabilities *pCap = &ah->caps;
|
|
|
+ u32 sync_cause = 0;
|
|
|
+ struct ath_common *common = ath9k_hw_common(ah);
|
|
|
+
|
|
|
+ if (REG_READ(ah, AR_INTR_ASYNC_CAUSE) & AR_INTR_MAC_IRQ) {
|
|
|
+ if ((REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M)
|
|
|
+ == AR_RTC_STATUS_ON)
|
|
|
+ isr = REG_READ(ah, AR_ISR);
|
|
|
+ }
|
|
|
+
|
|
|
+ sync_cause = REG_READ(ah, AR_INTR_SYNC_CAUSE) & AR_INTR_SYNC_DEFAULT;
|
|
|
+
|
|
|
+ *masked = 0;
|
|
|
+
|
|
|
+ if (!isr && !sync_cause)
|
|
|
+ return false;
|
|
|
+
|
|
|
+ if (isr) {
|
|
|
+ if (isr & AR_ISR_BCNMISC) {
|
|
|
+ u32 isr2;
|
|
|
+ isr2 = REG_READ(ah, AR_ISR_S2);
|
|
|
+
|
|
|
+ mask2 |= ((isr2 & AR_ISR_S2_TIM) >>
|
|
|
+ MAP_ISR_S2_TIM);
|
|
|
+ mask2 |= ((isr2 & AR_ISR_S2_DTIM) >>
|
|
|
+ MAP_ISR_S2_DTIM);
|
|
|
+ mask2 |= ((isr2 & AR_ISR_S2_DTIMSYNC) >>
|
|
|
+ MAP_ISR_S2_DTIMSYNC);
|
|
|
+ mask2 |= ((isr2 & AR_ISR_S2_CABEND) >>
|
|
|
+ MAP_ISR_S2_CABEND);
|
|
|
+ mask2 |= ((isr2 & AR_ISR_S2_GTT) <<
|
|
|
+ MAP_ISR_S2_GTT);
|
|
|
+ mask2 |= ((isr2 & AR_ISR_S2_CST) <<
|
|
|
+ MAP_ISR_S2_CST);
|
|
|
+ mask2 |= ((isr2 & AR_ISR_S2_TSFOOR) >>
|
|
|
+ MAP_ISR_S2_TSFOOR);
|
|
|
+
|
|
|
+ if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) {
|
|
|
+ REG_WRITE(ah, AR_ISR_S2, isr2);
|
|
|
+ isr &= ~AR_ISR_BCNMISC;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if ((pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED))
|
|
|
+ isr = REG_READ(ah, AR_ISR_RAC);
|
|
|
+
|
|
|
+ if (isr == 0xffffffff) {
|
|
|
+ *masked = 0;
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ *masked = isr & ATH9K_INT_COMMON;
|
|
|
+
|
|
|
+ if (ah->config.rx_intr_mitigation)
|
|
|
+ if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM))
|
|
|
+ *masked |= ATH9K_INT_RXLP;
|
|
|
+
|
|
|
+ if (ah->config.tx_intr_mitigation)
|
|
|
+ if (isr & (AR_ISR_TXMINTR | AR_ISR_TXINTM))
|
|
|
+ *masked |= ATH9K_INT_TX;
|
|
|
+
|
|
|
+ if (isr & (AR_ISR_LP_RXOK | AR_ISR_RXERR))
|
|
|
+ *masked |= ATH9K_INT_RXLP;
|
|
|
+
|
|
|
+ if (isr & AR_ISR_HP_RXOK)
|
|
|
+ *masked |= ATH9K_INT_RXHP;
|
|
|
+
|
|
|
+ if (isr & (AR_ISR_TXOK | AR_ISR_TXERR | AR_ISR_TXEOL)) {
|
|
|
+ *masked |= ATH9K_INT_TX;
|
|
|
+
|
|
|
+ if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) {
|
|
|
+ u32 s0, s1;
|
|
|
+ s0 = REG_READ(ah, AR_ISR_S0);
|
|
|
+ REG_WRITE(ah, AR_ISR_S0, s0);
|
|
|
+ s1 = REG_READ(ah, AR_ISR_S1);
|
|
|
+ REG_WRITE(ah, AR_ISR_S1, s1);
|
|
|
+
|
|
|
+ isr &= ~(AR_ISR_TXOK | AR_ISR_TXERR |
|
|
|
+ AR_ISR_TXEOL);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (isr & AR_ISR_GENTMR) {
|
|
|
+ u32 s5;
|
|
|
+
|
|
|
+ if (pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)
|
|
|
+ s5 = REG_READ(ah, AR_ISR_S5_S);
|
|
|
+ else
|
|
|
+ s5 = REG_READ(ah, AR_ISR_S5);
|
|
|
+
|
|
|
+ ah->intr_gen_timer_trigger =
|
|
|
+ MS(s5, AR_ISR_S5_GENTIMER_TRIG);
|
|
|
+
|
|
|
+ ah->intr_gen_timer_thresh =
|
|
|
+ MS(s5, AR_ISR_S5_GENTIMER_THRESH);
|
|
|
+
|
|
|
+ if (ah->intr_gen_timer_trigger)
|
|
|
+ *masked |= ATH9K_INT_GENTIMER;
|
|
|
+
|
|
|
+ if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) {
|
|
|
+ REG_WRITE(ah, AR_ISR_S5, s5);
|
|
|
+ isr &= ~AR_ISR_GENTMR;
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ *masked |= mask2;
|
|
|
+
|
|
|
+ if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) {
|
|
|
+ REG_WRITE(ah, AR_ISR, isr);
|
|
|
+
|
|
|
+ (void) REG_READ(ah, AR_ISR);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (sync_cause) {
|
|
|
+ if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT) {
|
|
|
+ REG_WRITE(ah, AR_RC, AR_RC_HOSTIF);
|
|
|
+ REG_WRITE(ah, AR_RC, 0);
|
|
|
+ *masked |= ATH9K_INT_FATAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (sync_cause & AR_INTR_SYNC_LOCAL_TIMEOUT)
|
|
|
+ ath_print(common, ATH_DBG_INTERRUPT,
|
|
|
+ "AR_INTR_SYNC_LOCAL_TIMEOUT\n");
|
|
|
+
|
|
|
+ REG_WRITE(ah, AR_INTR_SYNC_CAUSE_CLR, sync_cause);
|
|
|
+ (void) REG_READ(ah, AR_INTR_SYNC_CAUSE_CLR);
|
|
|
+
|
|
|
+ }
|
|
|
return true;
|
|
|
}
|
|
|
|