1 /* 2 * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org> 3 * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com> 4 * 5 * Permission to use, copy, modify, and 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 */ 18 19 /****************\ 20 GPIO Functions 21 \****************/ 22 23 #include "ath5k.h" 24 #include "reg.h" 25 #include "debug.h" 26 #include "base.h" 27 28 /* 29 * Set led state 30 */ 31 void ath5k_hw_set_ledstate(struct ath5k_hw *ah, unsigned int state) 32 { 33 u32 led; 34 /*5210 has different led mode handling*/ 35 u32 led_5210; 36 37 /*Reset led status*/ 38 if (ah->ah_version != AR5K_AR5210) 39 AR5K_REG_DISABLE_BITS(ah, AR5K_PCICFG, 40 AR5K_PCICFG_LEDMODE | AR5K_PCICFG_LED); 41 else 42 AR5K_REG_DISABLE_BITS(ah, AR5K_PCICFG, AR5K_PCICFG_LED); 43 44 /* 45 * Some blinking values, define at your wish 46 */ 47 switch (state) { 48 case AR5K_LED_SCAN: 49 case AR5K_LED_AUTH: 50 led = AR5K_PCICFG_LEDMODE_PROP | AR5K_PCICFG_LED_PEND; 51 led_5210 = AR5K_PCICFG_LED_PEND | AR5K_PCICFG_LED_BCTL; 52 break; 53 54 case AR5K_LED_INIT: 55 led = AR5K_PCICFG_LEDMODE_PROP | AR5K_PCICFG_LED_NONE; 56 led_5210 = AR5K_PCICFG_LED_PEND; 57 break; 58 59 case AR5K_LED_ASSOC: 60 case AR5K_LED_RUN: 61 led = AR5K_PCICFG_LEDMODE_PROP | AR5K_PCICFG_LED_ASSOC; 62 led_5210 = AR5K_PCICFG_LED_ASSOC; 63 break; 64 65 default: 66 led = AR5K_PCICFG_LEDMODE_PROM | AR5K_PCICFG_LED_NONE; 67 led_5210 = AR5K_PCICFG_LED_PEND; 68 break; 69 } 70 71 /*Write new status to the register*/ 72 if (ah->ah_version != AR5K_AR5210) 73 AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, led); 74 else 75 AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, led_5210); 76 } 77 78 /* 79 * Set GPIO inputs 80 */ 81 int ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio) 82 { 83 if (gpio >= AR5K_NUM_GPIO) 84 return -EINVAL; 85 86 ath5k_hw_reg_write(ah, 87 (ath5k_hw_reg_read(ah, AR5K_GPIOCR) & ~AR5K_GPIOCR_OUT(gpio)) 88 | AR5K_GPIOCR_IN(gpio), AR5K_GPIOCR); 89 90 return 0; 91 } 92 93 /* 94 * Set GPIO outputs 95 */ 96 int ath5k_hw_set_gpio_output(struct ath5k_hw *ah, u32 gpio) 97 { 98 if (gpio >= AR5K_NUM_GPIO) 99 return -EINVAL; 100 101 ath5k_hw_reg_write(ah, 102 (ath5k_hw_reg_read(ah, AR5K_GPIOCR) & ~AR5K_GPIOCR_OUT(gpio)) 103 | AR5K_GPIOCR_OUT(gpio), AR5K_GPIOCR); 104 105 return 0; 106 } 107 108 /* 109 * Get GPIO state 110 */ 111 u32 ath5k_hw_get_gpio(struct ath5k_hw *ah, u32 gpio) 112 { 113 if (gpio >= AR5K_NUM_GPIO) 114 return 0xffffffff; 115 116 /* GPIO input magic */ 117 return ((ath5k_hw_reg_read(ah, AR5K_GPIODI) & AR5K_GPIODI_M) >> gpio) & 118 0x1; 119 } 120 121 /* 122 * Set GPIO state 123 */ 124 int ath5k_hw_set_gpio(struct ath5k_hw *ah, u32 gpio, u32 val) 125 { 126 u32 data; 127 128 if (gpio >= AR5K_NUM_GPIO) 129 return -EINVAL; 130 131 /* GPIO output magic */ 132 data = ath5k_hw_reg_read(ah, AR5K_GPIODO); 133 134 data &= ~(1 << gpio); 135 data |= (val & 1) << gpio; 136 137 ath5k_hw_reg_write(ah, data, AR5K_GPIODO); 138 139 return 0; 140 } 141 142 /* 143 * Initialize the GPIO interrupt (RFKill switch) 144 */ 145 void ath5k_hw_set_gpio_intr(struct ath5k_hw *ah, unsigned int gpio, 146 u32 interrupt_level) 147 { 148 u32 data; 149 150 if (gpio >= AR5K_NUM_GPIO) 151 return; 152 153 /* 154 * Set the GPIO interrupt 155 */ 156 data = (ath5k_hw_reg_read(ah, AR5K_GPIOCR) & 157 ~(AR5K_GPIOCR_INT_SEL(gpio) | AR5K_GPIOCR_INT_SELH | 158 AR5K_GPIOCR_INT_ENA | AR5K_GPIOCR_OUT(gpio))) | 159 (AR5K_GPIOCR_INT_SEL(gpio) | AR5K_GPIOCR_INT_ENA); 160 161 ath5k_hw_reg_write(ah, interrupt_level ? data : 162 (data | AR5K_GPIOCR_INT_SELH), AR5K_GPIOCR); 163 164 ah->ah_imr |= AR5K_IMR_GPIO; 165 166 /* Enable GPIO interrupts */ 167 AR5K_REG_ENABLE_BITS(ah, AR5K_PIMR, AR5K_IMR_GPIO); 168 } 169 170