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