1/*
2 * Copyright (c) 2013 Qualcomm Atheros, Inc.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
9 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10 * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
11 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
13 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14 * PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#include "opt_ah.h"
18
19#include "ah.h"
20#include "ah_internal.h"
21
22#include "ar9300/ar9300.h"
23#include "ar9300/ar9300reg.h"
24#include "ar9300/ar9300phy.h"
25
26/*
27 * Checks to see if an interrupt is pending on our NIC
28 *
29 * Returns: TRUE    if an interrupt is pending
30 *          FALSE   if not
31 */
32HAL_BOOL
33ar9300_is_interrupt_pending(struct ath_hal *ah)
34{
35    u_int32_t sync_en_def = AR9300_INTR_SYNC_DEFAULT;
36    u_int32_t host_isr;
37
38    /*
39     * Some platforms trigger our ISR before applying power to
40     * the card, so make sure.
41     */
42    host_isr = OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_ASYNC_CAUSE));
43    if ((host_isr & AR_INTR_ASYNC_USED) && (host_isr != AR_INTR_SPURIOUS)) {
44        return AH_TRUE;
45    }
46
47    host_isr = OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_CAUSE));
48    if (AR_SREV_POSEIDON(ah)) {
49        sync_en_def = AR9300_INTR_SYNC_DEF_NO_HOST1_PERR;
50    }
51    else if (AR_SREV_WASP(ah)) {
52        sync_en_def = AR9340_INTR_SYNC_DEFAULT;
53    }
54
55    if ((host_isr & (sync_en_def | AR_INTR_SYNC_MASK_GPIO)) &&
56        (host_isr != AR_INTR_SPURIOUS)) {
57        return AH_TRUE;
58    }
59
60    return AH_FALSE;
61}
62
63/*
64 * Reads the Interrupt Status Register value from the NIC, thus deasserting
65 * the interrupt line, and returns both the masked and unmasked mapped ISR
66 * values.  The value returned is mapped to abstract the hw-specific bit
67 * locations in the Interrupt Status Register.
68 *
69 * Returns: A hardware-abstracted bitmap of all non-masked-out
70 *          interrupts pending, as well as an unmasked value
71 */
72#define MAP_ISR_S2_HAL_CST          6 /* Carrier sense timeout */
73#define MAP_ISR_S2_HAL_GTT          6 /* Global transmit timeout */
74#define MAP_ISR_S2_HAL_TIM          3 /* TIM */
75#define MAP_ISR_S2_HAL_CABEND       0 /* CABEND */
76#define MAP_ISR_S2_HAL_DTIMSYNC     7 /* DTIMSYNC */
77#define MAP_ISR_S2_HAL_DTIM         7 /* DTIM */
78#define MAP_ISR_S2_HAL_TSFOOR       4 /* Rx TSF out of range */
79#define MAP_ISR_S2_HAL_BBPANIC      6 /* Panic watchdog IRQ from BB */
80HAL_BOOL
81ar9300_get_pending_interrupts(
82    struct ath_hal *ah,
83    HAL_INT *masked,
84    HAL_INT_TYPE type,
85    u_int8_t msi,
86    HAL_BOOL nortc)
87{
88    struct ath_hal_9300 *ahp = AH9300(ah);
89    HAL_BOOL  ret_val = AH_TRUE;
90    u_int32_t isr = 0;
91    u_int32_t mask2 = 0;
92    u_int32_t sync_cause = 0;
93    u_int32_t async_cause;
94    u_int32_t msi_pend_addr_mask = 0;
95    u_int32_t sync_en_def = AR9300_INTR_SYNC_DEFAULT;
96    HAL_CAPABILITIES *p_cap = &AH_PRIVATE(ah)->ah_caps;
97
98    *masked = 0;
99
100    if (!nortc) {
101        if (HAL_INT_MSI == type) {
102            if (msi == HAL_MSIVEC_RXHP) {
103                OS_REG_WRITE(ah, AR_ISR, AR_ISR_HP_RXOK);
104                *masked = HAL_INT_RXHP;
105                goto end;
106            } else if (msi == HAL_MSIVEC_RXLP) {
107                OS_REG_WRITE(ah, AR_ISR,
108                    (AR_ISR_LP_RXOK | AR_ISR_RXMINTR | AR_ISR_RXINTM));
109                *masked = HAL_INT_RXLP;
110                goto end;
111            } else if (msi == HAL_MSIVEC_TX) {
112                OS_REG_WRITE(ah, AR_ISR, AR_ISR_TXOK);
113                *masked = HAL_INT_TX;
114                goto end;
115            } else if (msi == HAL_MSIVEC_MISC) {
116                /*
117                 * For the misc MSI event fall through and determine the cause.
118                 */
119            }
120        }
121    }
122
123    /* Make sure mac interrupt is pending in async interrupt cause register */
124    async_cause = OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_ASYNC_CAUSE));
125    if (async_cause & AR_INTR_ASYNC_USED) {
126        /*
127         * RTC may not be on since it runs on a slow 32khz clock
128         * so check its status to be sure
129         */
130        if (!nortc &&
131            (OS_REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M) ==
132             AR_RTC_STATUS_ON)
133        {
134            isr = OS_REG_READ(ah, AR_ISR);
135        }
136    }
137
138    if (AR_SREV_POSEIDON(ah)) {
139        sync_en_def = AR9300_INTR_SYNC_DEF_NO_HOST1_PERR;
140    }
141    else if (AR_SREV_WASP(ah)) {
142        sync_en_def = AR9340_INTR_SYNC_DEFAULT;
143    }
144
145    /* Store away the async and sync cause registers */
146    /* XXX Do this before the filtering done below */
147#ifdef	AH_INTERRUPT_DEBUGGING
148	ah->ah_intrstate[0] = OS_REG_READ(ah, AR_ISR);
149	ah->ah_intrstate[1] = OS_REG_READ(ah, AR_ISR_S0);
150	ah->ah_intrstate[2] = OS_REG_READ(ah, AR_ISR_S1);
151	ah->ah_intrstate[3] = OS_REG_READ(ah, AR_ISR_S2);
152	ah->ah_intrstate[4] = OS_REG_READ(ah, AR_ISR_S3);
153	ah->ah_intrstate[5] = OS_REG_READ(ah, AR_ISR_S4);
154	ah->ah_intrstate[6] = OS_REG_READ(ah, AR_ISR_S5);
155
156	/* XXX double reading? */
157	ah->ah_syncstate = OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_CAUSE));
158#endif
159
160    sync_cause =
161        OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_CAUSE)) &
162        (sync_en_def | AR_INTR_SYNC_MASK_GPIO);
163
164    if (!isr && !sync_cause && !async_cause) {
165        ret_val = AH_FALSE;
166        goto end;
167    }
168
169    HALDEBUG(ah, HAL_DEBUG_INTERRUPT,
170        "%s: isr=0x%x, sync_cause=0x%x, async_cause=0x%x\n",
171	__func__,
172	isr,
173	sync_cause,
174	async_cause);
175
176    if (isr) {
177        if (isr & AR_ISR_BCNMISC) {
178            u_int32_t isr2;
179            isr2 = OS_REG_READ(ah, AR_ISR_S2);
180
181            /* Translate ISR bits to HAL values */
182            mask2 |= ((isr2 & AR_ISR_S2_TIM) >> MAP_ISR_S2_HAL_TIM);
183            mask2 |= ((isr2 & AR_ISR_S2_DTIM) >> MAP_ISR_S2_HAL_DTIM);
184            mask2 |= ((isr2 & AR_ISR_S2_DTIMSYNC) >> MAP_ISR_S2_HAL_DTIMSYNC);
185            mask2 |= ((isr2 & AR_ISR_S2_CABEND) >> MAP_ISR_S2_HAL_CABEND);
186            mask2 |= ((isr2 & AR_ISR_S2_GTT) << MAP_ISR_S2_HAL_GTT);
187            mask2 |= ((isr2 & AR_ISR_S2_CST) << MAP_ISR_S2_HAL_CST);
188            mask2 |= ((isr2 & AR_ISR_S2_TSFOOR) >> MAP_ISR_S2_HAL_TSFOOR);
189            mask2 |= ((isr2 & AR_ISR_S2_BBPANIC) >> MAP_ISR_S2_HAL_BBPANIC);
190
191            if (!p_cap->halIsrRacSupport) {
192                /*
193                 * EV61133 (missing interrupts due to ISR_RAC):
194                 * If not using ISR_RAC, clear interrupts by writing to ISR_S2.
195                 * This avoids a race condition where a new BCNMISC interrupt
196                 * could come in between reading the ISR and clearing the
197                 * interrupt via the primary ISR.  We therefore clear the
198                 * interrupt via the secondary, which avoids this race.
199                 */
200                OS_REG_WRITE(ah, AR_ISR_S2, isr2);
201                isr &= ~AR_ISR_BCNMISC;
202            }
203        }
204
205        /* Use AR_ISR_RAC only if chip supports it.
206         * See EV61133 (missing interrupts due to ISR_RAC)
207         */
208        if (p_cap->halIsrRacSupport) {
209            isr = OS_REG_READ(ah, AR_ISR_RAC);
210        }
211        if (isr == 0xffffffff) {
212            *masked = 0;
213            ret_val = AH_FALSE;
214            goto end;
215        }
216
217        *masked = isr & HAL_INT_COMMON;
218
219        /*
220         * When interrupt mitigation is switched on, we fake a normal RX or TX
221         * interrupt when we received a mitigated interrupt. This way, the upper
222         * layer do not need to know about feature.
223         */
224        if (ahp->ah_intr_mitigation_rx) {
225            /* Only Rx interrupt mitigation. No Tx intr. mitigation. */
226            if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM)) {
227                *masked |= HAL_INT_RXLP;
228            }
229        }
230        if (ahp->ah_intr_mitigation_tx) {
231            if (isr & (AR_ISR_TXMINTR | AR_ISR_TXINTM)) {
232                *masked |= HAL_INT_TX;
233            }
234        }
235
236        if (isr & (AR_ISR_LP_RXOK | AR_ISR_RXERR)) {
237            *masked |= HAL_INT_RXLP;
238        }
239        if (isr & AR_ISR_HP_RXOK) {
240            *masked |= HAL_INT_RXHP;
241        }
242        if (isr & (AR_ISR_TXOK | AR_ISR_TXERR | AR_ISR_TXEOL)) {
243            *masked |= HAL_INT_TX;
244
245            if (!p_cap->halIsrRacSupport) {
246                u_int32_t s0, s1;
247                /*
248                 * EV61133 (missing interrupts due to ISR_RAC):
249                 * If not using ISR_RAC, clear interrupts by writing to
250                 * ISR_S0/S1.
251                 * This avoids a race condition where a new interrupt
252                 * could come in between reading the ISR and clearing the
253                 * interrupt via the primary ISR.  We therefore clear the
254                 * interrupt via the secondary, which avoids this race.
255                 */
256                s0 = OS_REG_READ(ah, AR_ISR_S0);
257                OS_REG_WRITE(ah, AR_ISR_S0, s0);
258                s1 = OS_REG_READ(ah, AR_ISR_S1);
259                OS_REG_WRITE(ah, AR_ISR_S1, s1);
260
261                isr &= ~(AR_ISR_TXOK | AR_ISR_TXERR | AR_ISR_TXEOL);
262            }
263        }
264
265        /*
266         * Do not treat receive overflows as fatal for owl.
267         */
268        if (isr & AR_ISR_RXORN) {
269#if __PKT_SERIOUS_ERRORS__
270            HALDEBUG(ah, HAL_DEBUG_INTERRUPT,
271                "%s: receive FIFO overrun interrupt\n", __func__);
272#endif
273        }
274
275#if 0
276        /* XXX Verify if this is fixed for Osprey */
277        if (!p_cap->halAutoSleepSupport) {
278            u_int32_t isr5 = OS_REG_READ(ah, AR_ISR_S5_S);
279            if (isr5 & AR_ISR_S5_TIM_TIMER) {
280                *masked |= HAL_INT_TIM_TIMER;
281            }
282        }
283#endif
284        if (isr & AR_ISR_GENTMR) {
285            u_int32_t s5;
286
287            if (p_cap->halIsrRacSupport) {
288                /* Use secondary shadow registers if using ISR_RAC */
289                s5 = OS_REG_READ(ah, AR_ISR_S5_S);
290            } else {
291                s5 = OS_REG_READ(ah, AR_ISR_S5);
292            }
293            if (isr & AR_ISR_GENTMR) {
294
295                HALDEBUG(ah, HAL_DEBUG_INTERRUPT,
296                    "%s: GENTIMER, ISR_RAC=0x%x ISR_S2_S=0x%x\n", __func__,
297                    isr, s5);
298                ahp->ah_intr_gen_timer_trigger =
299                    MS(s5, AR_ISR_S5_GENTIMER_TRIG);
300                ahp->ah_intr_gen_timer_thresh =
301                    MS(s5, AR_ISR_S5_GENTIMER_THRESH);
302                if (ahp->ah_intr_gen_timer_trigger) {
303                    *masked |= HAL_INT_GENTIMER;
304                }
305            }
306            if (!p_cap->halIsrRacSupport) {
307                /*
308                 * EV61133 (missing interrupts due to ISR_RAC):
309                 * If not using ISR_RAC, clear interrupts by writing to ISR_S5.
310                 * This avoids a race condition where a new interrupt
311                 * could come in between reading the ISR and clearing the
312                 * interrupt via the primary ISR.  We therefore clear the
313                 * interrupt via the secondary, which avoids this race.
314                 */
315                OS_REG_WRITE(ah, AR_ISR_S5, s5);
316                isr &= ~AR_ISR_GENTMR;
317            }
318        }
319
320        *masked |= mask2;
321
322        if (!p_cap->halIsrRacSupport) {
323            /*
324             * EV61133 (missing interrupts due to ISR_RAC):
325             * If not using ISR_RAC, clear the interrupts we've read by
326             * writing back ones in these locations to the primary ISR
327             * (except for interrupts that have a secondary isr register -
328             * see above).
329             */
330            OS_REG_WRITE(ah, AR_ISR, isr);
331
332            /* Flush prior write */
333            (void) OS_REG_READ(ah, AR_ISR);
334        }
335
336#ifdef AH_SUPPORT_AR9300
337        if (*masked & HAL_INT_BBPANIC) {
338            ar9300_handle_bb_panic(ah);
339        }
340#endif
341    }
342
343    if (async_cause) {
344        if (nortc) {
345            OS_REG_WRITE(ah,
346                AR_HOSTIF_REG(ah, AR_INTR_ASYNC_CAUSE_CLR), async_cause);
347            /* Flush prior write */
348            (void) OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_ASYNC_CAUSE_CLR));
349        } else {
350#ifdef ATH_GPIO_USE_ASYNC_CAUSE
351            if (async_cause & AR_INTR_ASYNC_CAUSE_GPIO) {
352                ahp->ah_gpio_cause = (async_cause & AR_INTR_ASYNC_CAUSE_GPIO) >>
353                                     AR_INTR_ASYNC_ENABLE_GPIO_S;
354                *masked |= HAL_INT_GPIO;
355            }
356#endif
357        }
358
359#if ATH_SUPPORT_MCI
360        if ((async_cause & AR_INTR_ASYNC_CAUSE_MCI) &&
361            p_cap->halMciSupport)
362        {
363            u_int32_t int_raw, int_rx_msg;
364
365            int_rx_msg = OS_REG_READ(ah, AR_MCI_INTERRUPT_RX_MSG_RAW);
366            int_raw = OS_REG_READ(ah, AR_MCI_INTERRUPT_RAW);
367
368            if ((int_raw == 0xdeadbeef) || (int_rx_msg == 0xdeadbeef))
369            {
370                HALDEBUG(ah, HAL_DEBUG_BT_COEX,
371                    "(MCI) Get 0xdeadbeef during MCI int processing"
372                    "new int_raw=0x%08x, new rx_msg_raw=0x%08x, "
373                    "int_raw=0x%08x, rx_msg_raw=0x%08x\n",
374                    int_raw, int_rx_msg, ahp->ah_mci_int_raw,
375                    ahp->ah_mci_int_rx_msg);
376            }
377            else {
378                if (ahp->ah_mci_int_raw || ahp->ah_mci_int_rx_msg) {
379                    ahp->ah_mci_int_rx_msg |= int_rx_msg;
380                    ahp->ah_mci_int_raw |= int_raw;
381                }
382                else {
383                    ahp->ah_mci_int_rx_msg = int_rx_msg;
384                    ahp->ah_mci_int_raw = int_raw;
385                }
386
387                *masked |= HAL_INT_MCI;
388                ahp->ah_mci_rx_status = OS_REG_READ(ah, AR_MCI_RX_STATUS);
389                if (int_rx_msg & AR_MCI_INTERRUPT_RX_MSG_CONT_INFO) {
390                    ahp->ah_mci_cont_status =
391                                    OS_REG_READ(ah, AR_MCI_CONT_STATUS);
392                    HALDEBUG(ah, HAL_DEBUG_BT_COEX,
393                        "(MCI) cont_status=0x%08x\n", ahp->ah_mci_cont_status);
394                }
395                OS_REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW,
396                    int_rx_msg);
397                OS_REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, int_raw);
398
399                HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s:AR_INTR_SYNC_MCI\n", __func__);
400            }
401        }
402#endif
403    }
404
405    if (sync_cause) {
406        int host1_fatal, host1_perr, radm_cpl_timeout, local_timeout;
407
408        host1_fatal = AR_SREV_WASP(ah) ?
409            AR9340_INTR_SYNC_HOST1_FATAL : AR9300_INTR_SYNC_HOST1_FATAL;
410        host1_perr = AR_SREV_WASP(ah) ?
411            AR9340_INTR_SYNC_HOST1_PERR : AR9300_INTR_SYNC_HOST1_PERR;
412        radm_cpl_timeout = AR_SREV_WASP(ah) ?
413            0x0 : AR9300_INTR_SYNC_RADM_CPL_TIMEOUT;
414        local_timeout = AR_SREV_WASP(ah) ?
415            AR9340_INTR_SYNC_LOCAL_TIMEOUT : AR9300_INTR_SYNC_LOCAL_TIMEOUT;
416
417        if (sync_cause & host1_fatal) {
418#if __PKT_SERIOUS_ERRORS__
419            HALDEBUG(ah, HAL_DEBUG_UNMASKABLE,
420                "%s: received PCI FATAL interrupt\n", __func__);
421#endif
422           *masked |= HAL_INT_FATAL; /* Set FATAL INT flag here;*/
423        }
424        if (sync_cause & host1_perr) {
425#if __PKT_SERIOUS_ERRORS__
426            HALDEBUG(ah, HAL_DEBUG_UNMASKABLE,
427                "%s: received PCI PERR interrupt\n", __func__);
428#endif
429        }
430
431        if (sync_cause & radm_cpl_timeout) {
432            HALDEBUG(ah, HAL_DEBUG_INTERRUPT,
433                "%s: AR_INTR_SYNC_RADM_CPL_TIMEOUT\n",
434                __func__);
435
436            OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_RC), AR_RC_HOSTIF);
437            OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_RC), 0);
438            *masked |= HAL_INT_FATAL;
439        }
440        if (sync_cause & local_timeout) {
441            HALDEBUG(ah, HAL_DEBUG_INTERRUPT,
442                "%s: AR_INTR_SYNC_LOCAL_TIMEOUT\n",
443                __func__);
444        }
445
446#ifndef ATH_GPIO_USE_ASYNC_CAUSE
447        if (sync_cause & AR_INTR_SYNC_MASK_GPIO) {
448            ahp->ah_gpio_cause = (sync_cause & AR_INTR_SYNC_MASK_GPIO) >>
449                                 AR_INTR_SYNC_ENABLE_GPIO_S;
450            *masked |= HAL_INT_GPIO;
451            HALDEBUG(ah, HAL_DEBUG_INTERRUPT,
452                "%s: AR_INTR_SYNC_GPIO\n", __func__);
453        }
454#endif
455
456        OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_CAUSE_CLR), sync_cause);
457        /* Flush prior write */
458        (void) OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_CAUSE_CLR));
459    }
460
461end:
462    if (HAL_INT_MSI == type) {
463        /*
464         * WAR for Bug EV#75887
465         * In normal case, SW read HOST_INTF_PCIE_MSI (0x40A4) and write
466         * into ah_msi_reg.  Then use value of ah_msi_reg to set bit#25
467         * when want to enable HW write the cfg_msi_pending.
468         * Sometimes, driver get MSI interrupt before read 0x40a4 and
469         * ah_msi_reg is initialization value (0x0).
470         * We don't know why "MSI interrupt earlier than driver read" now...
471         */
472        if (!ahp->ah_msi_reg) {
473            ahp->ah_msi_reg = OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_PCIE_MSI));
474        }
475        if (AR_SREV_POSEIDON(ah)) {
476            msi_pend_addr_mask = AR_PCIE_MSI_HW_INT_PENDING_ADDR_MSI_64;
477        } else {
478            msi_pend_addr_mask = AR_PCIE_MSI_HW_INT_PENDING_ADDR;
479        }
480        OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_PCIE_MSI),
481            ((ahp->ah_msi_reg | AR_PCIE_MSI_ENABLE) & msi_pend_addr_mask));
482
483    }
484
485    return ret_val;
486}
487
488HAL_INT
489ar9300_get_interrupts(struct ath_hal *ah)
490{
491    return AH9300(ah)->ah_mask_reg;
492}
493
494/*
495 * Atomically enables NIC interrupts.  Interrupts are passed in
496 * via the enumerated bitmask in ints.
497 */
498HAL_INT
499ar9300_set_interrupts(struct ath_hal *ah, HAL_INT ints, HAL_BOOL nortc)
500{
501    struct ath_hal_9300 *ahp = AH9300(ah);
502    u_int32_t omask = ahp->ah_mask_reg;
503    u_int32_t mask, mask2, msi_mask = 0;
504    u_int32_t msi_pend_addr_mask = 0;
505    u_int32_t sync_en_def = AR9300_INTR_SYNC_DEFAULT;
506    HAL_CAPABILITIES *p_cap = &AH_PRIVATE(ah)->ah_caps;
507
508    HALDEBUG(ah, HAL_DEBUG_INTERRUPT,
509        "%s: 0x%x => 0x%x\n", __func__, omask, ints);
510
511    if (omask & HAL_INT_GLOBAL) {
512        HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: disable IER\n", __func__);
513
514        if (ah->ah_config.ath_hal_enable_msi) {
515            OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_INTR_PRIO_ASYNC_ENABLE), 0);
516            /* flush write to HW */
517            (void)OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_PRIO_ASYNC_ENABLE));
518        }
519
520        if (!nortc) {
521            OS_REG_WRITE(ah, AR_IER, AR_IER_DISABLE);
522            (void) OS_REG_READ(ah, AR_IER);   /* flush write to HW */
523        }
524
525        OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_ENABLE), 0);
526        /* flush write to HW */
527        (void) OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_ENABLE));
528        OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_INTR_ASYNC_ENABLE), 0);
529        /* flush write to HW */
530        (void) OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_ASYNC_ENABLE));
531    }
532
533    if (!nortc) {
534        /* reference count for global IER */
535        if (ints & HAL_INT_GLOBAL) {
536#ifdef AH_DEBUG
537            HALDEBUG(ah, HAL_DEBUG_INTERRUPT,
538                "%s: Request HAL_INT_GLOBAL ENABLED\n", __func__);
539#if 0
540            if (OS_ATOMIC_READ(&ahp->ah_ier_ref_count) == 0) {
541                HALDEBUG(ah, HAL_DEBUG_UNMASKABLE,
542                    "%s: WARNING: ah_ier_ref_count is 0 "
543                    "and attempting to enable IER\n",
544                    __func__);
545            }
546#endif
547#endif
548#if 0
549            if (OS_ATOMIC_READ(&ahp->ah_ier_ref_count) > 0) {
550                OS_ATOMIC_DEC(&ahp->ah_ier_ref_count);
551            }
552#endif
553        } else {
554            HALDEBUG(ah, HAL_DEBUG_INTERRUPT,
555                "%s: Request HAL_INT_GLOBAL DISABLED\n", __func__);
556            OS_ATOMIC_INC(&ahp->ah_ier_ref_count);
557        }
558        HALDEBUG(ah, HAL_DEBUG_INTERRUPT,
559            "%s: ah_ier_ref_count = %d\n", __func__, ahp->ah_ier_ref_count);
560
561        mask = ints & HAL_INT_COMMON;
562        mask2 = 0;
563        msi_mask = 0;
564
565        if (ints & HAL_INT_TX) {
566            if (ahp->ah_intr_mitigation_tx) {
567                mask |= AR_IMR_TXMINTR | AR_IMR_TXINTM;
568            } else if (ahp->ah_tx_ok_interrupt_mask) {
569                mask |= AR_IMR_TXOK;
570            }
571            msi_mask |= AR_INTR_PRIO_TX;
572            if (ahp->ah_tx_err_interrupt_mask) {
573                mask |= AR_IMR_TXERR;
574            }
575            if (ahp->ah_tx_eol_interrupt_mask) {
576                mask |= AR_IMR_TXEOL;
577            }
578        }
579        if (ints & HAL_INT_RX) {
580            mask |= AR_IMR_RXERR | AR_IMR_RXOK_HP;
581            if (ahp->ah_intr_mitigation_rx) {
582                mask &= ~(AR_IMR_RXOK_LP);
583                mask |=  AR_IMR_RXMINTR | AR_IMR_RXINTM;
584            } else {
585                mask |= AR_IMR_RXOK_LP;
586            }
587            msi_mask |= AR_INTR_PRIO_RXLP | AR_INTR_PRIO_RXHP;
588            if (! p_cap->halAutoSleepSupport) {
589                mask |= AR_IMR_GENTMR;
590            }
591        }
592
593        if (ints & (HAL_INT_BMISC)) {
594            mask |= AR_IMR_BCNMISC;
595            if (ints & HAL_INT_TIM) {
596                mask2 |= AR_IMR_S2_TIM;
597            }
598            if (ints & HAL_INT_DTIM) {
599                mask2 |= AR_IMR_S2_DTIM;
600            }
601            if (ints & HAL_INT_DTIMSYNC) {
602                mask2 |= AR_IMR_S2_DTIMSYNC;
603            }
604            if (ints & HAL_INT_CABEND) {
605                mask2 |= (AR_IMR_S2_CABEND);
606            }
607            if (ints & HAL_INT_TSFOOR) {
608                mask2 |= AR_IMR_S2_TSFOOR;
609            }
610        }
611
612        if (ints & (HAL_INT_GTT | HAL_INT_CST)) {
613            mask |= AR_IMR_BCNMISC;
614            if (ints & HAL_INT_GTT) {
615                mask2 |= AR_IMR_S2_GTT;
616            }
617            if (ints & HAL_INT_CST) {
618                mask2 |= AR_IMR_S2_CST;
619            }
620        }
621
622        if (ints & HAL_INT_BBPANIC) {
623            /* EV92527 - MAC secondary interrupt must enable AR_IMR_BCNMISC */
624            mask |= AR_IMR_BCNMISC;
625            mask2 |= AR_IMR_S2_BBPANIC;
626        }
627
628        if (ints & HAL_INT_GENTIMER) {
629            HALDEBUG(ah, HAL_DEBUG_INTERRUPT,
630                "%s: enabling gen timer\n", __func__);
631            mask |= AR_IMR_GENTMR;
632        }
633
634        /* Write the new IMR and store off our SW copy. */
635        HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: new IMR 0x%x\n", __func__, mask);
636        OS_REG_WRITE(ah, AR_IMR, mask);
637        ahp->ah_mask2Reg &= ~(AR_IMR_S2_TIM |
638                        AR_IMR_S2_DTIM |
639                        AR_IMR_S2_DTIMSYNC |
640                        AR_IMR_S2_CABEND |
641                        AR_IMR_S2_CABTO  |
642                        AR_IMR_S2_TSFOOR |
643                        AR_IMR_S2_GTT |
644                        AR_IMR_S2_CST |
645                        AR_IMR_S2_BBPANIC);
646        ahp->ah_mask2Reg |= mask2;
647        OS_REG_WRITE(ah, AR_IMR_S2, ahp->ah_mask2Reg );
648        ahp->ah_mask_reg = ints;
649
650        if (! p_cap->halAutoSleepSupport) {
651            if (ints & HAL_INT_TIM_TIMER) {
652                OS_REG_SET_BIT(ah, AR_IMR_S5, AR_IMR_S5_TIM_TIMER);
653            }
654            else {
655                OS_REG_CLR_BIT(ah, AR_IMR_S5, AR_IMR_S5_TIM_TIMER);
656            }
657        }
658    }
659
660    /* Re-enable interrupts if they were enabled before. */
661#if HAL_INTR_REFCOUNT_DISABLE
662    if ((ints & HAL_INT_GLOBAL)) {
663#else
664    if ((ints & HAL_INT_GLOBAL) && (OS_ATOMIC_READ(&ahp->ah_ier_ref_count) == 0)) {
665#endif
666        HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: enable IER\n", __func__);
667
668        if (!nortc) {
669            OS_REG_WRITE(ah, AR_IER, AR_IER_ENABLE);
670        }
671
672        mask = AR_INTR_MAC_IRQ;
673#ifdef ATH_GPIO_USE_ASYNC_CAUSE
674        if (ints & HAL_INT_GPIO) {
675            if (ahp->ah_gpio_mask) {
676                mask |= SM(ahp->ah_gpio_mask, AR_INTR_ASYNC_MASK_GPIO);
677            }
678        }
679#endif
680
681#if ATH_SUPPORT_MCI
682        if (ints & HAL_INT_MCI) {
683            mask |= AR_INTR_ASYNC_MASK_MCI;
684        }
685#endif
686
687        OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_INTR_ASYNC_ENABLE), mask);
688        OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_INTR_ASYNC_MASK), mask);
689
690        if (ah->ah_config.ath_hal_enable_msi) {
691            OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_INTR_PRIO_ASYNC_ENABLE),
692                msi_mask);
693            OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_INTR_PRIO_ASYNC_MASK),
694                msi_mask);
695            if (AR_SREV_POSEIDON(ah)) {
696                msi_pend_addr_mask = AR_PCIE_MSI_HW_INT_PENDING_ADDR_MSI_64;
697            } else {
698                msi_pend_addr_mask = AR_PCIE_MSI_HW_INT_PENDING_ADDR;
699            }
700            OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_PCIE_MSI),
701                ((ahp->ah_msi_reg | AR_PCIE_MSI_ENABLE) & msi_pend_addr_mask));
702        }
703
704        /*
705         * debug - enable to see all synchronous interrupts status
706         * Enable synchronous GPIO interrupts as well, since some async
707         * GPIO interrupts don't wake the chip up.
708         */
709        mask = 0;
710#ifndef ATH_GPIO_USE_ASYNC_CAUSE
711        if (ints & HAL_INT_GPIO) {
712            mask |= SM(ahp->ah_gpio_mask, AR_INTR_SYNC_MASK_GPIO);
713        }
714#endif
715        if (AR_SREV_POSEIDON(ah)) {
716            sync_en_def = AR9300_INTR_SYNC_DEF_NO_HOST1_PERR;
717        }
718        else if (AR_SREV_WASP(ah)) {
719            sync_en_def = AR9340_INTR_SYNC_DEFAULT;
720        }
721
722        OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_ENABLE),
723            (sync_en_def | mask));
724        OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_MASK),
725            (sync_en_def | mask));
726
727        HALDEBUG(ah,  HAL_DEBUG_INTERRUPT,
728            "AR_IMR 0x%x IER 0x%x\n",
729            OS_REG_READ(ah, AR_IMR), OS_REG_READ(ah, AR_IER));
730    }
731
732    return omask;
733}
734
735void
736ar9300_set_intr_mitigation_timer(
737    struct ath_hal* ah,
738    HAL_INT_MITIGATION reg,
739    u_int32_t value)
740{
741#ifdef AR5416_INT_MITIGATION
742    switch (reg) {
743    case HAL_INT_THRESHOLD:
744        OS_REG_WRITE(ah, AR_MIRT, 0);
745        break;
746    case HAL_INT_RX_LASTPKT:
747        OS_REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_LAST, value);
748        break;
749    case HAL_INT_RX_FIRSTPKT:
750        OS_REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_FIRST, value);
751        break;
752    case HAL_INT_TX_LASTPKT:
753        OS_REG_RMW_FIELD(ah, AR_TIMT, AR_TIMT_LAST, value);
754        break;
755    case HAL_INT_TX_FIRSTPKT:
756        OS_REG_RMW_FIELD(ah, AR_TIMT, AR_TIMT_FIRST, value);
757        break;
758    default:
759        break;
760    }
761#endif
762}
763
764u_int32_t
765ar9300_get_intr_mitigation_timer(struct ath_hal* ah, HAL_INT_MITIGATION reg)
766{
767    u_int32_t val = 0;
768#ifdef AR5416_INT_MITIGATION
769    switch (reg) {
770    case HAL_INT_THRESHOLD:
771        val = OS_REG_READ(ah, AR_MIRT);
772        break;
773    case HAL_INT_RX_LASTPKT:
774        val = OS_REG_READ(ah, AR_RIMT) & 0xFFFF;
775        break;
776    case HAL_INT_RX_FIRSTPKT:
777        val = OS_REG_READ(ah, AR_RIMT) >> 16;
778        break;
779    case HAL_INT_TX_LASTPKT:
780        val = OS_REG_READ(ah, AR_TIMT) & 0xFFFF;
781        break;
782    case HAL_INT_TX_FIRSTPKT:
783        val = OS_REG_READ(ah, AR_TIMT) >> 16;
784        break;
785    default:
786        break;
787    }
788#endif
789    return val;
790}
791