ar9300_gpio.c revision 278759
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_9_INPUT_ONLY)) 166250003Sadrian { 167250003Sadrian return AH_FALSE; 168250003Sadrian } 169250003Sadrian 170250003Sadrian /* Convert HAL signal type definitions to hardware-specific values. */ 171250008Sadrian if ((int) hal_signal_type < ARRAY_LENGTH(mux_signal_conversion_table)) 172250003Sadrian { 173250003Sadrian ah_signal_type = mux_signal_conversion_table[hal_signal_type]; 174250003Sadrian } else { 175250003Sadrian return AH_FALSE; 176250003Sadrian } 177250003Sadrian 178250003Sadrian if (gpio <= AR9382_MAX_JTAG_GPIO_PIN_NUM) { 179250003Sadrian OS_REG_SET_BIT(ah, 180250003Sadrian AR_HOSTIF_REG(ah, AR_GPIO_INPUT_EN_VAL), AR_GPIO_JTAG_DISABLE); 181250003Sadrian } 182250003Sadrian 183250003Sadrian#if UMAC_SUPPORT_SMARTANTENNA 184250003Sadrian /* Get the pin and func values for smart antenna */ 185250003Sadrian switch (ah_signal_type) 186250003Sadrian { 187250003Sadrian case AR_GPIO_OUTPUT_MUX_AS_SMARTANT_CTRL0: 188250003Sadrian gpio = ATH_GPIOPIN_ANTCHAIN0; 189250003Sadrian ah_signal_type = ATH_GPIOFUNC_ANTCHAIN0; 190250003Sadrian smart_ant = 1; 191250003Sadrian break; 192250003Sadrian case AR_GPIO_OUTPUT_MUX_AS_SMARTANT_CTRL1: 193250003Sadrian gpio = ATH_GPIOPIN_ANTCHAIN1; 194250003Sadrian ah_signal_type = ATH_GPIOFUNC_ANTCHAIN1; 195250003Sadrian smart_ant = 1; 196250003Sadrian break; 197250003Sadrian case AR_GPIO_OUTPUT_MUX_AS_SMARTANT_CTRL2: 198250003Sadrian gpio = ATH_GPIOPIN_ANTCHAIN2; 199250003Sadrian ah_signal_type = ATH_GPIOFUNC_ANTCHAIN2; 200250003Sadrian smart_ant = 1; 201250003Sadrian break; 202250003Sadrian#if ATH_SMARTANTENNA_ROUTE_SWCOM_TO_GPIO 203250003Sadrian case AR_GPIO_OUTPUT_MUX_AS_SWCOM3: 204250003Sadrian gpio = ATH_GPIOPIN_ROUTE_SWCOM3; 205250003Sadrian ah_signal_type = ATH_GPIOFUNC_ROUTE_SWCOM3; 206250003Sadrian smart_ant = 1; 207250003Sadrian break; 208250003Sadrian#endif 209250003Sadrian default: 210250003Sadrian break; 211250003Sadrian } 212250003Sadrian#endif 213250003Sadrian 214250003Sadrian if (smart_ant && (AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah))) 215250003Sadrian { 216250008Sadrian#if UMAC_SUPPORT_SMARTANTENNA 217250003Sadrian ar9340_soc_gpio_cfg_output_mux(ah, gpio, ah_signal_type); 218250003Sadrian#endif 219250003Sadrian return AH_TRUE; 220250003Sadrian } else 221250003Sadrian { 222250003Sadrian /* Configure the MUX */ 223250003Sadrian ar9300_gpio_cfg_output_mux(ah, gpio, ah_signal_type); 224250003Sadrian } 225250003Sadrian 226250003Sadrian /* 2 bits per output mode */ 227250003Sadrian gpio_shift = 2 * gpio; 228250003Sadrian 229250003Sadrian OS_REG_RMW(ah, 230250003Sadrian AR_HOSTIF_REG(ah, AR_GPIO_OE_OUT), 231250003Sadrian (AR_GPIO_OE_OUT_DRV_ALL << gpio_shift), 232250003Sadrian (AR_GPIO_OE_OUT_DRV << gpio_shift)); 233250003Sadrian return AH_TRUE; 234250003Sadrian} 235250003Sadrian 236250003Sadrian/* 237250003Sadrian * Configure GPIO Output lines -LED off 238250003Sadrian */ 239250003SadrianHAL_BOOL 240250003Sadrianar9300_gpio_cfg_output_led_off( 241250003Sadrian struct ath_hal *ah, 242250003Sadrian u_int32_t gpio, 243250008Sadrian HAL_GPIO_MUX_TYPE halSignalType) 244250003Sadrian{ 245250003Sadrian#define N(a) (sizeof(a) / sizeof(a[0])) 246250003Sadrian u_int32_t ah_signal_type; 247250003Sadrian u_int32_t gpio_shift; 248250003Sadrian u_int8_t smart_ant = 0; 249250003Sadrian 250250003Sadrian static const u_int32_t mux_signal_conversion_table[] = { 251250003Sadrian /* HAL_GPIO_OUTPUT_MUX_AS_OUTPUT */ 252250003Sadrian AR_GPIO_OUTPUT_MUX_AS_OUTPUT, 253250003Sadrian /* HAL_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED */ 254250003Sadrian AR_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED, 255250003Sadrian /* HAL_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED */ 256250003Sadrian AR_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED, 257250003Sadrian /* HAL_GPIO_OUTPUT_MUX_AS_MAC_NETWORK_LED */ 258250003Sadrian AR_GPIO_OUTPUT_MUX_AS_MAC_NETWORK_LED, 259250003Sadrian /* HAL_GPIO_OUTPUT_MUX_AS_MAC_POWER_LED */ 260250003Sadrian AR_GPIO_OUTPUT_MUX_AS_MAC_POWER_LED, 261250003Sadrian /* HAL_GPIO_OUTPUT_MUX_AS_WLAN_ACTIVE */ 262250003Sadrian AR_GPIO_OUTPUT_MUX_AS_RX_CLEAR_EXTERNAL, 263250003Sadrian /* HAL_GPIO_OUTPUT_MUX_AS_TX_FRAME */ 264250003Sadrian AR_GPIO_OUTPUT_MUX_AS_TX_FRAME, 265250003Sadrian /* HAL_GPIO_OUTPUT_MUX_AS_MCI_WLAN_DATA */ 266250003Sadrian AR_GPIO_OUTPUT_MUX_AS_MCI_WLAN_DATA, 267250003Sadrian /* HAL_GPIO_OUTPUT_MUX_AS_MCI_WLAN_CLK */ 268250003Sadrian AR_GPIO_OUTPUT_MUX_AS_MCI_WLAN_CLK, 269250003Sadrian /* HAL_GPIO_OUTPUT_MUX_AS_MCI_BT_DATA */ 270250003Sadrian AR_GPIO_OUTPUT_MUX_AS_MCI_BT_DATA, 271250003Sadrian /* HAL_GPIO_OUTPUT_MUX_AS_MCI_BT_CLK */ 272250003Sadrian AR_GPIO_OUTPUT_MUX_AS_MCI_BT_CLK, 273250003Sadrian /* HAL_GPIO_OUTPUT_MUX_AS_WL_IN_TX */ 274250003Sadrian AR_GPIO_OUTPUT_MUX_AS_WL_IN_TX, 275250003Sadrian /* HAL_GPIO_OUTPUT_MUX_AS_WL_IN_RX */ 276250003Sadrian AR_GPIO_OUTPUT_MUX_AS_WL_IN_RX, 277250003Sadrian /* HAL_GPIO_OUTPUT_MUX_AS_BT_IN_TX */ 278250003Sadrian AR_GPIO_OUTPUT_MUX_AS_BT_IN_TX, 279250003Sadrian /* HAL_GPIO_OUTPUT_MUX_AS_BT_IN_RX */ 280250003Sadrian AR_GPIO_OUTPUT_MUX_AS_BT_IN_RX, 281250003Sadrian AR_GPIO_OUTPUT_MUX_AS_RUCKUS_STROBE, 282250003Sadrian AR_GPIO_OUTPUT_MUX_AS_RUCKUS_DATA, 283250003Sadrian AR_GPIO_OUTPUT_MUX_AS_SMARTANT_CTRL0, 284250003Sadrian AR_GPIO_OUTPUT_MUX_AS_SMARTANT_CTRL1, 285250003Sadrian AR_GPIO_OUTPUT_MUX_AS_SMARTANT_CTRL2 286250003Sadrian }; 287250003Sadrian HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.hal_num_gpio_pins); 288250003Sadrian 289250003Sadrian /* Convert HAL signal type definitions to hardware-specific values. */ 290250008Sadrian if ((int) halSignalType < ARRAY_LENGTH(mux_signal_conversion_table)) 291250003Sadrian { 292250003Sadrian ah_signal_type = mux_signal_conversion_table[halSignalType]; 293250003Sadrian } else { 294250003Sadrian return AH_FALSE; 295250003Sadrian } 296250003Sadrian#if UMAC_SUPPORT_SMARTANTENNA 297250003Sadrian /* Get the pin and func values for smart antenna */ 298250003Sadrian switch (halSignalType) 299250003Sadrian { 300250003Sadrian case AR_GPIO_OUTPUT_MUX_AS_SMARTANT_CTRL0: 301250003Sadrian gpio = ATH_GPIOPIN_ANTCHAIN0; 302250003Sadrian ah_signal_type = ATH_GPIOFUNC_ANTCHAIN0; 303250003Sadrian smart_ant = 1; 304250003Sadrian break; 305250003Sadrian case AR_GPIO_OUTPUT_MUX_AS_SMARTANT_CTRL1: 306250003Sadrian gpio = ATH_GPIOPIN_ANTCHAIN1; 307250003Sadrian ah_signal_type = ATH_GPIOFUNC_ANTCHAIN1; 308250003Sadrian smart_ant = 1; 309250003Sadrian break; 310250003Sadrian case AR_GPIO_OUTPUT_MUX_AS_SMARTANT_CTRL2: 311250003Sadrian gpio = ATH_GPIOPIN_ANTCHAIN2; 312250003Sadrian ah_signal_type = ATH_GPIOFUNC_ANTCHAIN2; 313250003Sadrian smart_ant = 1; 314250003Sadrian break; 315250003Sadrian default: 316250003Sadrian break; 317250003Sadrian } 318250003Sadrian#endif 319250003Sadrian 320250003Sadrian if (smart_ant && AR_SREV_WASP(ah)) 321250003Sadrian { 322250003Sadrian return AH_FALSE; 323250003Sadrian } 324250003Sadrian 325250003Sadrian // Configure the MUX 326250003Sadrian ar9300_gpio_cfg_output_mux(ah, gpio, ah_signal_type); 327250003Sadrian 328250003Sadrian // 2 bits per output mode 329250003Sadrian gpio_shift = 2*gpio; 330250003Sadrian 331250003Sadrian OS_REG_RMW(ah, 332250003Sadrian AR_HOSTIF_REG(ah, AR_GPIO_OE_OUT), 333250003Sadrian (AR_GPIO_OE_OUT_DRV_NO << gpio_shift), 334250003Sadrian (AR_GPIO_OE_OUT_DRV << gpio_shift)); 335250003Sadrian 336250003Sadrian return AH_TRUE; 337250003Sadrian#undef N 338250003Sadrian} 339250003Sadrian 340250003Sadrian/* 341250003Sadrian * Configure GPIO Input lines 342250003Sadrian */ 343250003SadrianHAL_BOOL 344250003Sadrianar9300_gpio_cfg_input(struct ath_hal *ah, u_int32_t gpio) 345250003Sadrian{ 346250003Sadrian u_int32_t gpio_shift; 347250003Sadrian 348250008Sadrian HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.halNumGpioPins); 349250003Sadrian if ((gpio == AR9382_GPIO_PIN_8_RESERVED) || 350250003Sadrian (gpio > AR9382_MAX_GPIO_INPUT_PIN_NUM)) 351250003Sadrian { 352250003Sadrian return AH_FALSE; 353250003Sadrian } 354250003Sadrian 355250003Sadrian if (gpio <= AR9382_MAX_JTAG_GPIO_PIN_NUM) { 356250003Sadrian OS_REG_SET_BIT(ah, 357250003Sadrian AR_HOSTIF_REG(ah, AR_GPIO_INPUT_EN_VAL), AR_GPIO_JTAG_DISABLE); 358250003Sadrian } 359250003Sadrian /* TODO: configure input mux for AR9300 */ 360250003Sadrian /* If configured as input, set output to tristate */ 361250003Sadrian gpio_shift = 2 * gpio; 362250003Sadrian 363250003Sadrian OS_REG_RMW(ah, 364250003Sadrian AR_HOSTIF_REG(ah, AR_GPIO_OE_OUT), 365250003Sadrian (AR_GPIO_OE_OUT_DRV_NO << gpio_shift), 366250003Sadrian (AR_GPIO_OE_OUT_DRV << gpio_shift)); 367250003Sadrian return AH_TRUE; 368250003Sadrian} 369250003Sadrian 370250003Sadrian/* 371250003Sadrian * Once configured for I/O - set output lines 372250003Sadrian * output the level of GPio PIN without care work mode 373250003Sadrian */ 374250003SadrianHAL_BOOL 375250003Sadrianar9300_gpio_set(struct ath_hal *ah, u_int32_t gpio, u_int32_t val) 376250003Sadrian{ 377250008Sadrian HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.halNumGpioPins); 378250003Sadrian if ((gpio == AR9382_GPIO_PIN_8_RESERVED) || 379250003Sadrian (gpio == AR9382_GPIO_9_INPUT_ONLY)) 380250003Sadrian { 381250003Sadrian return AH_FALSE; 382250003Sadrian } 383250003Sadrian OS_REG_RMW(ah, AR_HOSTIF_REG(ah, AR_GPIO_OUT), 384250003Sadrian ((val & 1) << gpio), AR_GPIO_BIT(gpio)); 385250003Sadrian 386250003Sadrian return AH_TRUE; 387250003Sadrian} 388250003Sadrian 389250003Sadrian/* 390250003Sadrian * Once configured for I/O - get input lines 391250003Sadrian */ 392250003Sadrianu_int32_t 393250003Sadrianar9300_gpio_get(struct ath_hal *ah, u_int32_t gpio) 394250003Sadrian{ 395250003Sadrian u_int32_t gpio_in; 396250008Sadrian HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.halNumGpioPins); 397278759Sadrian if ((gpio == AR9382_GPIO_PIN_8_RESERVED)) 398250003Sadrian { 399250003Sadrian return 0xffffffff; 400250003Sadrian } 401250003Sadrian 402250003Sadrian gpio_in = OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_IN)); 403250003Sadrian OS_REG_RMW(ah, AR_HOSTIF_REG(ah, AR_GPIO_IN), 404250003Sadrian (1 << gpio), AR_GPIO_BIT(gpio)); 405250003Sadrian return (MS(gpio_in, AR_GPIO_IN_VAL) & AR_GPIO_BIT(gpio)) != 0; 406250003Sadrian} 407250003Sadrian 408250003Sadrianu_int32_t 409250003Sadrianar9300_gpio_get_intr(struct ath_hal *ah) 410250003Sadrian{ 411250003Sadrian unsigned int mask = 0; 412250003Sadrian struct ath_hal_9300 *ahp = AH9300(ah); 413250003Sadrian 414250003Sadrian mask = ahp->ah_gpio_cause; 415250003Sadrian return mask; 416250003Sadrian} 417250003Sadrian 418250003Sadrian/* 419250003Sadrian * Set the GPIO Interrupt 420250003Sadrian * Sync and Async interrupts are both set/cleared. 421250003Sadrian * Async GPIO interrupts may not be raised when the chip is put to sleep. 422250003Sadrian */ 423250003Sadrianvoid 424250003Sadrianar9300_gpio_set_intr(struct ath_hal *ah, u_int gpio, u_int32_t ilevel) 425250003Sadrian{ 426250003Sadrian 427250003Sadrian 428250003Sadrian int i, reg_bit; 429250003Sadrian u_int32_t reg_val; 430250003Sadrian u_int32_t regs[2], shifts[2]; 431250003Sadrian 432250003Sadrian#ifdef AH_ASSERT 433250003Sadrian u_int32_t gpio_mask; 434250003Sadrian u_int32_t old_field_val = 0, field_val = 0; 435250003Sadrian#endif 436250003Sadrian 437250003Sadrian#ifdef ATH_GPIO_USE_ASYNC_CAUSE 438250003Sadrian regs[0] = AR_HOSTIF_REG(ah, AR_INTR_ASYNC_ENABLE); 439250003Sadrian regs[1] = AR_HOSTIF_REG(ah, AR_INTR_ASYNC_MASK); 440250003Sadrian shifts[0] = AR_INTR_ASYNC_ENABLE_GPIO_S; 441250003Sadrian shifts[1] = AR_INTR_ASYNC_MASK_GPIO_S; 442250003Sadrian#else 443250003Sadrian regs[0] = AR_HOSTIF_REG(ah, AR_INTR_SYNC_ENABLE); 444250003Sadrian regs[1] = AR_HOSTIF_REG(ah, AR_INTR_SYNC_MASK); 445250003Sadrian shifts[0] = AR_INTR_SYNC_ENABLE_GPIO_S; 446250003Sadrian shifts[1] = AR_INTR_SYNC_MASK_GPIO_S; 447250003Sadrian#endif 448250003Sadrian 449250008Sadrian HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.halNumGpioPins); 450250003Sadrian 451250003Sadrian if ((gpio == AR9382_GPIO_PIN_8_RESERVED) || 452250003Sadrian (gpio > AR9382_MAX_GPIO_INPUT_PIN_NUM)) 453250003Sadrian { 454250003Sadrian return; 455250003Sadrian } 456250003Sadrian 457250003Sadrian#ifdef AH_ASSERT 458250008Sadrian gpio_mask = (1 << AH_PRIVATE(ah)->ah_caps.halNumGpioPins) - 1; 459250003Sadrian#endif 460250003Sadrian if (ilevel == HAL_GPIO_INTR_DISABLE) { 461250003Sadrian /* clear this GPIO's bit in the interrupt registers */ 462250003Sadrian for (i = 0; i < ARRAY_LENGTH(regs); i++) { 463250003Sadrian reg_val = OS_REG_READ(ah, regs[i]); 464250003Sadrian reg_bit = shifts[i] + gpio; 465250003Sadrian reg_val &= ~(1 << reg_bit); 466250003Sadrian OS_REG_WRITE(ah, regs[i], reg_val); 467250003Sadrian 468250003Sadrian /* check that each register has same GPIOs enabled */ 469250003Sadrian#ifdef AH_ASSERT 470250003Sadrian field_val = (reg_val >> shifts[i]) & gpio_mask; 471250003Sadrian HALASSERT(i == 0 || old_field_val == field_val); 472250003Sadrian old_field_val = field_val; 473250003Sadrian#endif 474250003Sadrian } 475250003Sadrian 476250003Sadrian } else { 477250003Sadrian reg_val = OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_INTR_POL)); 478250003Sadrian reg_bit = gpio; 479250003Sadrian if (ilevel == HAL_GPIO_INTR_HIGH) { 480250003Sadrian /* 0 == interrupt on pin high */ 481250003Sadrian reg_val &= ~(1 << reg_bit); 482250003Sadrian } else if (ilevel == HAL_GPIO_INTR_LOW) { 483250003Sadrian /* 1 == interrupt on pin low */ 484250003Sadrian reg_val |= (1 << reg_bit); 485250003Sadrian } 486250003Sadrian OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_GPIO_INTR_POL), reg_val); 487250003Sadrian 488250003Sadrian /* set this GPIO's bit in the interrupt registers */ 489250003Sadrian for (i = 0; i < ARRAY_LENGTH(regs); i++) { 490250003Sadrian reg_val = OS_REG_READ(ah, regs[i]); 491250003Sadrian reg_bit = shifts[i] + gpio; 492250003Sadrian reg_val |= (1 << reg_bit); 493250003Sadrian OS_REG_WRITE(ah, regs[i], reg_val); 494250003Sadrian 495250003Sadrian /* check that each register has same GPIOs enabled */ 496250003Sadrian#ifdef AH_ASSERT 497250003Sadrian field_val = (reg_val >> shifts[i]) & gpio_mask; 498250003Sadrian HALASSERT(i == 0 || old_field_val == field_val); 499250003Sadrian old_field_val = field_val; 500250003Sadrian#endif 501250003Sadrian } 502250003Sadrian } 503250003Sadrian} 504250003Sadrian 505250003Sadrianu_int32_t 506250003Sadrianar9300_gpio_get_polarity(struct ath_hal *ah) 507250003Sadrian{ 508250003Sadrian return OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_INTR_POL)); 509250003Sadrian 510250003Sadrian} 511250003Sadrian 512250003Sadrianvoid 513250003Sadrianar9300_gpio_set_polarity(struct ath_hal *ah, u_int32_t pol_map, 514250003Sadrian u_int32_t changed_mask) 515250003Sadrian{ 516250003Sadrian u_int32_t gpio_mask; 517250003Sadrian 518250008Sadrian gpio_mask = (1 << AH_PRIVATE(ah)->ah_caps.halNumGpioPins) - 1; 519250003Sadrian OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_GPIO_INTR_POL), gpio_mask & pol_map); 520250003Sadrian 521250003Sadrian#ifndef ATH_GPIO_USE_ASYNC_CAUSE 522250003Sadrian /* 523250003Sadrian * For SYNC_CAUSE type interrupts, we need to clear the cause register 524250003Sadrian * explicitly. Otherwise an interrupt with the original polarity setting 525250003Sadrian * will come up immediately (if there is already an interrupt source), 526250003Sadrian * which is not what we want usually. 527250003Sadrian */ 528250003Sadrian OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_CAUSE_CLR), 529250003Sadrian changed_mask << AR_INTR_SYNC_ENABLE_GPIO_S); 530250003Sadrian OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_CAUSE_CLR)); 531250003Sadrian#endif 532250003Sadrian} 533250003Sadrian 534250003Sadrian/* 535250003Sadrian * get the GPIO input pin mask 536250003Sadrian * gpio0 - gpio13 537250003Sadrian * gpio8, gpio11, regard as reserved by the chip ar9382 538250003Sadrian */ 539250003Sadrian 540250003Sadrianu_int32_t 541250003Sadrianar9300_gpio_get_mask(struct ath_hal *ah) 542250003Sadrian{ 543250003Sadrian u_int32_t mask = (1 << (AR9382_MAX_GPIO_INPUT_PIN_NUM + 1) ) - 1; 544250003Sadrian 545250003Sadrian if (AH_PRIVATE(ah)->ah_devid == AR9300_DEVID_AR9380_PCIE) { 546250003Sadrian mask = (1 << AR9382_MAX_GPIO_PIN_NUM) - 1; 547278759Sadrian mask &= ~(1 << AR9382_GPIO_PIN_8_RESERVED); 548250003Sadrian } 549250003Sadrian return mask; 550250003Sadrian} 551250003Sadrian 552250003Sadrianint 553250003Sadrianar9300_gpio_set_mask(struct ath_hal *ah, u_int32_t mask, u_int32_t pol_map) 554250003Sadrian{ 555250003Sadrian u_int32_t invalid = ~((1 << (AR9382_MAX_GPIO_INPUT_PIN_NUM + 1)) - 1); 556250003Sadrian 557250003Sadrian if (AH_PRIVATE(ah)->ah_devid == AR9300_DEVID_AR9380_PCIE) { 558250003Sadrian invalid = ~((1 << AR9382_MAX_GPIO_PIN_NUM) - 1); 559278759Sadrian invalid |= 1 << AR9382_GPIO_PIN_8_RESERVED; 560250003Sadrian } 561250003Sadrian if (mask & invalid) { 562250003Sadrian ath_hal_printf(ah, "%s: invalid GPIO mask 0x%x\n", __func__, mask); 563250003Sadrian return -1; 564250003Sadrian } 565250003Sadrian AH9300(ah)->ah_gpio_mask = mask; 566250003Sadrian OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_GPIO_INTR_POL), mask & pol_map); 567250003Sadrian 568250003Sadrian return 0; 569250003Sadrian} 570250003Sadrian 571250003Sadrian#ifdef AH_DEBUG 572250003Sadrianvoid ar9300_gpio_show(struct ath_hal *ah); 573250003Sadrianvoid ar9300_gpio_show(struct ath_hal *ah) 574250003Sadrian{ 575250003Sadrian ath_hal_printf(ah, "--- 9382 GPIOs ---(ah=%p)\n", ah ); 576250003Sadrian ath_hal_printf(ah, 577250003Sadrian "AH9300(_ah)->ah_hostifregs:%p\r\n", &(AH9300(ah)->ah_hostifregs)); 578250003Sadrian ath_hal_printf(ah, 579250003Sadrian "GPIO_OUT: 0x%08X\n", 580250003Sadrian OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_OUT))); 581250003Sadrian ath_hal_printf(ah, 582250003Sadrian "GPIO_IN: 0x%08X\n", 583250003Sadrian OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_IN))); 584250003Sadrian ath_hal_printf(ah, 585250003Sadrian "GPIO_OE: 0x%08X\n", 586250003Sadrian OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_OE_OUT))); 587250003Sadrian ath_hal_printf(ah, 588250003Sadrian "GPIO_OE1_OUT: 0x%08X\n", 589250003Sadrian OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_OE1_OUT))); 590250003Sadrian ath_hal_printf(ah, 591250003Sadrian "GPIO_INTR_POLAR: 0x%08X\n", 592250003Sadrian OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_INTR_POL))); 593250003Sadrian ath_hal_printf(ah, 594250003Sadrian "GPIO_INPUT_VALUE: 0x%08X\n", 595250003Sadrian OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_INPUT_EN_VAL))); 596250003Sadrian ath_hal_printf(ah, 597250003Sadrian "GPIO_INPUT_MUX1: 0x%08X\n", 598250003Sadrian OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_INPUT_MUX1))); 599250003Sadrian ath_hal_printf(ah, 600250003Sadrian "GPIO_INPUT_MUX2: 0x%08X\n", 601250003Sadrian OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_INPUT_MUX2))); 602250003Sadrian ath_hal_printf(ah, 603250003Sadrian "GPIO_OUTPUT_MUX1: 0x%08X\n", 604250003Sadrian OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_OUTPUT_MUX1))); 605250003Sadrian ath_hal_printf(ah, 606250003Sadrian "GPIO_OUTPUT_MUX2: 0x%08X\n", 607250003Sadrian OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_OUTPUT_MUX2))); 608250003Sadrian ath_hal_printf(ah, 609250003Sadrian "GPIO_OUTPUT_MUX3: 0x%08X\n", 610250003Sadrian OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_OUTPUT_MUX3))); 611250003Sadrian ath_hal_printf(ah, 612250003Sadrian "GPIO_INPUT_STATE: 0x%08X\n", 613250003Sadrian OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INPUT_STATE))); 614250003Sadrian ath_hal_printf(ah, 615250003Sadrian "GPIO_PDPU: 0x%08X\n", 616250003Sadrian OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_PDPU))); 617250003Sadrian ath_hal_printf(ah, 618250003Sadrian "GPIO_DS: 0x%08X\n", 619250003Sadrian OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_GPIO_DS))); 620250003Sadrian ath_hal_printf(ah, 621250003Sadrian "AR_INTR_ASYNC_ENABLE: 0x%08X\n", 622250003Sadrian OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_ASYNC_ENABLE))); 623250003Sadrian ath_hal_printf(ah, 624250003Sadrian "AR_INTR_ASYNC_MASK: 0x%08X\n", 625250003Sadrian OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_ASYNC_MASK))); 626250003Sadrian ath_hal_printf(ah, 627250003Sadrian "AR_INTR_SYNC_ENABLE: 0x%08X\n", 628250003Sadrian OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_ENABLE))); 629250003Sadrian ath_hal_printf(ah, 630250003Sadrian "AR_INTR_SYNC_MASK: 0x%08X\n", 631250003Sadrian OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_MASK))); 632250003Sadrian ath_hal_printf(ah, 633250003Sadrian "AR_INTR_ASYNC_CAUSE: 0x%08X\n", 634250003Sadrian OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_ASYNC_CAUSE))); 635250003Sadrian ath_hal_printf(ah, 636250003Sadrian "AR_INTR_SYNC_CAUSE: 0x%08X\n", 637250003Sadrian OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_CAUSE))); 638250003Sadrian 639250003Sadrian} 640250003Sadrian#endif /*AH_DEBUG*/ 641