1250003Sadrian/*
2250003Sadrian * Copyright (c) 2013 Qualcomm Atheros, Inc.
3250003Sadrian *
4250003Sadrian * Permission to use, copy, modify, and/or distribute this software for any
5250003Sadrian * purpose with or without fee is hereby granted, provided that the above
6250003Sadrian * copyright notice and this permission notice appear in all copies.
7250003Sadrian *
8250003Sadrian * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
9250003Sadrian * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10250003Sadrian * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
11250003Sadrian * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12250003Sadrian * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
13250003Sadrian * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14250003Sadrian * PERFORMANCE OF THIS SOFTWARE.
15250003Sadrian */
16250003Sadrian
17250003Sadrian#include "opt_ah.h"
18250003Sadrian
19250003Sadrian#include "ah.h"
20250003Sadrian#include "ah_internal.h"
21250003Sadrian#include "ah_devid.h"
22250003Sadrian#ifdef AH_DEBUG
23250003Sadrian#include "ah_desc.h"                    /* NB: for HAL_PHYERR* */
24250003Sadrian#endif
25250003Sadrian
26250003Sadrian#include "ar9300/ar9300.h"
27250003Sadrian#include "ar9300/ar9300reg.h"
28250003Sadrian#include "ar9300/ar9300phy.h"
29250003Sadrian
30250003Sadrian#define AR_GPIO_BIT(_gpio)                      (1 << (_gpio))
31250003Sadrian
32250003Sadrian/*
33250003Sadrian * Configure GPIO Output Mux control
34250003Sadrian */
35250008Sadrian#if UMAC_SUPPORT_SMARTANTENNA
36250003Sadrianstatic void  ar9340_soc_gpio_cfg_output_mux(
37250003Sadrian    struct ath_hal *ah,
38250003Sadrian    u_int32_t gpio,
39250003Sadrian    u_int32_t ah_signal_type)
40250003Sadrian{
41250003Sadrian#define ADDR_READ(addr)      (*((volatile u_int32_t *)(addr)))
42250003Sadrian#define ADDR_WRITE(addr, b)   (void)((*(volatile u_int32_t *) (addr)) = (b))
43250003Sadrian#define AR9340_SOC_GPIO_FUN0    0xB804002c
44250003Sadrian#define AR9340_SOC_GPIO_OE      0xB8040000
45250003Sadrian#if ATH_SMARTANTENNA_DISABLE_JTAG
46250003Sadrian#define AR9340_SOC_GPIO_FUNCTION   (volatile u_int32_t*) 0xB804006c
47250003Sadrian#define WASP_DISABLE_JTAG  0x2
48250003Sadrian#define MAX_JTAG_GPIO_PIN 1
49250003Sadrian#endif
50250003Sadrian    u_int8_t out_func, shift;
51250003Sadrian    u_int32_t  flags;
52250003Sadrian    volatile u_int32_t* address;
53250003Sadrian
54250003Sadrian    if (!ah_signal_type){
55250003Sadrian        return;
56250003Sadrian    }
57250003Sadrian#if ATH_SMARTANTENNA_DISABLE_JTAG
58250003Sadrian/*
59250003Sadrian * To use GPIO pins 0 and 1 for controling antennas, JTAG needs to disabled.
60250003Sadrian */
61250003Sadrian    if (gpio <= MAX_JTAG_GPIO_PIN) {
62250003Sadrian        flags = ADDR_READ(AR9340_SOC_GPIO_FUNCTION);
63250003Sadrian        flags |= WASP_DISABLE_JTAG;
64250003Sadrian        ADDR_WRITE(AR9340_SOC_GPIO_FUNCTION, flags);
65250003Sadrian    }
66250003Sadrian#endif
67250003Sadrian    out_func = gpio / 4;
68250003Sadrian    shift = (gpio % 4);
69250003Sadrian    address = (volatile u_int32_t *)(AR9340_SOC_GPIO_FUN0 + (out_func*4));
70250003Sadrian
71250003Sadrian    flags = ADDR_READ(address);
72250003Sadrian    flags |= ah_signal_type << (8*shift);
73250003Sadrian    ADDR_WRITE(address, flags);
74250003Sadrian    flags = ADDR_READ(AR9340_SOC_GPIO_OE);
75250003Sadrian    flags &= ~(1 << gpio);
76250003Sadrian    ADDR_WRITE(AR9340_SOC_GPIO_OE, flags);
77250003Sadrian
78250003Sadrian}
79250003Sadrian#endif
80250003Sadrian
81250003Sadrianstatic void
82250003Sadrianar9300_gpio_cfg_output_mux(struct ath_hal *ah, u_int32_t gpio, u_int32_t type)
83250003Sadrian{
84250003Sadrian    int          addr;
85250003Sadrian    u_int32_t    gpio_shift;
86250003Sadrian
87250003Sadrian    /* each MUX controls 6 GPIO pins */
88250003Sadrian    if (gpio > 11) {
89250003Sadrian        addr = AR_HOSTIF_REG(ah, AR_GPIO_OUTPUT_MUX3);
90250003Sadrian    } else if (gpio > 5) {
91250003Sadrian        addr = AR_HOSTIF_REG(ah, AR_GPIO_OUTPUT_MUX2);
92250003Sadrian    } else {
93250003Sadrian        addr = AR_HOSTIF_REG(ah, AR_GPIO_OUTPUT_MUX1);
94250003Sadrian    }
95250003Sadrian
96250003Sadrian    /*
97250003Sadrian     * 5 bits per GPIO pin.
98250003Sadrian     * Bits 0..4 for 1st pin in that mux,
99250003Sadrian     * bits 5..9 for 2nd pin, etc.
100250003Sadrian     */
101250003Sadrian    gpio_shift = (gpio % 6) * 5;
102250003Sadrian
103250003Sadrian    OS_REG_RMW(ah, addr, (type << gpio_shift), (0x1f << gpio_shift));
104250003Sadrian}
105250003Sadrian
106250003Sadrian/*
107250003Sadrian * Configure GPIO Output lines
108250003Sadrian */
109250003SadrianHAL_BOOL
110250003Sadrianar9300_gpio_cfg_output(
111250003Sadrian    struct ath_hal *ah,
112250003Sadrian    u_int32_t gpio,
113250008Sadrian    HAL_GPIO_MUX_TYPE hal_signal_type)
114250003Sadrian{
115250003Sadrian    u_int32_t    ah_signal_type;
116250003Sadrian    u_int32_t    gpio_shift;
117250003Sadrian    u_int8_t    smart_ant = 0;
118250003Sadrian    static const u_int32_t    mux_signal_conversion_table[] = {
119250003Sadrian                    /* HAL_GPIO_OUTPUT_MUX_AS_OUTPUT             */
120250003Sadrian        AR_GPIO_OUTPUT_MUX_AS_OUTPUT,
121250003Sadrian                    /* HAL_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED */
122250003Sadrian        AR_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED,
123250003Sadrian                    /* HAL_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED     */
124250003Sadrian        AR_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED,
125250003Sadrian                    /* HAL_GPIO_OUTPUT_MUX_AS_MAC_NETWORK_LED    */
126250003Sadrian        AR_GPIO_OUTPUT_MUX_AS_MAC_NETWORK_LED,
127250003Sadrian                    /* HAL_GPIO_OUTPUT_MUX_AS_MAC_POWER_LED      */
128250003Sadrian        AR_GPIO_OUTPUT_MUX_AS_MAC_POWER_LED,
129250003Sadrian                    /* HAL_GPIO_OUTPUT_MUX_AS_WLAN_ACTIVE        */
130250003Sadrian        AR_GPIO_OUTPUT_MUX_AS_RX_CLEAR_EXTERNAL,
131250003Sadrian                    /* HAL_GPIO_OUTPUT_MUX_AS_TX_FRAME           */
132250003Sadrian        AR_GPIO_OUTPUT_MUX_AS_TX_FRAME,
133250003Sadrian                    /* HAL_GPIO_OUTPUT_MUX_AS_MCI_WLAN_DATA      */
134250003Sadrian        AR_GPIO_OUTPUT_MUX_AS_MCI_WLAN_DATA,
135250003Sadrian                    /* HAL_GPIO_OUTPUT_MUX_AS_MCI_WLAN_CLK       */
136250003Sadrian        AR_GPIO_OUTPUT_MUX_AS_MCI_WLAN_CLK,
137250003Sadrian                    /* HAL_GPIO_OUTPUT_MUX_AS_MCI_BT_DATA        */
138250003Sadrian        AR_GPIO_OUTPUT_MUX_AS_MCI_BT_DATA,
139250003Sadrian                    /* HAL_GPIO_OUTPUT_MUX_AS_MCI_BT_CLK         */
140250003Sadrian        AR_GPIO_OUTPUT_MUX_AS_MCI_BT_CLK,
141250003Sadrian	            /* HAL_GPIO_OUTPUT_MUX_AS_WL_IN_TX           */
142250003Sadrian        AR_GPIO_OUTPUT_MUX_AS_WL_IN_TX,
143250003Sadrian                    /* HAL_GPIO_OUTPUT_MUX_AS_WL_IN_RX           */
144250003Sadrian        AR_GPIO_OUTPUT_MUX_AS_WL_IN_RX,
145250003Sadrian                    /* HAL_GPIO_OUTPUT_MUX_AS_BT_IN_TX           */
146250003Sadrian        AR_GPIO_OUTPUT_MUX_AS_BT_IN_TX,
147250003Sadrian                    /* HAL_GPIO_OUTPUT_MUX_AS_BT_IN_RX           */
148250003Sadrian        AR_GPIO_OUTPUT_MUX_AS_BT_IN_RX,
149250003Sadrian                    /* HAL_GPIO_OUTPUT_MUX_AS_RUCKUS_STROBE      */
150250003Sadrian        AR_GPIO_OUTPUT_MUX_AS_RUCKUS_STROBE,
151250003Sadrian                    /* HAL_GPIO_OUTPUT_MUX_AS_RUCKUS_DATA        */
152250003Sadrian        AR_GPIO_OUTPUT_MUX_AS_RUCKUS_DATA,
153250003Sadrian                    /* HAL_GPIO_OUTPUT_MUX_AS_SMARTANT_CTRL0     */
154250003Sadrian        AR_GPIO_OUTPUT_MUX_AS_SMARTANT_CTRL0,
155250003Sadrian                    /* HAL_GPIO_OUTPUT_MUX_AS_SMARTANT_CTRL1     */
156250003Sadrian        AR_GPIO_OUTPUT_MUX_AS_SMARTANT_CTRL1,
157250003Sadrian                    /* HAL_GPIO_OUTPUT_MUX_AS_SMARTANT_CTRL2     */
158250003Sadrian        AR_GPIO_OUTPUT_MUX_AS_SMARTANT_CTRL2,
159250003Sadrian                    /* HAL_GPIO_OUTPUT_MUX_AS_SMARTANT_SWCOM3    */
160250003Sadrian        AR_GPIO_OUTPUT_MUX_AS_SWCOM3,
161250003Sadrian    };
162250003Sadrian
163250008Sadrian    HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.halNumGpioPins);
164250003Sadrian    if ((gpio == AR9382_GPIO_PIN_8_RESERVED)  ||
165250003Sadrian        (gpio == AR9382_GPIO_PIN_11_RESERVED) ||
166250003Sadrian        (gpio == AR9382_GPIO_9_INPUT_ONLY))
167250003Sadrian    {
168250003Sadrian        return AH_FALSE;
169250003Sadrian    }
170250003Sadrian
171250003Sadrian    /* Convert HAL signal type definitions to hardware-specific values. */
172250008Sadrian    if ((int) hal_signal_type < ARRAY_LENGTH(mux_signal_conversion_table))
173250003Sadrian    {
174250003Sadrian        ah_signal_type = mux_signal_conversion_table[hal_signal_type];
175250003Sadrian    } else {
176250003Sadrian        return AH_FALSE;
177250003Sadrian    }
178250003Sadrian
179250003Sadrian    if (gpio <= AR9382_MAX_JTAG_GPIO_PIN_NUM) {
180250003Sadrian        OS_REG_SET_BIT(ah,
181250003Sadrian            AR_HOSTIF_REG(ah, AR_GPIO_INPUT_EN_VAL), AR_GPIO_JTAG_DISABLE);
182250003Sadrian    }
183250003Sadrian
184250003Sadrian#if UMAC_SUPPORT_SMARTANTENNA
185250003Sadrian    /* Get the pin and func values for smart antenna */
186250003Sadrian    switch (ah_signal_type)
187250003Sadrian    {
188250003Sadrian        case AR_GPIO_OUTPUT_MUX_AS_SMARTANT_CTRL0:
189250003Sadrian            gpio = ATH_GPIOPIN_ANTCHAIN0;
190250003Sadrian            ah_signal_type = ATH_GPIOFUNC_ANTCHAIN0;
191250003Sadrian            smart_ant = 1;
192250003Sadrian            break;
193250003Sadrian        case AR_GPIO_OUTPUT_MUX_AS_SMARTANT_CTRL1:
194250003Sadrian            gpio = ATH_GPIOPIN_ANTCHAIN1;
195250003Sadrian            ah_signal_type = ATH_GPIOFUNC_ANTCHAIN1;
196250003Sadrian            smart_ant = 1;
197250003Sadrian            break;
198250003Sadrian        case AR_GPIO_OUTPUT_MUX_AS_SMARTANT_CTRL2:
199250003Sadrian            gpio = ATH_GPIOPIN_ANTCHAIN2;
200250003Sadrian            ah_signal_type = ATH_GPIOFUNC_ANTCHAIN2;
201250003Sadrian            smart_ant = 1;
202250003Sadrian            break;
203250003Sadrian#if ATH_SMARTANTENNA_ROUTE_SWCOM_TO_GPIO
204250003Sadrian        case AR_GPIO_OUTPUT_MUX_AS_SWCOM3:
205250003Sadrian            gpio = ATH_GPIOPIN_ROUTE_SWCOM3;
206250003Sadrian            ah_signal_type = ATH_GPIOFUNC_ROUTE_SWCOM3;
207250003Sadrian            smart_ant = 1;
208250003Sadrian            break;
209250003Sadrian#endif
210250003Sadrian        default:
211250003Sadrian            break;
212250003Sadrian    }
213250003Sadrian#endif
214250003Sadrian
215250003Sadrian    if (smart_ant && (AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)))
216250003Sadrian    {
217250008Sadrian#if UMAC_SUPPORT_SMARTANTENNA
218250003Sadrian        ar9340_soc_gpio_cfg_output_mux(ah, gpio, ah_signal_type);
219250003Sadrian#endif
220250003Sadrian        return AH_TRUE;
221250003Sadrian    } else
222250003Sadrian    {
223250003Sadrian        /* Configure the MUX */
224250003Sadrian        ar9300_gpio_cfg_output_mux(ah, gpio, ah_signal_type);
225250003Sadrian    }
226250003Sadrian
227250003Sadrian    /* 2 bits per output mode */
228250003Sadrian    gpio_shift = 2 * gpio;
229250003Sadrian
230250003Sadrian    OS_REG_RMW(ah,
231250003Sadrian               AR_HOSTIF_REG(ah, AR_GPIO_OE_OUT),
232250003Sadrian               (AR_GPIO_OE_OUT_DRV_ALL << gpio_shift),
233250003Sadrian               (AR_GPIO_OE_OUT_DRV << gpio_shift));
234250003Sadrian    return AH_TRUE;
235250003Sadrian}
236250003Sadrian
237250003Sadrian/*
238250003Sadrian * Configure GPIO Output lines -LED off
239250003Sadrian */
240250003SadrianHAL_BOOL
241250003Sadrianar9300_gpio_cfg_output_led_off(
242250003Sadrian    struct ath_hal *ah,
243250003Sadrian    u_int32_t gpio,
244250008Sadrian    HAL_GPIO_MUX_TYPE halSignalType)
245250003Sadrian{
246250003Sadrian#define N(a)    (sizeof(a) / sizeof(a[0]))
247250003Sadrian    u_int32_t    ah_signal_type;
248250003Sadrian    u_int32_t    gpio_shift;
249250003Sadrian    u_int8_t    smart_ant = 0;
250250003Sadrian
251250003Sadrian    static const u_int32_t    mux_signal_conversion_table[] = {
252250003Sadrian        /* HAL_GPIO_OUTPUT_MUX_AS_OUTPUT             */
253250003Sadrian        AR_GPIO_OUTPUT_MUX_AS_OUTPUT,
254250003Sadrian        /* HAL_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED */
255250003Sadrian        AR_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED,
256250003Sadrian        /* HAL_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED     */
257250003Sadrian        AR_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED,
258250003Sadrian        /* HAL_GPIO_OUTPUT_MUX_AS_MAC_NETWORK_LED    */
259250003Sadrian        AR_GPIO_OUTPUT_MUX_AS_MAC_NETWORK_LED,
260250003Sadrian        /* HAL_GPIO_OUTPUT_MUX_AS_MAC_POWER_LED      */
261250003Sadrian        AR_GPIO_OUTPUT_MUX_AS_MAC_POWER_LED,
262250003Sadrian        /* HAL_GPIO_OUTPUT_MUX_AS_WLAN_ACTIVE        */
263250003Sadrian        AR_GPIO_OUTPUT_MUX_AS_RX_CLEAR_EXTERNAL,
264250003Sadrian        /* HAL_GPIO_OUTPUT_MUX_AS_TX_FRAME           */
265250003Sadrian        AR_GPIO_OUTPUT_MUX_AS_TX_FRAME,
266250003Sadrian        /* HAL_GPIO_OUTPUT_MUX_AS_MCI_WLAN_DATA      */
267250003Sadrian        AR_GPIO_OUTPUT_MUX_AS_MCI_WLAN_DATA,
268250003Sadrian        /* HAL_GPIO_OUTPUT_MUX_AS_MCI_WLAN_CLK       */
269250003Sadrian        AR_GPIO_OUTPUT_MUX_AS_MCI_WLAN_CLK,
270250003Sadrian        /* HAL_GPIO_OUTPUT_MUX_AS_MCI_BT_DATA        */
271250003Sadrian        AR_GPIO_OUTPUT_MUX_AS_MCI_BT_DATA,
272250003Sadrian        /* HAL_GPIO_OUTPUT_MUX_AS_MCI_BT_CLK         */
273250003Sadrian        AR_GPIO_OUTPUT_MUX_AS_MCI_BT_CLK,
274250003Sadrian        /* HAL_GPIO_OUTPUT_MUX_AS_WL_IN_TX           */
275250003Sadrian        AR_GPIO_OUTPUT_MUX_AS_WL_IN_TX,
276250003Sadrian        /* HAL_GPIO_OUTPUT_MUX_AS_WL_IN_RX           */
277250003Sadrian        AR_GPIO_OUTPUT_MUX_AS_WL_IN_RX,
278250003Sadrian        /* HAL_GPIO_OUTPUT_MUX_AS_BT_IN_TX           */
279250003Sadrian        AR_GPIO_OUTPUT_MUX_AS_BT_IN_TX,
280250003Sadrian        /* HAL_GPIO_OUTPUT_MUX_AS_BT_IN_RX           */
281250003Sadrian        AR_GPIO_OUTPUT_MUX_AS_BT_IN_RX,
282250003Sadrian        AR_GPIO_OUTPUT_MUX_AS_RUCKUS_STROBE,
283250003Sadrian        AR_GPIO_OUTPUT_MUX_AS_RUCKUS_DATA,
284250003Sadrian        AR_GPIO_OUTPUT_MUX_AS_SMARTANT_CTRL0,
285250003Sadrian        AR_GPIO_OUTPUT_MUX_AS_SMARTANT_CTRL1,
286250003Sadrian        AR_GPIO_OUTPUT_MUX_AS_SMARTANT_CTRL2
287250003Sadrian    };
288250003Sadrian    HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.hal_num_gpio_pins);
289250003Sadrian
290250003Sadrian    /* Convert HAL signal type definitions to hardware-specific values. */
291250008Sadrian    if ((int) halSignalType < ARRAY_LENGTH(mux_signal_conversion_table))
292250003Sadrian    {
293250003Sadrian        ah_signal_type = mux_signal_conversion_table[halSignalType];
294250003Sadrian    } else {
295250003Sadrian        return AH_FALSE;
296250003Sadrian    }
297250003Sadrian#if UMAC_SUPPORT_SMARTANTENNA
298250003Sadrian    /* Get the pin and func values for smart antenna */
299250003Sadrian    switch (halSignalType)
300250003Sadrian    {
301250003Sadrian        case AR_GPIO_OUTPUT_MUX_AS_SMARTANT_CTRL0:
302250003Sadrian            gpio = ATH_GPIOPIN_ANTCHAIN0;
303250003Sadrian            ah_signal_type = ATH_GPIOFUNC_ANTCHAIN0;
304250003Sadrian            smart_ant = 1;
305250003Sadrian            break;
306250003Sadrian        case AR_GPIO_OUTPUT_MUX_AS_SMARTANT_CTRL1:
307250003Sadrian            gpio = ATH_GPIOPIN_ANTCHAIN1;
308250003Sadrian            ah_signal_type = ATH_GPIOFUNC_ANTCHAIN1;
309250003Sadrian            smart_ant = 1;
310250003Sadrian            break;
311250003Sadrian        case AR_GPIO_OUTPUT_MUX_AS_SMARTANT_CTRL2:
312250003Sadrian            gpio = ATH_GPIOPIN_ANTCHAIN2;
313250003Sadrian            ah_signal_type = ATH_GPIOFUNC_ANTCHAIN2;
314250003Sadrian            smart_ant = 1;
315250003Sadrian            break;
316250003Sadrian        default:
317250003Sadrian            break;
318250003Sadrian    }
319250003Sadrian#endif
320250003Sadrian
321250003Sadrian    if (smart_ant && AR_SREV_WASP(ah))
322250003Sadrian    {
323250003Sadrian        return AH_FALSE;
324250003Sadrian    }
325250003Sadrian
326250003Sadrian    // Configure the MUX
327250003Sadrian    ar9300_gpio_cfg_output_mux(ah, gpio, ah_signal_type);
328250003Sadrian
329250003Sadrian    // 2 bits per output mode
330250003Sadrian    gpio_shift = 2*gpio;
331250003Sadrian
332250003Sadrian    OS_REG_RMW(ah,
333250003Sadrian               AR_HOSTIF_REG(ah, AR_GPIO_OE_OUT),
334250003Sadrian               (AR_GPIO_OE_OUT_DRV_NO << gpio_shift),
335250003Sadrian               (AR_GPIO_OE_OUT_DRV << gpio_shift));
336250003Sadrian
337250003Sadrian    return AH_TRUE;
338250003Sadrian#undef N
339250003Sadrian}
340250003Sadrian
341250003Sadrian/*
342250003Sadrian * Configure GPIO Input lines
343250003Sadrian */
344250003SadrianHAL_BOOL
345250003Sadrianar9300_gpio_cfg_input(struct ath_hal *ah, u_int32_t gpio)
346250003Sadrian{
347250003Sadrian    u_int32_t    gpio_shift;
348250003Sadrian
349250008Sadrian    HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.halNumGpioPins);
350250003Sadrian    if ((gpio == AR9382_GPIO_PIN_8_RESERVED)  ||
351250003Sadrian        (gpio == AR9382_GPIO_PIN_11_RESERVED) ||
352250003Sadrian        (gpio > AR9382_MAX_GPIO_INPUT_PIN_NUM))
353250003Sadrian    {
354250003Sadrian        return AH_FALSE;
355250003Sadrian    }
356250003Sadrian
357250003Sadrian    if (gpio <= AR9382_MAX_JTAG_GPIO_PIN_NUM) {
358250003Sadrian        OS_REG_SET_BIT(ah,
359250003Sadrian            AR_HOSTIF_REG(ah, AR_GPIO_INPUT_EN_VAL), AR_GPIO_JTAG_DISABLE);
360250003Sadrian    }
361250003Sadrian    /* TODO: configure input mux for AR9300 */
362250003Sadrian    /* If configured as input, set output to tristate */
363250003Sadrian    gpio_shift = 2 * gpio;
364250003Sadrian
365250003Sadrian    OS_REG_RMW(ah,
366250003Sadrian               AR_HOSTIF_REG(ah, AR_GPIO_OE_OUT),
367250003Sadrian               (AR_GPIO_OE_OUT_DRV_NO << gpio_shift),
368250003Sadrian               (AR_GPIO_OE_OUT_DRV << gpio_shift));
369250003Sadrian    return AH_TRUE;
370250003Sadrian}
371250003Sadrian
372250003Sadrian/*
373250003Sadrian * Once configured for I/O - set output lines
374250003Sadrian * output the level of GPio PIN without care work mode
375250003Sadrian */
376250003SadrianHAL_BOOL
377250003Sadrianar9300_gpio_set(struct ath_hal *ah, u_int32_t gpio, u_int32_t val)
378250003Sadrian{
379250008Sadrian    HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.halNumGpioPins);
380250003Sadrian    if ((gpio == AR9382_GPIO_PIN_8_RESERVED)  ||
381250003Sadrian        (gpio == AR9382_GPIO_PIN_11_RESERVED) ||
382250003Sadrian        (gpio == AR9382_GPIO_9_INPUT_ONLY))
383250003Sadrian    {
384250003Sadrian        return AH_FALSE;
385250003Sadrian    }
386250003Sadrian    OS_REG_RMW(ah, AR_HOSTIF_REG(ah, AR_GPIO_OUT),
387250003Sadrian        ((val & 1) << gpio), AR_GPIO_BIT(gpio));
388250003Sadrian
389250003Sadrian    return AH_TRUE;
390250003Sadrian}
391250003Sadrian
392250003Sadrian/*
393250003Sadrian * Once configured for I/O - get input lines
394250003Sadrian */
395250003Sadrianu_int32_t
396250003Sadrianar9300_gpio_get(struct ath_hal *ah, u_int32_t gpio)
397250003Sadrian{
398250003Sadrian    u_int32_t gpio_in;
399250008Sadrian    HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.halNumGpioPins);
400250003Sadrian    if ((gpio == AR9382_GPIO_PIN_8_RESERVED) ||
401250003Sadrian        (gpio == AR9382_GPIO_PIN_11_RESERVED))
402250003Sadrian    {
403250003Sadrian        return 0xffffffff;
404250003Sadrian    }
405250003Sadrian
406250003Sadrian    gpio_in = OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_IN));
407250003Sadrian    OS_REG_RMW(ah, AR_HOSTIF_REG(ah, AR_GPIO_IN),
408250003Sadrian        (1 << gpio), AR_GPIO_BIT(gpio));
409250003Sadrian    return (MS(gpio_in, AR_GPIO_IN_VAL) & AR_GPIO_BIT(gpio)) != 0;
410250003Sadrian}
411250003Sadrian
412250003Sadrianu_int32_t
413250003Sadrianar9300_gpio_get_intr(struct ath_hal *ah)
414250003Sadrian{
415250003Sadrian    unsigned int mask = 0;
416250003Sadrian    struct ath_hal_9300 *ahp = AH9300(ah);
417250003Sadrian
418250003Sadrian    mask = ahp->ah_gpio_cause;
419250003Sadrian    return mask;
420250003Sadrian}
421250003Sadrian
422250003Sadrian/*
423250003Sadrian * Set the GPIO Interrupt
424250003Sadrian * Sync and Async interrupts are both set/cleared.
425250003Sadrian * Async GPIO interrupts may not be raised when the chip is put to sleep.
426250003Sadrian */
427250003Sadrianvoid
428250003Sadrianar9300_gpio_set_intr(struct ath_hal *ah, u_int gpio, u_int32_t ilevel)
429250003Sadrian{
430250003Sadrian
431250003Sadrian
432250003Sadrian    int i, reg_bit;
433250003Sadrian    u_int32_t reg_val;
434250003Sadrian    u_int32_t regs[2], shifts[2];
435250003Sadrian
436250003Sadrian#ifdef AH_ASSERT
437250003Sadrian    u_int32_t gpio_mask;
438250003Sadrian    u_int32_t old_field_val = 0, field_val = 0;
439250003Sadrian#endif
440250003Sadrian
441250003Sadrian#ifdef ATH_GPIO_USE_ASYNC_CAUSE
442250003Sadrian    regs[0] = AR_HOSTIF_REG(ah, AR_INTR_ASYNC_ENABLE);
443250003Sadrian    regs[1] = AR_HOSTIF_REG(ah, AR_INTR_ASYNC_MASK);
444250003Sadrian    shifts[0] = AR_INTR_ASYNC_ENABLE_GPIO_S;
445250003Sadrian    shifts[1] = AR_INTR_ASYNC_MASK_GPIO_S;
446250003Sadrian#else
447250003Sadrian    regs[0] = AR_HOSTIF_REG(ah, AR_INTR_SYNC_ENABLE);
448250003Sadrian    regs[1] = AR_HOSTIF_REG(ah, AR_INTR_SYNC_MASK);
449250003Sadrian    shifts[0] = AR_INTR_SYNC_ENABLE_GPIO_S;
450250003Sadrian    shifts[1] = AR_INTR_SYNC_MASK_GPIO_S;
451250003Sadrian#endif
452250003Sadrian
453250008Sadrian    HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.halNumGpioPins);
454250003Sadrian
455250003Sadrian    if ((gpio == AR9382_GPIO_PIN_8_RESERVED) ||
456250003Sadrian        (gpio == AR9382_GPIO_PIN_11_RESERVED) ||
457250003Sadrian        (gpio > AR9382_MAX_GPIO_INPUT_PIN_NUM))
458250003Sadrian    {
459250003Sadrian        return;
460250003Sadrian    }
461250003Sadrian
462250003Sadrian#ifdef AH_ASSERT
463250008Sadrian    gpio_mask = (1 << AH_PRIVATE(ah)->ah_caps.halNumGpioPins) - 1;
464250003Sadrian#endif
465250003Sadrian    if (ilevel == HAL_GPIO_INTR_DISABLE) {
466250003Sadrian        /* clear this GPIO's bit in the interrupt registers */
467250003Sadrian        for (i = 0; i < ARRAY_LENGTH(regs); i++) {
468250003Sadrian            reg_val = OS_REG_READ(ah, regs[i]);
469250003Sadrian            reg_bit = shifts[i] + gpio;
470250003Sadrian            reg_val &= ~(1 << reg_bit);
471250003Sadrian            OS_REG_WRITE(ah, regs[i], reg_val);
472250003Sadrian
473250003Sadrian            /* check that each register has same GPIOs enabled */
474250003Sadrian#ifdef AH_ASSERT
475250003Sadrian            field_val = (reg_val >> shifts[i]) & gpio_mask;
476250003Sadrian            HALASSERT(i == 0 || old_field_val == field_val);
477250003Sadrian            old_field_val = field_val;
478250003Sadrian#endif
479250003Sadrian        }
480250003Sadrian
481250003Sadrian    } else {
482250003Sadrian        reg_val = OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_INTR_POL));
483250003Sadrian        reg_bit = gpio;
484250003Sadrian        if (ilevel == HAL_GPIO_INTR_HIGH) {
485250003Sadrian            /* 0 == interrupt on pin high */
486250003Sadrian            reg_val &= ~(1 << reg_bit);
487250003Sadrian        } else if (ilevel == HAL_GPIO_INTR_LOW) {
488250003Sadrian            /* 1 == interrupt on pin low */
489250003Sadrian            reg_val |= (1 << reg_bit);
490250003Sadrian        }
491250003Sadrian        OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_GPIO_INTR_POL), reg_val);
492250003Sadrian
493250003Sadrian        /* set this GPIO's bit in the interrupt registers */
494250003Sadrian        for (i = 0; i < ARRAY_LENGTH(regs); i++) {
495250003Sadrian            reg_val = OS_REG_READ(ah, regs[i]);
496250003Sadrian            reg_bit = shifts[i] + gpio;
497250003Sadrian            reg_val |= (1 << reg_bit);
498250003Sadrian            OS_REG_WRITE(ah, regs[i], reg_val);
499250003Sadrian
500250003Sadrian            /* check that each register has same GPIOs enabled */
501250003Sadrian#ifdef AH_ASSERT
502250003Sadrian            field_val = (reg_val >> shifts[i]) & gpio_mask;
503250003Sadrian            HALASSERT(i == 0 || old_field_val == field_val);
504250003Sadrian            old_field_val = field_val;
505250003Sadrian#endif
506250003Sadrian        }
507250003Sadrian    }
508250003Sadrian}
509250003Sadrian
510250003Sadrianu_int32_t
511250003Sadrianar9300_gpio_get_polarity(struct ath_hal *ah)
512250003Sadrian{
513250003Sadrian    return OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_INTR_POL));
514250003Sadrian
515250003Sadrian}
516250003Sadrian
517250003Sadrianvoid
518250003Sadrianar9300_gpio_set_polarity(struct ath_hal *ah, u_int32_t pol_map,
519250003Sadrian                         u_int32_t changed_mask)
520250003Sadrian{
521250003Sadrian    u_int32_t gpio_mask;
522250003Sadrian
523250008Sadrian    gpio_mask = (1 << AH_PRIVATE(ah)->ah_caps.halNumGpioPins) - 1;
524250003Sadrian    OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_GPIO_INTR_POL), gpio_mask & pol_map);
525250003Sadrian
526250003Sadrian#ifndef ATH_GPIO_USE_ASYNC_CAUSE
527250003Sadrian    /*
528250003Sadrian     * For SYNC_CAUSE type interrupts, we need to clear the cause register
529250003Sadrian     * explicitly. Otherwise an interrupt with the original polarity setting
530250003Sadrian     * will come up immediately (if there is already an interrupt source),
531250003Sadrian     * which is not what we want usually.
532250003Sadrian     */
533250003Sadrian    OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_CAUSE_CLR),
534250003Sadrian                 changed_mask << AR_INTR_SYNC_ENABLE_GPIO_S);
535250003Sadrian    OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_CAUSE_CLR));
536250003Sadrian#endif
537250003Sadrian}
538250003Sadrian
539250003Sadrian/*
540250003Sadrian * get the GPIO input pin mask
541250003Sadrian * gpio0 - gpio13
542250003Sadrian * gpio8, gpio11, regard as reserved by the chip ar9382
543250003Sadrian */
544250003Sadrian
545250003Sadrianu_int32_t
546250003Sadrianar9300_gpio_get_mask(struct ath_hal *ah)
547250003Sadrian{
548250003Sadrian    u_int32_t mask = (1 << (AR9382_MAX_GPIO_INPUT_PIN_NUM + 1) ) - 1;
549250003Sadrian
550250003Sadrian    if (AH_PRIVATE(ah)->ah_devid == AR9300_DEVID_AR9380_PCIE) {
551250003Sadrian        mask = (1 << AR9382_MAX_GPIO_PIN_NUM) - 1;
552250003Sadrian        mask &= ~(1 << AR9382_GPIO_PIN_8_RESERVED |
553250003Sadrian                  1 << AR9382_GPIO_PIN_11_RESERVED);
554250003Sadrian    }
555250003Sadrian    return mask;
556250003Sadrian}
557250003Sadrian
558250003Sadrianint
559250003Sadrianar9300_gpio_set_mask(struct ath_hal *ah, u_int32_t mask, u_int32_t pol_map)
560250003Sadrian{
561250003Sadrian    u_int32_t invalid = ~((1 << (AR9382_MAX_GPIO_INPUT_PIN_NUM + 1)) - 1);
562250003Sadrian
563250003Sadrian    if (AH_PRIVATE(ah)->ah_devid == AR9300_DEVID_AR9380_PCIE) {
564250003Sadrian        invalid = ~((1 << AR9382_MAX_GPIO_PIN_NUM) - 1);
565250003Sadrian        invalid |= 1 << AR9382_GPIO_PIN_8_RESERVED |
566250003Sadrian                   1 << AR9382_GPIO_PIN_11_RESERVED;
567250003Sadrian    }
568250003Sadrian    if (mask & invalid) {
569250003Sadrian        ath_hal_printf(ah, "%s: invalid GPIO mask 0x%x\n", __func__, mask);
570250003Sadrian        return -1;
571250003Sadrian    }
572250003Sadrian    AH9300(ah)->ah_gpio_mask = mask;
573250003Sadrian    OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_GPIO_INTR_POL), mask & pol_map);
574250003Sadrian
575250003Sadrian    return 0;
576250003Sadrian}
577250003Sadrian
578250003Sadrian#ifdef AH_DEBUG
579250003Sadrianvoid ar9300_gpio_show(struct ath_hal *ah);
580250003Sadrianvoid ar9300_gpio_show(struct ath_hal *ah)
581250003Sadrian{
582250003Sadrian    ath_hal_printf(ah, "--- 9382 GPIOs ---(ah=%p)\n", ah );
583250003Sadrian    ath_hal_printf(ah,
584250003Sadrian        "AH9300(_ah)->ah_hostifregs:%p\r\n", &(AH9300(ah)->ah_hostifregs));
585250003Sadrian    ath_hal_printf(ah,
586250003Sadrian        "GPIO_OUT:         0x%08X\n",
587250003Sadrian        OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_OUT)));
588250003Sadrian    ath_hal_printf(ah,
589250003Sadrian        "GPIO_IN:          0x%08X\n",
590250003Sadrian         OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_IN)));
591250003Sadrian    ath_hal_printf(ah,
592250003Sadrian        "GPIO_OE:          0x%08X\n",
593250003Sadrian         OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_OE_OUT)));
594250003Sadrian    ath_hal_printf(ah,
595250003Sadrian        "GPIO_OE1_OUT:     0x%08X\n",
596250003Sadrian         OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_OE1_OUT)));
597250003Sadrian    ath_hal_printf(ah,
598250003Sadrian        "GPIO_INTR_POLAR:  0x%08X\n",
599250003Sadrian         OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_INTR_POL)));
600250003Sadrian    ath_hal_printf(ah,
601250003Sadrian        "GPIO_INPUT_VALUE: 0x%08X\n",
602250003Sadrian         OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_INPUT_EN_VAL)));
603250003Sadrian    ath_hal_printf(ah,
604250003Sadrian        "GPIO_INPUT_MUX1:  0x%08X\n",
605250003Sadrian         OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_INPUT_MUX1)));
606250003Sadrian    ath_hal_printf(ah,
607250003Sadrian        "GPIO_INPUT_MUX2:  0x%08X\n",
608250003Sadrian         OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_INPUT_MUX2)));
609250003Sadrian    ath_hal_printf(ah,
610250003Sadrian        "GPIO_OUTPUT_MUX1: 0x%08X\n",
611250003Sadrian         OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_OUTPUT_MUX1)));
612250003Sadrian    ath_hal_printf(ah,
613250003Sadrian        "GPIO_OUTPUT_MUX2: 0x%08X\n",
614250003Sadrian         OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_OUTPUT_MUX2)));
615250003Sadrian    ath_hal_printf(ah,
616250003Sadrian        "GPIO_OUTPUT_MUX3: 0x%08X\n",
617250003Sadrian         OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_OUTPUT_MUX3)));
618250003Sadrian    ath_hal_printf(ah,
619250003Sadrian        "GPIO_INPUT_STATE: 0x%08X\n",
620250003Sadrian         OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INPUT_STATE)));
621250003Sadrian    ath_hal_printf(ah,
622250003Sadrian        "GPIO_PDPU:        0x%08X\n",
623250003Sadrian         OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_PDPU)));
624250003Sadrian    ath_hal_printf(ah,
625250003Sadrian        "GPIO_DS:          0x%08X\n",
626250003Sadrian         OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_DS)));
627250003Sadrian    ath_hal_printf(ah,
628250003Sadrian        "AR_INTR_ASYNC_ENABLE: 0x%08X\n",
629250003Sadrian         OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_ASYNC_ENABLE)));
630250003Sadrian    ath_hal_printf(ah,
631250003Sadrian        "AR_INTR_ASYNC_MASK:   0x%08X\n",
632250003Sadrian         OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_ASYNC_MASK)));
633250003Sadrian    ath_hal_printf(ah,
634250003Sadrian        "AR_INTR_SYNC_ENABLE:  0x%08X\n",
635250003Sadrian         OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_ENABLE)));
636250003Sadrian    ath_hal_printf(ah,
637250003Sadrian        "AR_INTR_SYNC_MASK:    0x%08X\n",
638250003Sadrian         OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_MASK)));
639250003Sadrian    ath_hal_printf(ah,
640250003Sadrian        "AR_INTR_ASYNC_CAUSE:  0x%08X\n",
641250003Sadrian         OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_ASYNC_CAUSE)));
642250003Sadrian    ath_hal_printf(ah,
643250003Sadrian        "AR_INTR_SYNC_CAUSE:   0x%08X\n",
644250003Sadrian         OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_CAUSE)));
645250003Sadrian
646250003Sadrian}
647250003Sadrian#endif /*AH_DEBUG*/
648