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