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