xref: /freebsd/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_gpio.c (revision 02e9120893770924227138ba49df1edb3896112a)
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 #include "ah_devid.h"
22 #ifdef AH_DEBUG
23 #include "ah_desc.h"                    /* NB: for HAL_PHYERR* */
24 #endif
25 
26 #include "ar9300/ar9300.h"
27 #include "ar9300/ar9300reg.h"
28 #include "ar9300/ar9300phy.h"
29 
30 #define AR_GPIO_BIT(_gpio)                      (1 << (_gpio))
31 
32 /*
33  * Configure GPIO Output Mux control
34  */
35 #if UMAC_SUPPORT_SMARTANTENNA
36 static void  ar9340_soc_gpio_cfg_output_mux(
37     struct ath_hal *ah,
38     u_int32_t gpio,
39     u_int32_t ah_signal_type)
40 {
41 #define ADDR_READ(addr)      (*((volatile u_int32_t *)(addr)))
42 #define ADDR_WRITE(addr, b)   (void)((*(volatile u_int32_t *) (addr)) = (b))
43 #define AR9340_SOC_GPIO_FUN0    0xB804002c
44 #define AR9340_SOC_GPIO_OE      0xB8040000
45 #if ATH_SMARTANTENNA_DISABLE_JTAG
46 #define AR9340_SOC_GPIO_FUNCTION   (volatile u_int32_t*) 0xB804006c
47 #define WASP_DISABLE_JTAG  0x2
48 #define MAX_JTAG_GPIO_PIN 1
49 #endif
50     u_int8_t out_func, shift;
51     u_int32_t  flags;
52     volatile u_int32_t* address;
53 
54     if (!ah_signal_type){
55         return;
56     }
57 #if ATH_SMARTANTENNA_DISABLE_JTAG
58 /*
59  * To use GPIO pins 0 and 1 for controling antennas, JTAG needs to disabled.
60  */
61     if (gpio <= MAX_JTAG_GPIO_PIN) {
62         flags = ADDR_READ(AR9340_SOC_GPIO_FUNCTION);
63         flags |= WASP_DISABLE_JTAG;
64         ADDR_WRITE(AR9340_SOC_GPIO_FUNCTION, flags);
65     }
66 #endif
67     out_func = gpio / 4;
68     shift = (gpio % 4);
69     address = (volatile u_int32_t *)(AR9340_SOC_GPIO_FUN0 + (out_func*4));
70 
71     flags = ADDR_READ(address);
72     flags |= ah_signal_type << (8*shift);
73     ADDR_WRITE(address, flags);
74     flags = ADDR_READ(AR9340_SOC_GPIO_OE);
75     flags &= ~(1 << gpio);
76     ADDR_WRITE(AR9340_SOC_GPIO_OE, flags);
77 
78 }
79 #endif
80 
81 static void
82 ar9300_gpio_cfg_output_mux(struct ath_hal *ah, u_int32_t gpio, u_int32_t type)
83 {
84     int          addr;
85     u_int32_t    gpio_shift;
86 
87     /* each MUX controls 6 GPIO pins */
88     if (gpio > 11) {
89         addr = AR_HOSTIF_REG(ah, AR_GPIO_OUTPUT_MUX3);
90     } else if (gpio > 5) {
91         addr = AR_HOSTIF_REG(ah, AR_GPIO_OUTPUT_MUX2);
92     } else {
93         addr = AR_HOSTIF_REG(ah, AR_GPIO_OUTPUT_MUX1);
94     }
95 
96     /*
97      * 5 bits per GPIO pin.
98      * Bits 0..4 for 1st pin in that mux,
99      * bits 5..9 for 2nd pin, etc.
100      */
101     gpio_shift = (gpio % 6) * 5;
102 
103     OS_REG_RMW(ah, addr, (type << gpio_shift), (0x1f << gpio_shift));
104 }
105 
106 /*
107  * Configure GPIO Output lines
108  */
109 HAL_BOOL
110 ar9300_gpio_cfg_output(
111     struct ath_hal *ah,
112     u_int32_t gpio,
113     HAL_GPIO_MUX_TYPE hal_signal_type)
114 {
115     u_int32_t    ah_signal_type;
116     u_int32_t    gpio_shift;
117     u_int8_t    smart_ant = 0;
118     static const u_int32_t    mux_signal_conversion_table[] = {
119                     /* HAL_GPIO_OUTPUT_MUX_AS_OUTPUT             */
120         AR_GPIO_OUTPUT_MUX_AS_OUTPUT,
121                     /* HAL_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED */
122         AR_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED,
123                     /* HAL_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED     */
124         AR_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED,
125                     /* HAL_GPIO_OUTPUT_MUX_AS_MAC_NETWORK_LED    */
126         AR_GPIO_OUTPUT_MUX_AS_MAC_NETWORK_LED,
127                     /* HAL_GPIO_OUTPUT_MUX_AS_MAC_POWER_LED      */
128         AR_GPIO_OUTPUT_MUX_AS_MAC_POWER_LED,
129                     /* HAL_GPIO_OUTPUT_MUX_AS_WLAN_ACTIVE        */
130         AR_GPIO_OUTPUT_MUX_AS_RX_CLEAR_EXTERNAL,
131                     /* HAL_GPIO_OUTPUT_MUX_AS_TX_FRAME           */
132         AR_GPIO_OUTPUT_MUX_AS_TX_FRAME,
133                     /* HAL_GPIO_OUTPUT_MUX_AS_MCI_WLAN_DATA      */
134         AR_GPIO_OUTPUT_MUX_AS_MCI_WLAN_DATA,
135                     /* HAL_GPIO_OUTPUT_MUX_AS_MCI_WLAN_CLK       */
136         AR_GPIO_OUTPUT_MUX_AS_MCI_WLAN_CLK,
137                     /* HAL_GPIO_OUTPUT_MUX_AS_MCI_BT_DATA        */
138         AR_GPIO_OUTPUT_MUX_AS_MCI_BT_DATA,
139                     /* HAL_GPIO_OUTPUT_MUX_AS_MCI_BT_CLK         */
140         AR_GPIO_OUTPUT_MUX_AS_MCI_BT_CLK,
141 	            /* HAL_GPIO_OUTPUT_MUX_AS_WL_IN_TX           */
142         AR_GPIO_OUTPUT_MUX_AS_WL_IN_TX,
143                     /* HAL_GPIO_OUTPUT_MUX_AS_WL_IN_RX           */
144         AR_GPIO_OUTPUT_MUX_AS_WL_IN_RX,
145                     /* HAL_GPIO_OUTPUT_MUX_AS_BT_IN_TX           */
146         AR_GPIO_OUTPUT_MUX_AS_BT_IN_TX,
147                     /* HAL_GPIO_OUTPUT_MUX_AS_BT_IN_RX           */
148         AR_GPIO_OUTPUT_MUX_AS_BT_IN_RX,
149                     /* HAL_GPIO_OUTPUT_MUX_AS_RUCKUS_STROBE      */
150         AR_GPIO_OUTPUT_MUX_AS_RUCKUS_STROBE,
151                     /* HAL_GPIO_OUTPUT_MUX_AS_RUCKUS_DATA        */
152         AR_GPIO_OUTPUT_MUX_AS_RUCKUS_DATA,
153                     /* HAL_GPIO_OUTPUT_MUX_AS_SMARTANT_CTRL0     */
154         AR_GPIO_OUTPUT_MUX_AS_SMARTANT_CTRL0,
155                     /* HAL_GPIO_OUTPUT_MUX_AS_SMARTANT_CTRL1     */
156         AR_GPIO_OUTPUT_MUX_AS_SMARTANT_CTRL1,
157                     /* HAL_GPIO_OUTPUT_MUX_AS_SMARTANT_CTRL2     */
158         AR_GPIO_OUTPUT_MUX_AS_SMARTANT_CTRL2,
159                     /* HAL_GPIO_OUTPUT_MUX_AS_SMARTANT_SWCOM3    */
160         AR_GPIO_OUTPUT_MUX_AS_SWCOM3,
161     };
162 
163     HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.halNumGpioPins);
164     if ((gpio == AR9382_GPIO_PIN_8_RESERVED)  ||
165         (gpio == AR9382_GPIO_9_INPUT_ONLY))
166     {
167         return AH_FALSE;
168     }
169 
170     /* Convert HAL signal type definitions to hardware-specific values. */
171     if ((int) hal_signal_type < ARRAY_LENGTH(mux_signal_conversion_table))
172     {
173         ah_signal_type = mux_signal_conversion_table[hal_signal_type];
174     } else {
175         return AH_FALSE;
176     }
177 
178     if (gpio <= AR9382_MAX_JTAG_GPIO_PIN_NUM) {
179         OS_REG_SET_BIT(ah,
180             AR_HOSTIF_REG(ah, AR_GPIO_INPUT_EN_VAL), AR_GPIO_JTAG_DISABLE);
181     }
182 
183 #if UMAC_SUPPORT_SMARTANTENNA
184     /* Get the pin and func values for smart antenna */
185     switch (ah_signal_type)
186     {
187         case AR_GPIO_OUTPUT_MUX_AS_SMARTANT_CTRL0:
188             gpio = ATH_GPIOPIN_ANTCHAIN0;
189             ah_signal_type = ATH_GPIOFUNC_ANTCHAIN0;
190             smart_ant = 1;
191             break;
192         case AR_GPIO_OUTPUT_MUX_AS_SMARTANT_CTRL1:
193             gpio = ATH_GPIOPIN_ANTCHAIN1;
194             ah_signal_type = ATH_GPIOFUNC_ANTCHAIN1;
195             smart_ant = 1;
196             break;
197         case AR_GPIO_OUTPUT_MUX_AS_SMARTANT_CTRL2:
198             gpio = ATH_GPIOPIN_ANTCHAIN2;
199             ah_signal_type = ATH_GPIOFUNC_ANTCHAIN2;
200             smart_ant = 1;
201             break;
202 #if ATH_SMARTANTENNA_ROUTE_SWCOM_TO_GPIO
203         case AR_GPIO_OUTPUT_MUX_AS_SWCOM3:
204             gpio = ATH_GPIOPIN_ROUTE_SWCOM3;
205             ah_signal_type = ATH_GPIOFUNC_ROUTE_SWCOM3;
206             smart_ant = 1;
207             break;
208 #endif
209         default:
210             break;
211     }
212 #endif
213 
214     if (smart_ant && (AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)))
215     {
216 #if UMAC_SUPPORT_SMARTANTENNA
217         ar9340_soc_gpio_cfg_output_mux(ah, gpio, ah_signal_type);
218 #endif
219         return AH_TRUE;
220     } else
221     {
222         /* Configure the MUX */
223         ar9300_gpio_cfg_output_mux(ah, gpio, ah_signal_type);
224     }
225 
226     /* 2 bits per output mode */
227     gpio_shift = 2 * gpio;
228 
229     OS_REG_RMW(ah,
230                AR_HOSTIF_REG(ah, AR_GPIO_OE_OUT),
231                (AR_GPIO_OE_OUT_DRV_ALL << gpio_shift),
232                (AR_GPIO_OE_OUT_DRV << gpio_shift));
233     return AH_TRUE;
234 }
235 
236 /*
237  * Configure GPIO Output lines -LED off
238  */
239 HAL_BOOL
240 ar9300_gpio_cfg_output_led_off(
241     struct ath_hal *ah,
242     u_int32_t gpio,
243     HAL_GPIO_MUX_TYPE halSignalType)
244 {
245 #define N(a)    (sizeof(a) / sizeof(a[0]))
246     u_int32_t    ah_signal_type;
247     u_int32_t    gpio_shift;
248     u_int8_t    smart_ant = 0;
249 
250     static const u_int32_t    mux_signal_conversion_table[] = {
251         /* HAL_GPIO_OUTPUT_MUX_AS_OUTPUT             */
252         AR_GPIO_OUTPUT_MUX_AS_OUTPUT,
253         /* HAL_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED */
254         AR_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED,
255         /* HAL_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED     */
256         AR_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED,
257         /* HAL_GPIO_OUTPUT_MUX_AS_MAC_NETWORK_LED    */
258         AR_GPIO_OUTPUT_MUX_AS_MAC_NETWORK_LED,
259         /* HAL_GPIO_OUTPUT_MUX_AS_MAC_POWER_LED      */
260         AR_GPIO_OUTPUT_MUX_AS_MAC_POWER_LED,
261         /* HAL_GPIO_OUTPUT_MUX_AS_WLAN_ACTIVE        */
262         AR_GPIO_OUTPUT_MUX_AS_RX_CLEAR_EXTERNAL,
263         /* HAL_GPIO_OUTPUT_MUX_AS_TX_FRAME           */
264         AR_GPIO_OUTPUT_MUX_AS_TX_FRAME,
265         /* HAL_GPIO_OUTPUT_MUX_AS_MCI_WLAN_DATA      */
266         AR_GPIO_OUTPUT_MUX_AS_MCI_WLAN_DATA,
267         /* HAL_GPIO_OUTPUT_MUX_AS_MCI_WLAN_CLK       */
268         AR_GPIO_OUTPUT_MUX_AS_MCI_WLAN_CLK,
269         /* HAL_GPIO_OUTPUT_MUX_AS_MCI_BT_DATA        */
270         AR_GPIO_OUTPUT_MUX_AS_MCI_BT_DATA,
271         /* HAL_GPIO_OUTPUT_MUX_AS_MCI_BT_CLK         */
272         AR_GPIO_OUTPUT_MUX_AS_MCI_BT_CLK,
273         /* HAL_GPIO_OUTPUT_MUX_AS_WL_IN_TX           */
274         AR_GPIO_OUTPUT_MUX_AS_WL_IN_TX,
275         /* HAL_GPIO_OUTPUT_MUX_AS_WL_IN_RX           */
276         AR_GPIO_OUTPUT_MUX_AS_WL_IN_RX,
277         /* HAL_GPIO_OUTPUT_MUX_AS_BT_IN_TX           */
278         AR_GPIO_OUTPUT_MUX_AS_BT_IN_TX,
279         /* HAL_GPIO_OUTPUT_MUX_AS_BT_IN_RX           */
280         AR_GPIO_OUTPUT_MUX_AS_BT_IN_RX,
281         AR_GPIO_OUTPUT_MUX_AS_RUCKUS_STROBE,
282         AR_GPIO_OUTPUT_MUX_AS_RUCKUS_DATA,
283         AR_GPIO_OUTPUT_MUX_AS_SMARTANT_CTRL0,
284         AR_GPIO_OUTPUT_MUX_AS_SMARTANT_CTRL1,
285         AR_GPIO_OUTPUT_MUX_AS_SMARTANT_CTRL2
286     };
287     HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.hal_num_gpio_pins);
288 
289     /* Convert HAL signal type definitions to hardware-specific values. */
290     if ((int) halSignalType < ARRAY_LENGTH(mux_signal_conversion_table))
291     {
292         ah_signal_type = mux_signal_conversion_table[halSignalType];
293     } else {
294         return AH_FALSE;
295     }
296 #if UMAC_SUPPORT_SMARTANTENNA
297     /* Get the pin and func values for smart antenna */
298     switch (halSignalType)
299     {
300         case AR_GPIO_OUTPUT_MUX_AS_SMARTANT_CTRL0:
301             gpio = ATH_GPIOPIN_ANTCHAIN0;
302             ah_signal_type = ATH_GPIOFUNC_ANTCHAIN0;
303             smart_ant = 1;
304             break;
305         case AR_GPIO_OUTPUT_MUX_AS_SMARTANT_CTRL1:
306             gpio = ATH_GPIOPIN_ANTCHAIN1;
307             ah_signal_type = ATH_GPIOFUNC_ANTCHAIN1;
308             smart_ant = 1;
309             break;
310         case AR_GPIO_OUTPUT_MUX_AS_SMARTANT_CTRL2:
311             gpio = ATH_GPIOPIN_ANTCHAIN2;
312             ah_signal_type = ATH_GPIOFUNC_ANTCHAIN2;
313             smart_ant = 1;
314             break;
315         default:
316             break;
317     }
318 #endif
319 
320     if (smart_ant && AR_SREV_WASP(ah))
321     {
322         return AH_FALSE;
323     }
324 
325     // Configure the MUX
326     ar9300_gpio_cfg_output_mux(ah, gpio, ah_signal_type);
327 
328     // 2 bits per output mode
329     gpio_shift = 2*gpio;
330 
331     OS_REG_RMW(ah,
332                AR_HOSTIF_REG(ah, AR_GPIO_OE_OUT),
333                (AR_GPIO_OE_OUT_DRV_NO << gpio_shift),
334                (AR_GPIO_OE_OUT_DRV << gpio_shift));
335 
336     return AH_TRUE;
337 #undef N
338 }
339 
340 /*
341  * Configure GPIO Input lines
342  */
343 HAL_BOOL
344 ar9300_gpio_cfg_input(struct ath_hal *ah, u_int32_t gpio)
345 {
346     u_int32_t    gpio_shift;
347 
348     HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.halNumGpioPins);
349     if ((gpio == AR9382_GPIO_PIN_8_RESERVED)  ||
350         (gpio > AR9382_MAX_GPIO_INPUT_PIN_NUM))
351     {
352         return AH_FALSE;
353     }
354 
355     if (gpio <= AR9382_MAX_JTAG_GPIO_PIN_NUM) {
356         OS_REG_SET_BIT(ah,
357             AR_HOSTIF_REG(ah, AR_GPIO_INPUT_EN_VAL), AR_GPIO_JTAG_DISABLE);
358     }
359     /* TODO: configure input mux for AR9300 */
360     /* If configured as input, set output to tristate */
361     gpio_shift = 2 * gpio;
362 
363     OS_REG_RMW(ah,
364                AR_HOSTIF_REG(ah, AR_GPIO_OE_OUT),
365                (AR_GPIO_OE_OUT_DRV_NO << gpio_shift),
366                (AR_GPIO_OE_OUT_DRV << gpio_shift));
367     return AH_TRUE;
368 }
369 
370 /*
371  * Once configured for I/O - set output lines
372  * output the level of GPio PIN without care work mode
373  */
374 HAL_BOOL
375 ar9300_gpio_set(struct ath_hal *ah, u_int32_t gpio, u_int32_t val)
376 {
377     HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.halNumGpioPins);
378     if ((gpio == AR9382_GPIO_PIN_8_RESERVED)  ||
379         (gpio == AR9382_GPIO_9_INPUT_ONLY))
380     {
381         return AH_FALSE;
382     }
383     OS_REG_RMW(ah, AR_HOSTIF_REG(ah, AR_GPIO_OUT),
384         ((val & 1) << gpio), AR_GPIO_BIT(gpio));
385 
386     return AH_TRUE;
387 }
388 
389 /*
390  * Once configured for I/O - get input lines
391  */
392 u_int32_t
393 ar9300_gpio_get(struct ath_hal *ah, u_int32_t gpio)
394 {
395     u_int32_t gpio_in;
396     HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.halNumGpioPins);
397     if (gpio == AR9382_GPIO_PIN_8_RESERVED)
398     {
399         return 0xffffffff;
400     }
401 
402     gpio_in = OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_IN));
403     OS_REG_RMW(ah, AR_HOSTIF_REG(ah, AR_GPIO_IN),
404         (1 << gpio), AR_GPIO_BIT(gpio));
405     return (MS(gpio_in, AR_GPIO_IN_VAL) & AR_GPIO_BIT(gpio)) != 0;
406 }
407 
408 u_int32_t
409 ar9300_gpio_get_intr(struct ath_hal *ah)
410 {
411     unsigned int mask = 0;
412     struct ath_hal_9300 *ahp = AH9300(ah);
413 
414     mask = ahp->ah_gpio_cause;
415     return mask;
416 }
417 
418 /*
419  * Set the GPIO Interrupt
420  * Sync and Async interrupts are both set/cleared.
421  * Async GPIO interrupts may not be raised when the chip is put to sleep.
422  */
423 void
424 ar9300_gpio_set_intr(struct ath_hal *ah, u_int gpio, u_int32_t ilevel)
425 {
426 
427 
428     int i, reg_bit;
429     u_int32_t reg_val;
430     u_int32_t regs[2], shifts[2];
431 
432 #ifdef AH_ASSERT
433     u_int32_t gpio_mask;
434     u_int32_t old_field_val = 0, field_val = 0;
435 #endif
436 
437 #ifdef ATH_GPIO_USE_ASYNC_CAUSE
438     regs[0] = AR_HOSTIF_REG(ah, AR_INTR_ASYNC_ENABLE);
439     regs[1] = AR_HOSTIF_REG(ah, AR_INTR_ASYNC_MASK);
440     shifts[0] = AR_INTR_ASYNC_ENABLE_GPIO_S;
441     shifts[1] = AR_INTR_ASYNC_MASK_GPIO_S;
442 #else
443     regs[0] = AR_HOSTIF_REG(ah, AR_INTR_SYNC_ENABLE);
444     regs[1] = AR_HOSTIF_REG(ah, AR_INTR_SYNC_MASK);
445     shifts[0] = AR_INTR_SYNC_ENABLE_GPIO_S;
446     shifts[1] = AR_INTR_SYNC_MASK_GPIO_S;
447 #endif
448 
449     HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.halNumGpioPins);
450 
451     if ((gpio == AR9382_GPIO_PIN_8_RESERVED) ||
452         (gpio > AR9382_MAX_GPIO_INPUT_PIN_NUM))
453     {
454         return;
455     }
456 
457 #ifdef AH_ASSERT
458     gpio_mask = (1 << AH_PRIVATE(ah)->ah_caps.halNumGpioPins) - 1;
459 #endif
460     if (ilevel == HAL_GPIO_INTR_DISABLE) {
461         /* clear this GPIO's bit in the interrupt registers */
462         for (i = 0; i < ARRAY_LENGTH(regs); i++) {
463             reg_val = OS_REG_READ(ah, regs[i]);
464             reg_bit = shifts[i] + gpio;
465             reg_val &= ~(1 << reg_bit);
466             OS_REG_WRITE(ah, regs[i], reg_val);
467 
468             /* check that each register has same GPIOs enabled */
469 #ifdef AH_ASSERT
470             field_val = (reg_val >> shifts[i]) & gpio_mask;
471             HALASSERT(i == 0 || old_field_val == field_val);
472             old_field_val = field_val;
473 #endif
474         }
475 
476     } else {
477         reg_val = OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_INTR_POL));
478         reg_bit = gpio;
479         if (ilevel == HAL_GPIO_INTR_HIGH) {
480             /* 0 == interrupt on pin high */
481             reg_val &= ~(1 << reg_bit);
482         } else if (ilevel == HAL_GPIO_INTR_LOW) {
483             /* 1 == interrupt on pin low */
484             reg_val |= (1 << reg_bit);
485         }
486         OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_GPIO_INTR_POL), reg_val);
487 
488         /* set this GPIO's bit in the interrupt registers */
489         for (i = 0; i < ARRAY_LENGTH(regs); i++) {
490             reg_val = OS_REG_READ(ah, regs[i]);
491             reg_bit = shifts[i] + gpio;
492             reg_val |= (1 << reg_bit);
493             OS_REG_WRITE(ah, regs[i], reg_val);
494 
495             /* check that each register has same GPIOs enabled */
496 #ifdef AH_ASSERT
497             field_val = (reg_val >> shifts[i]) & gpio_mask;
498             HALASSERT(i == 0 || old_field_val == field_val);
499             old_field_val = field_val;
500 #endif
501         }
502     }
503 }
504 
505 u_int32_t
506 ar9300_gpio_get_polarity(struct ath_hal *ah)
507 {
508     return OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_INTR_POL));
509 
510 }
511 
512 void
513 ar9300_gpio_set_polarity(struct ath_hal *ah, u_int32_t pol_map,
514                          u_int32_t changed_mask)
515 {
516     u_int32_t gpio_mask;
517 
518     gpio_mask = (1 << AH_PRIVATE(ah)->ah_caps.halNumGpioPins) - 1;
519     OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_GPIO_INTR_POL), gpio_mask & pol_map);
520 
521 #ifndef ATH_GPIO_USE_ASYNC_CAUSE
522     /*
523      * For SYNC_CAUSE type interrupts, we need to clear the cause register
524      * explicitly. Otherwise an interrupt with the original polarity setting
525      * will come up immediately (if there is already an interrupt source),
526      * which is not what we want usually.
527      */
528     OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_CAUSE_CLR),
529                  changed_mask << AR_INTR_SYNC_ENABLE_GPIO_S);
530     OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_CAUSE_CLR));
531 #endif
532 }
533 
534 /*
535  * get the GPIO input pin mask
536  * gpio0 - gpio13
537  * gpio8, gpio11, regard as reserved by the chip ar9382
538  */
539 
540 u_int32_t
541 ar9300_gpio_get_mask(struct ath_hal *ah)
542 {
543     u_int32_t mask = (1 << (AR9382_MAX_GPIO_INPUT_PIN_NUM + 1) ) - 1;
544 
545     if (AH_PRIVATE(ah)->ah_devid == AR9300_DEVID_AR9380_PCIE) {
546         mask = (1 << AR9382_MAX_GPIO_PIN_NUM) - 1;
547         mask &= ~(1 << AR9382_GPIO_PIN_8_RESERVED);
548     }
549     return mask;
550 }
551 
552 int
553 ar9300_gpio_set_mask(struct ath_hal *ah, u_int32_t mask, u_int32_t pol_map)
554 {
555     u_int32_t invalid = ~((1 << (AR9382_MAX_GPIO_INPUT_PIN_NUM + 1)) - 1);
556 
557     if (AH_PRIVATE(ah)->ah_devid == AR9300_DEVID_AR9380_PCIE) {
558         invalid = ~((1 << AR9382_MAX_GPIO_PIN_NUM) - 1);
559         invalid |= 1 << AR9382_GPIO_PIN_8_RESERVED;
560     }
561     if (mask & invalid) {
562         ath_hal_printf(ah, "%s: invalid GPIO mask 0x%x\n", __func__, mask);
563         return -1;
564     }
565     AH9300(ah)->ah_gpio_mask = mask;
566     OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_GPIO_INTR_POL), mask & pol_map);
567 
568     return 0;
569 }
570 
571 #ifdef AH_DEBUG
572 void ar9300_gpio_show(struct ath_hal *ah);
573 void ar9300_gpio_show(struct ath_hal *ah)
574 {
575     ath_hal_printf(ah, "--- 9382 GPIOs ---(ah=%p)\n", ah );
576     ath_hal_printf(ah,
577         "AH9300(_ah)->ah_hostifregs:%p\r\n", &(AH9300(ah)->ah_hostifregs));
578     ath_hal_printf(ah,
579         "GPIO_OUT:         0x%08X\n",
580         OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_OUT)));
581     ath_hal_printf(ah,
582         "GPIO_IN:          0x%08X\n",
583          OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_IN)));
584     ath_hal_printf(ah,
585         "GPIO_OE:          0x%08X\n",
586          OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_OE_OUT)));
587     ath_hal_printf(ah,
588         "GPIO_OE1_OUT:     0x%08X\n",
589          OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_OE1_OUT)));
590     ath_hal_printf(ah,
591         "GPIO_INTR_POLAR:  0x%08X\n",
592          OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_INTR_POL)));
593     ath_hal_printf(ah,
594         "GPIO_INPUT_VALUE: 0x%08X\n",
595          OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_INPUT_EN_VAL)));
596     ath_hal_printf(ah,
597         "GPIO_INPUT_MUX1:  0x%08X\n",
598          OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_INPUT_MUX1)));
599     ath_hal_printf(ah,
600         "GPIO_INPUT_MUX2:  0x%08X\n",
601          OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_INPUT_MUX2)));
602     ath_hal_printf(ah,
603         "GPIO_OUTPUT_MUX1: 0x%08X\n",
604          OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_OUTPUT_MUX1)));
605     ath_hal_printf(ah,
606         "GPIO_OUTPUT_MUX2: 0x%08X\n",
607          OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_OUTPUT_MUX2)));
608     ath_hal_printf(ah,
609         "GPIO_OUTPUT_MUX3: 0x%08X\n",
610          OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_OUTPUT_MUX3)));
611     ath_hal_printf(ah,
612         "GPIO_INPUT_STATE: 0x%08X\n",
613          OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INPUT_STATE)));
614     ath_hal_printf(ah,
615         "GPIO_PDPU:        0x%08X\n",
616          OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_PDPU)));
617     ath_hal_printf(ah,
618         "GPIO_DS:          0x%08X\n",
619          OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_DS)));
620     ath_hal_printf(ah,
621         "AR_INTR_ASYNC_ENABLE: 0x%08X\n",
622          OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_ASYNC_ENABLE)));
623     ath_hal_printf(ah,
624         "AR_INTR_ASYNC_MASK:   0x%08X\n",
625          OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_ASYNC_MASK)));
626     ath_hal_printf(ah,
627         "AR_INTR_SYNC_ENABLE:  0x%08X\n",
628          OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_ENABLE)));
629     ath_hal_printf(ah,
630         "AR_INTR_SYNC_MASK:    0x%08X\n",
631          OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_MASK)));
632     ath_hal_printf(ah,
633         "AR_INTR_ASYNC_CAUSE:  0x%08X\n",
634          OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_ASYNC_CAUSE)));
635     ath_hal_printf(ah,
636         "AR_INTR_SYNC_CAUSE:   0x%08X\n",
637          OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_CAUSE)));
638 
639 }
640 #endif /*AH_DEBUG*/
641