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