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, reg; 39 40 /* each MUX controls 6 GPIO pins */ 41 if (gpio > 11) 42 addr = AR_GPIO_OUTPUT_MUX3; 43 else if (gpio > 5) 44 addr = AR_GPIO_OUTPUT_MUX2; 45 else 46 addr = AR_GPIO_OUTPUT_MUX1; 47 48 /* 49 * 5 bits per GPIO pin. Bits 0..4 for 1st pin in that mux, 50 * bits 5..9 for 2nd pin, etc. 51 */ 52 gpio_shift = (gpio % 6) * 5; 53 54 /* 55 * From Owl to Merlin 1.0, the value read from MUX1 bit 4 to bit 56 * 9 are wrong. Here is hardware's coding: 57 * PRDATA[4:0] <= gpio_output_mux[0]; 58 * PRDATA[9:4] <= gpio_output_mux[1]; 59 * <==== Bit 4 is used by both gpio_output_mux[0] [1]. 60 * Currently the max value for gpio_output_mux[] is 6. So bit 4 61 * will never be used. So it should be fine that bit 4 won't be 62 * able to recover. 63 */ 64 reg = OS_REG_READ(ah, addr); 65 if (addr == AR_GPIO_OUTPUT_MUX1 && !AR_SREV_MERLIN_20_OR_LATER(ah)) 66 reg = ((reg & 0x1F0) << 1) | (reg & ~0x1F0); 67 reg &= ~(0x1f << gpio_shift); 68 reg |= type << gpio_shift; 69 OS_REG_WRITE(ah, addr, reg); 70 } 71 72 /* 73 * Configure GPIO Output lines 74 */ 75 HAL_BOOL 76 ar5416GpioCfgOutput(struct ath_hal *ah, uint32_t gpio, HAL_GPIO_MUX_TYPE type) 77 { 78 uint32_t gpio_shift, reg; 79 80 HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.halNumGpioPins); 81 82 /* NB: type maps directly to hardware */ 83 cfgOutputMux(ah, gpio, type); 84 gpio_shift = gpio << 1; /* 2 bits per output mode */ 85 86 reg = OS_REG_READ(ah, AR_GPIO_OE_OUT); 87 reg &= ~(AR_GPIO_OE_OUT_DRV << gpio_shift); 88 reg |= AR_GPIO_OE_OUT_DRV_ALL << gpio_shift; 89 OS_REG_WRITE(ah, AR_GPIO_OE_OUT, reg); 90 91 return AH_TRUE; 92 } 93 94 /* 95 * Configure GPIO Input lines 96 */ 97 HAL_BOOL 98 ar5416GpioCfgInput(struct ath_hal *ah, uint32_t gpio) 99 { 100 uint32_t gpio_shift, reg; 101 102 HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.halNumGpioPins); 103 104 /* TODO: configure input mux for AR5416 */ 105 /* If configured as input, set output to tristate */ 106 gpio_shift = gpio << 1; 107 108 reg = OS_REG_READ(ah, AR_GPIO_OE_OUT); 109 reg &= ~(AR_GPIO_OE_OUT_DRV << gpio_shift); 110 reg |= AR_GPIO_OE_OUT_DRV_ALL << gpio_shift; 111 OS_REG_WRITE(ah, AR_GPIO_OE_OUT, reg); 112 113 return AH_TRUE; 114 } 115 116 /* 117 * Once configured for I/O - set output lines 118 */ 119 HAL_BOOL 120 ar5416GpioSet(struct ath_hal *ah, uint32_t gpio, uint32_t val) 121 { 122 uint32_t reg; 123 124 HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.halNumGpioPins); 125 126 reg = OS_REG_READ(ah, AR_GPIO_IN_OUT); 127 if (val & 1) 128 reg |= AR_GPIO_BIT(gpio); 129 else 130 reg &= ~AR_GPIO_BIT(gpio); 131 OS_REG_WRITE(ah, AR_GPIO_IN_OUT, reg); 132 return AH_TRUE; 133 } 134 135 /* 136 * Once configured for I/O - get input lines 137 */ 138 uint32_t 139 ar5416GpioGet(struct ath_hal *ah, uint32_t gpio) 140 { 141 uint32_t bits; 142 143 if (gpio >= AH_PRIVATE(ah)->ah_caps.halNumGpioPins) 144 return 0xffffffff; 145 /* 146 * Read output value for all gpio's, shift it, 147 * and verify whether the specific bit is set. 148 */ 149 if (AR_SREV_KITE_10_OR_LATER(ah)) 150 bits = MS(OS_REG_READ(ah, AR_GPIO_IN_OUT), AR9285_GPIO_IN_VAL); 151 else if (AR_SREV_MERLIN_10_OR_LATER(ah)) 152 bits = MS(OS_REG_READ(ah, AR_GPIO_IN_OUT), AR928X_GPIO_IN_VAL); 153 else 154 bits = MS(OS_REG_READ(ah, AR_GPIO_IN_OUT), AR_GPIO_IN_VAL); 155 return ((bits & AR_GPIO_BIT(gpio)) != 0); 156 } 157 158 /* 159 * Set the GPIO Interrupt Sync and Async interrupts are both set/cleared. 160 * Async GPIO interrupts may not be raised when the chip is put to sleep. 161 */ 162 void 163 ar5416GpioSetIntr(struct ath_hal *ah, u_int gpio, uint32_t ilevel) 164 { 165 uint32_t val, mask; 166 167 HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.halNumGpioPins); 168 169 if (ilevel == HAL_GPIO_INTR_DISABLE) { 170 val = MS(OS_REG_READ(ah, AR_INTR_ASYNC_ENABLE), 171 AR_INTR_ASYNC_ENABLE_GPIO) &~ AR_GPIO_BIT(gpio); 172 OS_REG_RMW_FIELD(ah, AR_INTR_ASYNC_ENABLE, 173 AR_INTR_ASYNC_ENABLE_GPIO, val); 174 175 mask = MS(OS_REG_READ(ah, AR_INTR_ASYNC_MASK), 176 AR_INTR_ASYNC_MASK_GPIO) &~ AR_GPIO_BIT(gpio); 177 OS_REG_RMW_FIELD(ah, AR_INTR_ASYNC_MASK, 178 AR_INTR_ASYNC_MASK_GPIO, mask); 179 180 /* Clear synchronous GPIO interrupt registers and pending interrupt flag */ 181 val = MS(OS_REG_READ(ah, AR_INTR_SYNC_ENABLE), 182 AR_INTR_SYNC_ENABLE_GPIO) &~ AR_GPIO_BIT(gpio); 183 OS_REG_RMW_FIELD(ah, AR_INTR_SYNC_ENABLE, 184 AR_INTR_SYNC_ENABLE_GPIO, val); 185 186 mask = MS(OS_REG_READ(ah, AR_INTR_SYNC_MASK), 187 AR_INTR_SYNC_MASK_GPIO) &~ AR_GPIO_BIT(gpio); 188 OS_REG_RMW_FIELD(ah, AR_INTR_SYNC_MASK, 189 AR_INTR_SYNC_MASK_GPIO, mask); 190 191 val = MS(OS_REG_READ(ah, AR_INTR_SYNC_CAUSE), 192 AR_INTR_SYNC_ENABLE_GPIO) | AR_GPIO_BIT(gpio); 193 OS_REG_RMW_FIELD(ah, AR_INTR_SYNC_CAUSE, 194 AR_INTR_SYNC_ENABLE_GPIO, val); 195 } else { 196 val = MS(OS_REG_READ(ah, AR_GPIO_INTR_POL), 197 AR_GPIO_INTR_POL_VAL); 198 if (ilevel == HAL_GPIO_INTR_HIGH) { 199 /* 0 == interrupt on pin high */ 200 val &= ~AR_GPIO_BIT(gpio); 201 } else if (ilevel == HAL_GPIO_INTR_LOW) { 202 /* 1 == interrupt on pin low */ 203 val |= AR_GPIO_BIT(gpio); 204 } 205 OS_REG_RMW_FIELD(ah, AR_GPIO_INTR_POL, 206 AR_GPIO_INTR_POL_VAL, val); 207 208 /* Change the interrupt mask. */ 209 val = MS(OS_REG_READ(ah, AR_INTR_ASYNC_ENABLE), 210 AR_INTR_ASYNC_ENABLE_GPIO) | AR_GPIO_BIT(gpio); 211 OS_REG_RMW_FIELD(ah, AR_INTR_ASYNC_ENABLE, 212 AR_INTR_ASYNC_ENABLE_GPIO, val); 213 214 mask = MS(OS_REG_READ(ah, AR_INTR_ASYNC_MASK), 215 AR_INTR_ASYNC_MASK_GPIO) | AR_GPIO_BIT(gpio); 216 OS_REG_RMW_FIELD(ah, AR_INTR_ASYNC_MASK, 217 AR_INTR_ASYNC_MASK_GPIO, mask); 218 219 /* Set synchronous GPIO interrupt registers as well */ 220 val = MS(OS_REG_READ(ah, AR_INTR_SYNC_ENABLE), 221 AR_INTR_SYNC_ENABLE_GPIO) | AR_GPIO_BIT(gpio); 222 OS_REG_RMW_FIELD(ah, AR_INTR_SYNC_ENABLE, 223 AR_INTR_SYNC_ENABLE_GPIO, val); 224 225 mask = MS(OS_REG_READ(ah, AR_INTR_SYNC_MASK), 226 AR_INTR_SYNC_MASK_GPIO) | AR_GPIO_BIT(gpio); 227 OS_REG_RMW_FIELD(ah, AR_INTR_SYNC_MASK, 228 AR_INTR_SYNC_MASK_GPIO, mask); 229 } 230 AH5416(ah)->ah_gpioMask = mask; /* for ar5416SetInterrupts */ 231 } 232