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
36static 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
81static void
82ar9300_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 */
109HAL_BOOL
110ar9300_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_PIN_11_RESERVED) ||
166        (gpio == AR9382_GPIO_9_INPUT_ONLY))
167    {
168        return AH_FALSE;
169    }
170
171    /* Convert HAL signal type definitions to hardware-specific values. */
172    if ((int) hal_signal_type < ARRAY_LENGTH(mux_signal_conversion_table))
173    {
174        ah_signal_type = mux_signal_conversion_table[hal_signal_type];
175    } else {
176        return AH_FALSE;
177    }
178
179    if (gpio <= AR9382_MAX_JTAG_GPIO_PIN_NUM) {
180        OS_REG_SET_BIT(ah,
181            AR_HOSTIF_REG(ah, AR_GPIO_INPUT_EN_VAL), AR_GPIO_JTAG_DISABLE);
182    }
183
184#if UMAC_SUPPORT_SMARTANTENNA
185    /* Get the pin and func values for smart antenna */
186    switch (ah_signal_type)
187    {
188        case AR_GPIO_OUTPUT_MUX_AS_SMARTANT_CTRL0:
189            gpio = ATH_GPIOPIN_ANTCHAIN0;
190            ah_signal_type = ATH_GPIOFUNC_ANTCHAIN0;
191            smart_ant = 1;
192            break;
193        case AR_GPIO_OUTPUT_MUX_AS_SMARTANT_CTRL1:
194            gpio = ATH_GPIOPIN_ANTCHAIN1;
195            ah_signal_type = ATH_GPIOFUNC_ANTCHAIN1;
196            smart_ant = 1;
197            break;
198        case AR_GPIO_OUTPUT_MUX_AS_SMARTANT_CTRL2:
199            gpio = ATH_GPIOPIN_ANTCHAIN2;
200            ah_signal_type = ATH_GPIOFUNC_ANTCHAIN2;
201            smart_ant = 1;
202            break;
203#if ATH_SMARTANTENNA_ROUTE_SWCOM_TO_GPIO
204        case AR_GPIO_OUTPUT_MUX_AS_SWCOM3:
205            gpio = ATH_GPIOPIN_ROUTE_SWCOM3;
206            ah_signal_type = ATH_GPIOFUNC_ROUTE_SWCOM3;
207            smart_ant = 1;
208            break;
209#endif
210        default:
211            break;
212    }
213#endif
214
215    if (smart_ant && (AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)))
216    {
217#if UMAC_SUPPORT_SMARTANTENNA
218        ar9340_soc_gpio_cfg_output_mux(ah, gpio, ah_signal_type);
219#endif
220        return AH_TRUE;
221    } else
222    {
223        /* Configure the MUX */
224        ar9300_gpio_cfg_output_mux(ah, gpio, ah_signal_type);
225    }
226
227    /* 2 bits per output mode */
228    gpio_shift = 2 * gpio;
229
230    OS_REG_RMW(ah,
231               AR_HOSTIF_REG(ah, AR_GPIO_OE_OUT),
232               (AR_GPIO_OE_OUT_DRV_ALL << gpio_shift),
233               (AR_GPIO_OE_OUT_DRV << gpio_shift));
234    return AH_TRUE;
235}
236
237/*
238 * Configure GPIO Output lines -LED off
239 */
240HAL_BOOL
241ar9300_gpio_cfg_output_led_off(
242    struct ath_hal *ah,
243    u_int32_t gpio,
244    HAL_GPIO_MUX_TYPE halSignalType)
245{
246#define N(a)    (sizeof(a) / sizeof(a[0]))
247    u_int32_t    ah_signal_type;
248    u_int32_t    gpio_shift;
249    u_int8_t    smart_ant = 0;
250
251    static const u_int32_t    mux_signal_conversion_table[] = {
252        /* HAL_GPIO_OUTPUT_MUX_AS_OUTPUT             */
253        AR_GPIO_OUTPUT_MUX_AS_OUTPUT,
254        /* HAL_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED */
255        AR_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED,
256        /* HAL_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED     */
257        AR_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED,
258        /* HAL_GPIO_OUTPUT_MUX_AS_MAC_NETWORK_LED    */
259        AR_GPIO_OUTPUT_MUX_AS_MAC_NETWORK_LED,
260        /* HAL_GPIO_OUTPUT_MUX_AS_MAC_POWER_LED      */
261        AR_GPIO_OUTPUT_MUX_AS_MAC_POWER_LED,
262        /* HAL_GPIO_OUTPUT_MUX_AS_WLAN_ACTIVE        */
263        AR_GPIO_OUTPUT_MUX_AS_RX_CLEAR_EXTERNAL,
264        /* HAL_GPIO_OUTPUT_MUX_AS_TX_FRAME           */
265        AR_GPIO_OUTPUT_MUX_AS_TX_FRAME,
266        /* HAL_GPIO_OUTPUT_MUX_AS_MCI_WLAN_DATA      */
267        AR_GPIO_OUTPUT_MUX_AS_MCI_WLAN_DATA,
268        /* HAL_GPIO_OUTPUT_MUX_AS_MCI_WLAN_CLK       */
269        AR_GPIO_OUTPUT_MUX_AS_MCI_WLAN_CLK,
270        /* HAL_GPIO_OUTPUT_MUX_AS_MCI_BT_DATA        */
271        AR_GPIO_OUTPUT_MUX_AS_MCI_BT_DATA,
272        /* HAL_GPIO_OUTPUT_MUX_AS_MCI_BT_CLK         */
273        AR_GPIO_OUTPUT_MUX_AS_MCI_BT_CLK,
274        /* HAL_GPIO_OUTPUT_MUX_AS_WL_IN_TX           */
275        AR_GPIO_OUTPUT_MUX_AS_WL_IN_TX,
276        /* HAL_GPIO_OUTPUT_MUX_AS_WL_IN_RX           */
277        AR_GPIO_OUTPUT_MUX_AS_WL_IN_RX,
278        /* HAL_GPIO_OUTPUT_MUX_AS_BT_IN_TX           */
279        AR_GPIO_OUTPUT_MUX_AS_BT_IN_TX,
280        /* HAL_GPIO_OUTPUT_MUX_AS_BT_IN_RX           */
281        AR_GPIO_OUTPUT_MUX_AS_BT_IN_RX,
282        AR_GPIO_OUTPUT_MUX_AS_RUCKUS_STROBE,
283        AR_GPIO_OUTPUT_MUX_AS_RUCKUS_DATA,
284        AR_GPIO_OUTPUT_MUX_AS_SMARTANT_CTRL0,
285        AR_GPIO_OUTPUT_MUX_AS_SMARTANT_CTRL1,
286        AR_GPIO_OUTPUT_MUX_AS_SMARTANT_CTRL2
287    };
288    HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.hal_num_gpio_pins);
289
290    /* Convert HAL signal type definitions to hardware-specific values. */
291    if ((int) halSignalType < ARRAY_LENGTH(mux_signal_conversion_table))
292    {
293        ah_signal_type = mux_signal_conversion_table[halSignalType];
294    } else {
295        return AH_FALSE;
296    }
297#if UMAC_SUPPORT_SMARTANTENNA
298    /* Get the pin and func values for smart antenna */
299    switch (halSignalType)
300    {
301        case AR_GPIO_OUTPUT_MUX_AS_SMARTANT_CTRL0:
302            gpio = ATH_GPIOPIN_ANTCHAIN0;
303            ah_signal_type = ATH_GPIOFUNC_ANTCHAIN0;
304            smart_ant = 1;
305            break;
306        case AR_GPIO_OUTPUT_MUX_AS_SMARTANT_CTRL1:
307            gpio = ATH_GPIOPIN_ANTCHAIN1;
308            ah_signal_type = ATH_GPIOFUNC_ANTCHAIN1;
309            smart_ant = 1;
310            break;
311        case AR_GPIO_OUTPUT_MUX_AS_SMARTANT_CTRL2:
312            gpio = ATH_GPIOPIN_ANTCHAIN2;
313            ah_signal_type = ATH_GPIOFUNC_ANTCHAIN2;
314            smart_ant = 1;
315            break;
316        default:
317            break;
318    }
319#endif
320
321    if (smart_ant && AR_SREV_WASP(ah))
322    {
323        return AH_FALSE;
324    }
325
326    // Configure the MUX
327    ar9300_gpio_cfg_output_mux(ah, gpio, ah_signal_type);
328
329    // 2 bits per output mode
330    gpio_shift = 2*gpio;
331
332    OS_REG_RMW(ah,
333               AR_HOSTIF_REG(ah, AR_GPIO_OE_OUT),
334               (AR_GPIO_OE_OUT_DRV_NO << gpio_shift),
335               (AR_GPIO_OE_OUT_DRV << gpio_shift));
336
337    return AH_TRUE;
338#undef N
339}
340
341/*
342 * Configure GPIO Input lines
343 */
344HAL_BOOL
345ar9300_gpio_cfg_input(struct ath_hal *ah, u_int32_t gpio)
346{
347    u_int32_t    gpio_shift;
348
349    HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.halNumGpioPins);
350    if ((gpio == AR9382_GPIO_PIN_8_RESERVED)  ||
351        (gpio == AR9382_GPIO_PIN_11_RESERVED) ||
352        (gpio > AR9382_MAX_GPIO_INPUT_PIN_NUM))
353    {
354        return AH_FALSE;
355    }
356
357    if (gpio <= AR9382_MAX_JTAG_GPIO_PIN_NUM) {
358        OS_REG_SET_BIT(ah,
359            AR_HOSTIF_REG(ah, AR_GPIO_INPUT_EN_VAL), AR_GPIO_JTAG_DISABLE);
360    }
361    /* TODO: configure input mux for AR9300 */
362    /* If configured as input, set output to tristate */
363    gpio_shift = 2 * gpio;
364
365    OS_REG_RMW(ah,
366               AR_HOSTIF_REG(ah, AR_GPIO_OE_OUT),
367               (AR_GPIO_OE_OUT_DRV_NO << gpio_shift),
368               (AR_GPIO_OE_OUT_DRV << gpio_shift));
369    return AH_TRUE;
370}
371
372/*
373 * Once configured for I/O - set output lines
374 * output the level of GPio PIN without care work mode
375 */
376HAL_BOOL
377ar9300_gpio_set(struct ath_hal *ah, u_int32_t gpio, u_int32_t val)
378{
379    HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.halNumGpioPins);
380    if ((gpio == AR9382_GPIO_PIN_8_RESERVED)  ||
381        (gpio == AR9382_GPIO_PIN_11_RESERVED) ||
382        (gpio == AR9382_GPIO_9_INPUT_ONLY))
383    {
384        return AH_FALSE;
385    }
386    OS_REG_RMW(ah, AR_HOSTIF_REG(ah, AR_GPIO_OUT),
387        ((val & 1) << gpio), AR_GPIO_BIT(gpio));
388
389    return AH_TRUE;
390}
391
392/*
393 * Once configured for I/O - get input lines
394 */
395u_int32_t
396ar9300_gpio_get(struct ath_hal *ah, u_int32_t gpio)
397{
398    u_int32_t gpio_in;
399    HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.halNumGpioPins);
400    if ((gpio == AR9382_GPIO_PIN_8_RESERVED) ||
401        (gpio == AR9382_GPIO_PIN_11_RESERVED))
402    {
403        return 0xffffffff;
404    }
405
406    gpio_in = OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_IN));
407    OS_REG_RMW(ah, AR_HOSTIF_REG(ah, AR_GPIO_IN),
408        (1 << gpio), AR_GPIO_BIT(gpio));
409    return (MS(gpio_in, AR_GPIO_IN_VAL) & AR_GPIO_BIT(gpio)) != 0;
410}
411
412u_int32_t
413ar9300_gpio_get_intr(struct ath_hal *ah)
414{
415    unsigned int mask = 0;
416    struct ath_hal_9300 *ahp = AH9300(ah);
417
418    mask = ahp->ah_gpio_cause;
419    return mask;
420}
421
422/*
423 * Set the GPIO Interrupt
424 * Sync and Async interrupts are both set/cleared.
425 * Async GPIO interrupts may not be raised when the chip is put to sleep.
426 */
427void
428ar9300_gpio_set_intr(struct ath_hal *ah, u_int gpio, u_int32_t ilevel)
429{
430
431
432    int i, reg_bit;
433    u_int32_t reg_val;
434    u_int32_t regs[2], shifts[2];
435
436#ifdef AH_ASSERT
437    u_int32_t gpio_mask;
438    u_int32_t old_field_val = 0, field_val = 0;
439#endif
440
441#ifdef ATH_GPIO_USE_ASYNC_CAUSE
442    regs[0] = AR_HOSTIF_REG(ah, AR_INTR_ASYNC_ENABLE);
443    regs[1] = AR_HOSTIF_REG(ah, AR_INTR_ASYNC_MASK);
444    shifts[0] = AR_INTR_ASYNC_ENABLE_GPIO_S;
445    shifts[1] = AR_INTR_ASYNC_MASK_GPIO_S;
446#else
447    regs[0] = AR_HOSTIF_REG(ah, AR_INTR_SYNC_ENABLE);
448    regs[1] = AR_HOSTIF_REG(ah, AR_INTR_SYNC_MASK);
449    shifts[0] = AR_INTR_SYNC_ENABLE_GPIO_S;
450    shifts[1] = AR_INTR_SYNC_MASK_GPIO_S;
451#endif
452
453    HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.halNumGpioPins);
454
455    if ((gpio == AR9382_GPIO_PIN_8_RESERVED) ||
456        (gpio == AR9382_GPIO_PIN_11_RESERVED) ||
457        (gpio > AR9382_MAX_GPIO_INPUT_PIN_NUM))
458    {
459        return;
460    }
461
462#ifdef AH_ASSERT
463    gpio_mask = (1 << AH_PRIVATE(ah)->ah_caps.halNumGpioPins) - 1;
464#endif
465    if (ilevel == HAL_GPIO_INTR_DISABLE) {
466        /* clear this GPIO's bit in the interrupt registers */
467        for (i = 0; i < ARRAY_LENGTH(regs); i++) {
468            reg_val = OS_REG_READ(ah, regs[i]);
469            reg_bit = shifts[i] + gpio;
470            reg_val &= ~(1 << reg_bit);
471            OS_REG_WRITE(ah, regs[i], reg_val);
472
473            /* check that each register has same GPIOs enabled */
474#ifdef AH_ASSERT
475            field_val = (reg_val >> shifts[i]) & gpio_mask;
476            HALASSERT(i == 0 || old_field_val == field_val);
477            old_field_val = field_val;
478#endif
479        }
480
481    } else {
482        reg_val = OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_INTR_POL));
483        reg_bit = gpio;
484        if (ilevel == HAL_GPIO_INTR_HIGH) {
485            /* 0 == interrupt on pin high */
486            reg_val &= ~(1 << reg_bit);
487        } else if (ilevel == HAL_GPIO_INTR_LOW) {
488            /* 1 == interrupt on pin low */
489            reg_val |= (1 << reg_bit);
490        }
491        OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_GPIO_INTR_POL), reg_val);
492
493        /* set this GPIO's bit in the interrupt registers */
494        for (i = 0; i < ARRAY_LENGTH(regs); i++) {
495            reg_val = OS_REG_READ(ah, regs[i]);
496            reg_bit = shifts[i] + gpio;
497            reg_val |= (1 << reg_bit);
498            OS_REG_WRITE(ah, regs[i], reg_val);
499
500            /* check that each register has same GPIOs enabled */
501#ifdef AH_ASSERT
502            field_val = (reg_val >> shifts[i]) & gpio_mask;
503            HALASSERT(i == 0 || old_field_val == field_val);
504            old_field_val = field_val;
505#endif
506        }
507    }
508}
509
510u_int32_t
511ar9300_gpio_get_polarity(struct ath_hal *ah)
512{
513    return OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_INTR_POL));
514
515}
516
517void
518ar9300_gpio_set_polarity(struct ath_hal *ah, u_int32_t pol_map,
519                         u_int32_t changed_mask)
520{
521    u_int32_t gpio_mask;
522
523    gpio_mask = (1 << AH_PRIVATE(ah)->ah_caps.halNumGpioPins) - 1;
524    OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_GPIO_INTR_POL), gpio_mask & pol_map);
525
526#ifndef ATH_GPIO_USE_ASYNC_CAUSE
527    /*
528     * For SYNC_CAUSE type interrupts, we need to clear the cause register
529     * explicitly. Otherwise an interrupt with the original polarity setting
530     * will come up immediately (if there is already an interrupt source),
531     * which is not what we want usually.
532     */
533    OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_CAUSE_CLR),
534                 changed_mask << AR_INTR_SYNC_ENABLE_GPIO_S);
535    OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_CAUSE_CLR));
536#endif
537}
538
539/*
540 * get the GPIO input pin mask
541 * gpio0 - gpio13
542 * gpio8, gpio11, regard as reserved by the chip ar9382
543 */
544
545u_int32_t
546ar9300_gpio_get_mask(struct ath_hal *ah)
547{
548    u_int32_t mask = (1 << (AR9382_MAX_GPIO_INPUT_PIN_NUM + 1) ) - 1;
549
550    if (AH_PRIVATE(ah)->ah_devid == AR9300_DEVID_AR9380_PCIE) {
551        mask = (1 << AR9382_MAX_GPIO_PIN_NUM) - 1;
552        mask &= ~(1 << AR9382_GPIO_PIN_8_RESERVED |
553                  1 << AR9382_GPIO_PIN_11_RESERVED);
554    }
555    return mask;
556}
557
558int
559ar9300_gpio_set_mask(struct ath_hal *ah, u_int32_t mask, u_int32_t pol_map)
560{
561    u_int32_t invalid = ~((1 << (AR9382_MAX_GPIO_INPUT_PIN_NUM + 1)) - 1);
562
563    if (AH_PRIVATE(ah)->ah_devid == AR9300_DEVID_AR9380_PCIE) {
564        invalid = ~((1 << AR9382_MAX_GPIO_PIN_NUM) - 1);
565        invalid |= 1 << AR9382_GPIO_PIN_8_RESERVED |
566                   1 << AR9382_GPIO_PIN_11_RESERVED;
567    }
568    if (mask & invalid) {
569        ath_hal_printf(ah, "%s: invalid GPIO mask 0x%x\n", __func__, mask);
570        return -1;
571    }
572    AH9300(ah)->ah_gpio_mask = mask;
573    OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_GPIO_INTR_POL), mask & pol_map);
574
575    return 0;
576}
577
578#ifdef AH_DEBUG
579void ar9300_gpio_show(struct ath_hal *ah);
580void ar9300_gpio_show(struct ath_hal *ah)
581{
582    ath_hal_printf(ah, "--- 9382 GPIOs ---(ah=%p)\n", ah );
583    ath_hal_printf(ah,
584        "AH9300(_ah)->ah_hostifregs:%p\r\n", &(AH9300(ah)->ah_hostifregs));
585    ath_hal_printf(ah,
586        "GPIO_OUT:         0x%08X\n",
587        OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_OUT)));
588    ath_hal_printf(ah,
589        "GPIO_IN:          0x%08X\n",
590         OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_IN)));
591    ath_hal_printf(ah,
592        "GPIO_OE:          0x%08X\n",
593         OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_OE_OUT)));
594    ath_hal_printf(ah,
595        "GPIO_OE1_OUT:     0x%08X\n",
596         OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_OE1_OUT)));
597    ath_hal_printf(ah,
598        "GPIO_INTR_POLAR:  0x%08X\n",
599         OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_INTR_POL)));
600    ath_hal_printf(ah,
601        "GPIO_INPUT_VALUE: 0x%08X\n",
602         OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_INPUT_EN_VAL)));
603    ath_hal_printf(ah,
604        "GPIO_INPUT_MUX1:  0x%08X\n",
605         OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_INPUT_MUX1)));
606    ath_hal_printf(ah,
607        "GPIO_INPUT_MUX2:  0x%08X\n",
608         OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_INPUT_MUX2)));
609    ath_hal_printf(ah,
610        "GPIO_OUTPUT_MUX1: 0x%08X\n",
611         OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_OUTPUT_MUX1)));
612    ath_hal_printf(ah,
613        "GPIO_OUTPUT_MUX2: 0x%08X\n",
614         OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_OUTPUT_MUX2)));
615    ath_hal_printf(ah,
616        "GPIO_OUTPUT_MUX3: 0x%08X\n",
617         OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_OUTPUT_MUX3)));
618    ath_hal_printf(ah,
619        "GPIO_INPUT_STATE: 0x%08X\n",
620         OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INPUT_STATE)));
621    ath_hal_printf(ah,
622        "GPIO_PDPU:        0x%08X\n",
623         OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_PDPU)));
624    ath_hal_printf(ah,
625        "GPIO_DS:          0x%08X\n",
626         OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_DS)));
627    ath_hal_printf(ah,
628        "AR_INTR_ASYNC_ENABLE: 0x%08X\n",
629         OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_ASYNC_ENABLE)));
630    ath_hal_printf(ah,
631        "AR_INTR_ASYNC_MASK:   0x%08X\n",
632         OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_ASYNC_MASK)));
633    ath_hal_printf(ah,
634        "AR_INTR_SYNC_ENABLE:  0x%08X\n",
635         OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_ENABLE)));
636    ath_hal_printf(ah,
637        "AR_INTR_SYNC_MASK:    0x%08X\n",
638         OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_MASK)));
639    ath_hal_printf(ah,
640        "AR_INTR_ASYNC_CAUSE:  0x%08X\n",
641         OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_ASYNC_CAUSE)));
642    ath_hal_printf(ah,
643        "AR_INTR_SYNC_CAUSE:   0x%08X\n",
644         OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_CAUSE)));
645
646}
647#endif /*AH_DEBUG*/
648