1 /* 2 * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting 3 * Copyright (c) 2002-2008 Atheros Communications, Inc. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 * 17 * $FreeBSD$ 18 */ 19 #include "opt_ah.h" 20 21 #include "ah.h" 22 #include "ah_internal.h" 23 #include "ah_devid.h" 24 25 #include "ar5416/ar5416.h" 26 #include "ar5416/ar5416reg.h" 27 #include "ar5416/ar5416phy.h" 28 29 #define AR_GPIO_BIT(_gpio) (1 << _gpio) 30 31 /* 32 * Configure GPIO Output Mux control 33 */ 34 static void 35 cfgOutputMux(struct ath_hal *ah, uint32_t gpio, uint32_t type) 36 { 37 int addr; 38 uint32_t gpio_shift, tmp; 39 40 HALDEBUG(ah, HAL_DEBUG_GPIO, "%s: gpio=%d, type=%d\n", 41 __func__, gpio, type); 42 43 /* each MUX controls 6 GPIO pins */ 44 if (gpio > 11) 45 addr = AR_GPIO_OUTPUT_MUX3; 46 else if (gpio > 5) 47 addr = AR_GPIO_OUTPUT_MUX2; 48 else 49 addr = AR_GPIO_OUTPUT_MUX1; 50 51 /* 52 * 5 bits per GPIO pin. Bits 0..4 for 1st pin in that mux, 53 * bits 5..9 for 2nd pin, etc. 54 */ 55 gpio_shift = (gpio % 6) * 5; 56 57 /* 58 * From Owl to Merlin 1.0, the value read from MUX1 bit 4 to bit 59 * 9 are wrong. Here is hardware's coding: 60 * PRDATA[4:0] <= gpio_output_mux[0]; 61 * PRDATA[9:4] <= gpio_output_mux[1]; 62 * <==== Bit 4 is used by both gpio_output_mux[0] [1]. 63 * Currently the max value for gpio_output_mux[] is 6. So bit 4 64 * will never be used. So it should be fine that bit 4 won't be 65 * able to recover. 66 */ 67 if (AR_SREV_MERLIN_20_OR_LATER(ah) || 68 (addr != AR_GPIO_OUTPUT_MUX1)) { 69 OS_REG_RMW(ah, addr, (type << gpio_shift), 70 (0x1f << gpio_shift)); 71 } else { 72 tmp = OS_REG_READ(ah, addr); 73 tmp = ((tmp & 0x1F0) << 1) | (tmp & ~0x1F0); 74 tmp &= ~(0x1f << gpio_shift); 75 tmp |= type << gpio_shift; 76 OS_REG_WRITE(ah, addr, tmp); 77 } 78 } 79 80 /* 81 * Configure GPIO Output lines 82 */ 83 HAL_BOOL 84 ar5416GpioCfgOutput(struct ath_hal *ah, uint32_t gpio, HAL_GPIO_MUX_TYPE type) 85 { 86 uint32_t gpio_shift, reg; 87 88 #define N(a) (sizeof(a) / sizeof(a[0])) 89 90 HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.halNumGpioPins); 91 92 /* 93 * This table maps the HAL GPIO pins to the actual hardware 94 * values. 95 */ 96 static const u_int32_t MuxSignalConversionTable[] = { 97 AR_GPIO_OUTPUT_MUX_AS_OUTPUT, 98 AR_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED, 99 AR_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED, 100 AR_GPIO_OUTPUT_MUX_AS_MAC_NETWORK_LED, 101 AR_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED, 102 AR_GPIO_OUTPUT_MUX_AS_RX_CLEAR_EXTERNAL, 103 AR_GPIO_OUTPUT_MUX_AS_TX_FRAME, 104 }; 105 106 HALDEBUG(ah, HAL_DEBUG_GPIO, 107 "%s: gpio=%d, type=%d\n", __func__, gpio, type); 108 109 /* 110 * Convert HAL signal type definitions to hardware-specific values. 111 */ 112 if (type >= N(MuxSignalConversionTable)) { 113 ath_hal_printf(ah, "%s: mux %d is invalid!\n", 114 __func__, 115 type); 116 return AH_FALSE; 117 } 118 cfgOutputMux(ah, gpio, MuxSignalConversionTable[type]); 119 120 /* 2 bits per output mode */ 121 gpio_shift = gpio << 1; 122 123 /* Always drive, rather than tristate/drive low/drive high */ 124 reg = OS_REG_READ(ah, AR_GPIO_OE_OUT); 125 reg &= ~(AR_GPIO_OE_OUT_DRV << gpio_shift); 126 reg |= AR_GPIO_OE_OUT_DRV_ALL << gpio_shift; 127 OS_REG_WRITE(ah, AR_GPIO_OE_OUT, reg); 128 129 return AH_TRUE; 130 #undef N 131 } 132 133 /* 134 * Configure GPIO Input lines 135 */ 136 HAL_BOOL 137 ar5416GpioCfgInput(struct ath_hal *ah, uint32_t gpio) 138 { 139 uint32_t gpio_shift, reg; 140 141 HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.halNumGpioPins); 142 143 HALDEBUG(ah, HAL_DEBUG_GPIO, "%s: gpio=%d\n", __func__, gpio); 144 145 /* TODO: configure input mux for AR5416 */ 146 /* If configured as input, set output to tristate */ 147 gpio_shift = gpio << 1; 148 149 reg = OS_REG_READ(ah, AR_GPIO_OE_OUT); 150 reg &= ~(AR_GPIO_OE_OUT_DRV << gpio_shift); 151 reg |= AR_GPIO_OE_OUT_DRV_ALL << gpio_shift; 152 OS_REG_WRITE(ah, AR_GPIO_OE_OUT, reg); 153 154 return AH_TRUE; 155 } 156 157 /* 158 * Once configured for I/O - set output lines 159 */ 160 HAL_BOOL 161 ar5416GpioSet(struct ath_hal *ah, uint32_t gpio, uint32_t val) 162 { 163 uint32_t reg; 164 165 HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.halNumGpioPins); 166 HALDEBUG(ah, HAL_DEBUG_GPIO, 167 "%s: gpio=%d, val=%d\n", __func__, gpio, val); 168 169 reg = OS_REG_READ(ah, AR_GPIO_IN_OUT); 170 if (val & 1) 171 reg |= AR_GPIO_BIT(gpio); 172 else 173 reg &= ~AR_GPIO_BIT(gpio); 174 OS_REG_WRITE(ah, AR_GPIO_IN_OUT, reg); 175 return AH_TRUE; 176 } 177 178 /* 179 * Once configured for I/O - get input lines 180 */ 181 uint32_t 182 ar5416GpioGet(struct ath_hal *ah, uint32_t gpio) 183 { 184 uint32_t bits; 185 186 if (gpio >= AH_PRIVATE(ah)->ah_caps.halNumGpioPins) 187 return 0xffffffff; 188 /* 189 * Read output value for all gpio's, shift it, 190 * and verify whether the specific bit is set. 191 */ 192 if (AR_SREV_KIWI_10_OR_LATER(ah)) 193 bits = MS(OS_REG_READ(ah, AR_GPIO_IN_OUT), AR9287_GPIO_IN_VAL); 194 if (AR_SREV_KITE_10_OR_LATER(ah)) 195 bits = MS(OS_REG_READ(ah, AR_GPIO_IN_OUT), AR9285_GPIO_IN_VAL); 196 else if (AR_SREV_MERLIN_10_OR_LATER(ah)) 197 bits = MS(OS_REG_READ(ah, AR_GPIO_IN_OUT), AR928X_GPIO_IN_VAL); 198 else 199 bits = MS(OS_REG_READ(ah, AR_GPIO_IN_OUT), AR_GPIO_IN_VAL); 200 return ((bits & AR_GPIO_BIT(gpio)) != 0); 201 } 202 203 /* 204 * Set the GPIO Interrupt Sync and Async interrupts are both set/cleared. 205 * Async GPIO interrupts may not be raised when the chip is put to sleep. 206 */ 207 void 208 ar5416GpioSetIntr(struct ath_hal *ah, u_int gpio, uint32_t ilevel) 209 { 210 uint32_t val, mask; 211 212 HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.halNumGpioPins); 213 HALDEBUG(ah, HAL_DEBUG_GPIO, 214 "%s: gpio=%d, ilevel=%d\n", __func__, gpio, ilevel); 215 216 if (ilevel == HAL_GPIO_INTR_DISABLE) { 217 val = MS(OS_REG_READ(ah, AR_INTR_ASYNC_ENABLE), 218 AR_INTR_ASYNC_ENABLE_GPIO) &~ AR_GPIO_BIT(gpio); 219 OS_REG_RMW_FIELD(ah, AR_INTR_ASYNC_ENABLE, 220 AR_INTR_ASYNC_ENABLE_GPIO, val); 221 222 mask = MS(OS_REG_READ(ah, AR_INTR_ASYNC_MASK), 223 AR_INTR_ASYNC_MASK_GPIO) &~ AR_GPIO_BIT(gpio); 224 OS_REG_RMW_FIELD(ah, AR_INTR_ASYNC_MASK, 225 AR_INTR_ASYNC_MASK_GPIO, mask); 226 227 /* Clear synchronous GPIO interrupt registers and pending interrupt flag */ 228 val = MS(OS_REG_READ(ah, AR_INTR_SYNC_ENABLE), 229 AR_INTR_SYNC_ENABLE_GPIO) &~ AR_GPIO_BIT(gpio); 230 OS_REG_RMW_FIELD(ah, AR_INTR_SYNC_ENABLE, 231 AR_INTR_SYNC_ENABLE_GPIO, val); 232 233 mask = MS(OS_REG_READ(ah, AR_INTR_SYNC_MASK), 234 AR_INTR_SYNC_MASK_GPIO) &~ AR_GPIO_BIT(gpio); 235 OS_REG_RMW_FIELD(ah, AR_INTR_SYNC_MASK, 236 AR_INTR_SYNC_MASK_GPIO, mask); 237 238 val = MS(OS_REG_READ(ah, AR_INTR_SYNC_CAUSE), 239 AR_INTR_SYNC_ENABLE_GPIO) | AR_GPIO_BIT(gpio); 240 OS_REG_RMW_FIELD(ah, AR_INTR_SYNC_CAUSE, 241 AR_INTR_SYNC_ENABLE_GPIO, val); 242 } else { 243 val = MS(OS_REG_READ(ah, AR_GPIO_INTR_POL), 244 AR_GPIO_INTR_POL_VAL); 245 if (ilevel == HAL_GPIO_INTR_HIGH) { 246 /* 0 == interrupt on pin high */ 247 val &= ~AR_GPIO_BIT(gpio); 248 } else if (ilevel == HAL_GPIO_INTR_LOW) { 249 /* 1 == interrupt on pin low */ 250 val |= AR_GPIO_BIT(gpio); 251 } 252 OS_REG_RMW_FIELD(ah, AR_GPIO_INTR_POL, 253 AR_GPIO_INTR_POL_VAL, val); 254 255 /* Change the interrupt mask. */ 256 val = MS(OS_REG_READ(ah, AR_INTR_ASYNC_ENABLE), 257 AR_INTR_ASYNC_ENABLE_GPIO) | AR_GPIO_BIT(gpio); 258 OS_REG_RMW_FIELD(ah, AR_INTR_ASYNC_ENABLE, 259 AR_INTR_ASYNC_ENABLE_GPIO, val); 260 261 mask = MS(OS_REG_READ(ah, AR_INTR_ASYNC_MASK), 262 AR_INTR_ASYNC_MASK_GPIO) | AR_GPIO_BIT(gpio); 263 OS_REG_RMW_FIELD(ah, AR_INTR_ASYNC_MASK, 264 AR_INTR_ASYNC_MASK_GPIO, mask); 265 266 /* Set synchronous GPIO interrupt registers as well */ 267 val = MS(OS_REG_READ(ah, AR_INTR_SYNC_ENABLE), 268 AR_INTR_SYNC_ENABLE_GPIO) | AR_GPIO_BIT(gpio); 269 OS_REG_RMW_FIELD(ah, AR_INTR_SYNC_ENABLE, 270 AR_INTR_SYNC_ENABLE_GPIO, val); 271 272 mask = MS(OS_REG_READ(ah, AR_INTR_SYNC_MASK), 273 AR_INTR_SYNC_MASK_GPIO) | AR_GPIO_BIT(gpio); 274 OS_REG_RMW_FIELD(ah, AR_INTR_SYNC_MASK, 275 AR_INTR_SYNC_MASK_GPIO, mask); 276 } 277 AH5416(ah)->ah_gpioMask = mask; /* for ar5416SetInterrupts */ 278 } 279