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 */
32 HAL_BOOL
ar9300_is_interrupt_pending(struct ath_hal * ah)33 ar9300_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 */
80 HAL_BOOL
ar9300_get_pending_interrupts(struct ath_hal * ah,HAL_INT * masked,HAL_INT_TYPE type,u_int8_t msi,HAL_BOOL nortc)81 ar9300_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
461 end:
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
488 HAL_INT
ar9300_get_interrupts(struct ath_hal * ah)489 ar9300_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 */
498 HAL_INT
ar9300_set_interrupts(struct ath_hal * ah,HAL_INT ints,HAL_BOOL nortc)499 ar9300_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
735 void
736 ar9300_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
764 u_int32_t
765 ar9300_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