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 HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.halNumGpioPins); 89 90 HALDEBUG(ah, HAL_DEBUG_GPIO, 91 "%s: gpio=%d, type=%d\n", __func__, gpio, type); 92 93 /* NB: type maps directly to hardware */ 94 /* XXX this may not actually be the case, for anything but output */ 95 cfgOutputMux(ah, gpio, type); 96 gpio_shift = gpio << 1; /* 2 bits per output mode */ 97 98 reg = OS_REG_READ(ah, AR_GPIO_OE_OUT); 99 reg &= ~(AR_GPIO_OE_OUT_DRV << gpio_shift); 100 /* Always drive, rather than tristate/drive low/drive high */ 101 reg |= AR_GPIO_OE_OUT_DRV_ALL << gpio_shift; 102 OS_REG_WRITE(ah, AR_GPIO_OE_OUT, reg); 103 104 return AH_TRUE; 105 } 106 107 /* 108 * Configure GPIO Input lines 109 */ 110 HAL_BOOL 111 ar5416GpioCfgInput(struct ath_hal *ah, uint32_t gpio) 112 { 113 uint32_t gpio_shift, reg; 114 115 HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.halNumGpioPins); 116 117 HALDEBUG(ah, HAL_DEBUG_GPIO, "%s: gpio=%d\n", __func__, gpio); 118 119 /* TODO: configure input mux for AR5416 */ 120 /* If configured as input, set output to tristate */ 121 gpio_shift = gpio << 1; 122 123 reg = OS_REG_READ(ah, AR_GPIO_OE_OUT); 124 reg &= ~(AR_GPIO_OE_OUT_DRV << gpio_shift); 125 reg |= AR_GPIO_OE_OUT_DRV_ALL << gpio_shift; 126 OS_REG_WRITE(ah, AR_GPIO_OE_OUT, reg); 127 128 return AH_TRUE; 129 } 130 131 /* 132 * Once configured for I/O - set output lines 133 */ 134 HAL_BOOL 135 ar5416GpioSet(struct ath_hal *ah, uint32_t gpio, uint32_t val) 136 { 137 uint32_t reg; 138 139 HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.halNumGpioPins); 140 HALDEBUG(ah, HAL_DEBUG_GPIO, 141 "%s: gpio=%d, val=%d\n", __func__, gpio, val); 142 143 reg = OS_REG_READ(ah, AR_GPIO_IN_OUT); 144 if (val & 1) 145 reg |= AR_GPIO_BIT(gpio); 146 else 147 reg &= ~AR_GPIO_BIT(gpio); 148 OS_REG_WRITE(ah, AR_GPIO_IN_OUT, reg); 149 return AH_TRUE; 150 } 151 152 /* 153 * Once configured for I/O - get input lines 154 */ 155 uint32_t 156 ar5416GpioGet(struct ath_hal *ah, uint32_t gpio) 157 { 158 uint32_t bits; 159 160 if (gpio >= AH_PRIVATE(ah)->ah_caps.halNumGpioPins) 161 return 0xffffffff; 162 /* 163 * Read output value for all gpio's, shift it, 164 * and verify whether the specific bit is set. 165 */ 166 if (AR_SREV_KIWI_10_OR_LATER(ah)) 167 bits = MS(OS_REG_READ(ah, AR_GPIO_IN_OUT), AR9287_GPIO_IN_VAL); 168 if (AR_SREV_KITE_10_OR_LATER(ah)) 169 bits = MS(OS_REG_READ(ah, AR_GPIO_IN_OUT), AR9285_GPIO_IN_VAL); 170 else if (AR_SREV_MERLIN_10_OR_LATER(ah)) 171 bits = MS(OS_REG_READ(ah, AR_GPIO_IN_OUT), AR928X_GPIO_IN_VAL); 172 else 173 bits = MS(OS_REG_READ(ah, AR_GPIO_IN_OUT), AR_GPIO_IN_VAL); 174 return ((bits & AR_GPIO_BIT(gpio)) != 0); 175 } 176 177 /* 178 * Set the GPIO Interrupt Sync and Async interrupts are both set/cleared. 179 * Async GPIO interrupts may not be raised when the chip is put to sleep. 180 */ 181 void 182 ar5416GpioSetIntr(struct ath_hal *ah, u_int gpio, uint32_t ilevel) 183 { 184 uint32_t val, mask; 185 186 HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.halNumGpioPins); 187 HALDEBUG(ah, HAL_DEBUG_GPIO, 188 "%s: gpio=%d, ilevel=%d\n", __func__, gpio, ilevel); 189 190 if (ilevel == HAL_GPIO_INTR_DISABLE) { 191 val = MS(OS_REG_READ(ah, AR_INTR_ASYNC_ENABLE), 192 AR_INTR_ASYNC_ENABLE_GPIO) &~ AR_GPIO_BIT(gpio); 193 OS_REG_RMW_FIELD(ah, AR_INTR_ASYNC_ENABLE, 194 AR_INTR_ASYNC_ENABLE_GPIO, val); 195 196 mask = MS(OS_REG_READ(ah, AR_INTR_ASYNC_MASK), 197 AR_INTR_ASYNC_MASK_GPIO) &~ AR_GPIO_BIT(gpio); 198 OS_REG_RMW_FIELD(ah, AR_INTR_ASYNC_MASK, 199 AR_INTR_ASYNC_MASK_GPIO, mask); 200 201 /* Clear synchronous GPIO interrupt registers and pending interrupt flag */ 202 val = MS(OS_REG_READ(ah, AR_INTR_SYNC_ENABLE), 203 AR_INTR_SYNC_ENABLE_GPIO) &~ AR_GPIO_BIT(gpio); 204 OS_REG_RMW_FIELD(ah, AR_INTR_SYNC_ENABLE, 205 AR_INTR_SYNC_ENABLE_GPIO, val); 206 207 mask = MS(OS_REG_READ(ah, AR_INTR_SYNC_MASK), 208 AR_INTR_SYNC_MASK_GPIO) &~ AR_GPIO_BIT(gpio); 209 OS_REG_RMW_FIELD(ah, AR_INTR_SYNC_MASK, 210 AR_INTR_SYNC_MASK_GPIO, mask); 211 212 val = MS(OS_REG_READ(ah, AR_INTR_SYNC_CAUSE), 213 AR_INTR_SYNC_ENABLE_GPIO) | AR_GPIO_BIT(gpio); 214 OS_REG_RMW_FIELD(ah, AR_INTR_SYNC_CAUSE, 215 AR_INTR_SYNC_ENABLE_GPIO, val); 216 } else { 217 val = MS(OS_REG_READ(ah, AR_GPIO_INTR_POL), 218 AR_GPIO_INTR_POL_VAL); 219 if (ilevel == HAL_GPIO_INTR_HIGH) { 220 /* 0 == interrupt on pin high */ 221 val &= ~AR_GPIO_BIT(gpio); 222 } else if (ilevel == HAL_GPIO_INTR_LOW) { 223 /* 1 == interrupt on pin low */ 224 val |= AR_GPIO_BIT(gpio); 225 } 226 OS_REG_RMW_FIELD(ah, AR_GPIO_INTR_POL, 227 AR_GPIO_INTR_POL_VAL, val); 228 229 /* Change the interrupt mask. */ 230 val = MS(OS_REG_READ(ah, AR_INTR_ASYNC_ENABLE), 231 AR_INTR_ASYNC_ENABLE_GPIO) | AR_GPIO_BIT(gpio); 232 OS_REG_RMW_FIELD(ah, AR_INTR_ASYNC_ENABLE, 233 AR_INTR_ASYNC_ENABLE_GPIO, val); 234 235 mask = MS(OS_REG_READ(ah, AR_INTR_ASYNC_MASK), 236 AR_INTR_ASYNC_MASK_GPIO) | AR_GPIO_BIT(gpio); 237 OS_REG_RMW_FIELD(ah, AR_INTR_ASYNC_MASK, 238 AR_INTR_ASYNC_MASK_GPIO, mask); 239 240 /* Set synchronous GPIO interrupt registers as well */ 241 val = MS(OS_REG_READ(ah, AR_INTR_SYNC_ENABLE), 242 AR_INTR_SYNC_ENABLE_GPIO) | AR_GPIO_BIT(gpio); 243 OS_REG_RMW_FIELD(ah, AR_INTR_SYNC_ENABLE, 244 AR_INTR_SYNC_ENABLE_GPIO, val); 245 246 mask = MS(OS_REG_READ(ah, AR_INTR_SYNC_MASK), 247 AR_INTR_SYNC_MASK_GPIO) | AR_GPIO_BIT(gpio); 248 OS_REG_RMW_FIELD(ah, AR_INTR_SYNC_MASK, 249 AR_INTR_SYNC_MASK_GPIO, mask); 250 } 251 AH5416(ah)->ah_gpioMask = mask; /* for ar5416SetInterrupts */ 252 } 253