Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
0003  * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
0004  *
0005  * Permission to use, copy, modify, and distribute this software for any
0006  * purpose with or without fee is hereby granted, provided that the above
0007  * copyright notice and this permission notice appear in all copies.
0008  *
0009  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
0010  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
0011  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
0012  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
0013  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
0014  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
0015  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
0016  *
0017  */
0018 
0019 /****************\
0020   GPIO Functions
0021 \****************/
0022 
0023 #include "ath5k.h"
0024 #include "reg.h"
0025 #include "debug.h"
0026 
0027 
0028 /**
0029  * DOC: GPIO/LED functions
0030  *
0031  * Here we control the 6 bidirectional GPIO pins provided by the hw.
0032  * We can set a GPIO pin to be an input or an output pin on GPIO control
0033  * register and then read or set its status from GPIO data input/output
0034  * registers.
0035  *
0036  * We also control the two LED pins provided by the hw, LED_0 is our
0037  * "power" LED and LED_1 is our "network activity" LED but many scenarios
0038  * are available from hw. Vendors might also provide LEDs connected to the
0039  * GPIO pins, we handle them through the LED subsystem on led.c
0040  */
0041 
0042 
0043 /**
0044  * ath5k_hw_set_ledstate() - Set led state
0045  * @ah: The &struct ath5k_hw
0046  * @state: One of AR5K_LED_*
0047  *
0048  * Used to set the LED blinking state. This only
0049  * works for the LED connected to the LED_0, LED_1 pins,
0050  * not the GPIO based.
0051  */
0052 void
0053 ath5k_hw_set_ledstate(struct ath5k_hw *ah, unsigned int state)
0054 {
0055     u32 led;
0056     /*5210 has different led mode handling*/
0057     u32 led_5210;
0058 
0059     /*Reset led status*/
0060     if (ah->ah_version != AR5K_AR5210)
0061         AR5K_REG_DISABLE_BITS(ah, AR5K_PCICFG,
0062             AR5K_PCICFG_LEDMODE |  AR5K_PCICFG_LED);
0063     else
0064         AR5K_REG_DISABLE_BITS(ah, AR5K_PCICFG, AR5K_PCICFG_LED);
0065 
0066     /*
0067      * Some blinking values, define at your wish
0068      */
0069     switch (state) {
0070     case AR5K_LED_SCAN:
0071     case AR5K_LED_AUTH:
0072         led = AR5K_PCICFG_LEDMODE_PROP | AR5K_PCICFG_LED_PEND;
0073         led_5210 = AR5K_PCICFG_LED_PEND | AR5K_PCICFG_LED_BCTL;
0074         break;
0075 
0076     case AR5K_LED_INIT:
0077         led = AR5K_PCICFG_LEDMODE_PROP | AR5K_PCICFG_LED_NONE;
0078         led_5210 = AR5K_PCICFG_LED_PEND;
0079         break;
0080 
0081     case AR5K_LED_ASSOC:
0082     case AR5K_LED_RUN:
0083         led = AR5K_PCICFG_LEDMODE_PROP | AR5K_PCICFG_LED_ASSOC;
0084         led_5210 = AR5K_PCICFG_LED_ASSOC;
0085         break;
0086 
0087     default:
0088         led = AR5K_PCICFG_LEDMODE_PROM | AR5K_PCICFG_LED_NONE;
0089         led_5210 = AR5K_PCICFG_LED_PEND;
0090         break;
0091     }
0092 
0093     /*Write new status to the register*/
0094     if (ah->ah_version != AR5K_AR5210)
0095         AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, led);
0096     else
0097         AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, led_5210);
0098 }
0099 
0100 /**
0101  * ath5k_hw_set_gpio_input() - Set GPIO inputs
0102  * @ah: The &struct ath5k_hw
0103  * @gpio: GPIO pin to set as input
0104  */
0105 int
0106 ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio)
0107 {
0108     if (gpio >= AR5K_NUM_GPIO)
0109         return -EINVAL;
0110 
0111     ath5k_hw_reg_write(ah,
0112         (ath5k_hw_reg_read(ah, AR5K_GPIOCR) & ~AR5K_GPIOCR_OUT(gpio))
0113         | AR5K_GPIOCR_IN(gpio), AR5K_GPIOCR);
0114 
0115     return 0;
0116 }
0117 
0118 /**
0119  * ath5k_hw_set_gpio_output() - Set GPIO outputs
0120  * @ah: The &struct ath5k_hw
0121  * @gpio: The GPIO pin to set as output
0122  */
0123 int
0124 ath5k_hw_set_gpio_output(struct ath5k_hw *ah, u32 gpio)
0125 {
0126     if (gpio >= AR5K_NUM_GPIO)
0127         return -EINVAL;
0128 
0129     ath5k_hw_reg_write(ah,
0130         (ath5k_hw_reg_read(ah, AR5K_GPIOCR) & ~AR5K_GPIOCR_OUT(gpio))
0131         | AR5K_GPIOCR_OUT(gpio), AR5K_GPIOCR);
0132 
0133     return 0;
0134 }
0135 
0136 /**
0137  * ath5k_hw_get_gpio() - Get GPIO state
0138  * @ah: The &struct ath5k_hw
0139  * @gpio: The GPIO pin to read
0140  */
0141 u32
0142 ath5k_hw_get_gpio(struct ath5k_hw *ah, u32 gpio)
0143 {
0144     if (gpio >= AR5K_NUM_GPIO)
0145         return 0xffffffff;
0146 
0147     /* GPIO input magic */
0148     return ((ath5k_hw_reg_read(ah, AR5K_GPIODI) & AR5K_GPIODI_M) >> gpio) &
0149         0x1;
0150 }
0151 
0152 /**
0153  * ath5k_hw_set_gpio() - Set GPIO state
0154  * @ah: The &struct ath5k_hw
0155  * @gpio: The GPIO pin to set
0156  * @val: Value to set (boolean)
0157  */
0158 int
0159 ath5k_hw_set_gpio(struct ath5k_hw *ah, u32 gpio, u32 val)
0160 {
0161     u32 data;
0162 
0163     if (gpio >= AR5K_NUM_GPIO)
0164         return -EINVAL;
0165 
0166     /* GPIO output magic */
0167     data = ath5k_hw_reg_read(ah, AR5K_GPIODO);
0168 
0169     data &= ~(1 << gpio);
0170     data |= (val & 1) << gpio;
0171 
0172     ath5k_hw_reg_write(ah, data, AR5K_GPIODO);
0173 
0174     return 0;
0175 }
0176 
0177 /**
0178  * ath5k_hw_set_gpio_intr() - Initialize the GPIO interrupt (RFKill switch)
0179  * @ah: The &struct ath5k_hw
0180  * @gpio: The GPIO pin to use
0181  * @interrupt_level: True to generate interrupt on active pin (high)
0182  *
0183  * This function is used to set up the GPIO interrupt for the hw RFKill switch.
0184  * That switch is connected to a GPIO pin and it's number is stored on EEPROM.
0185  * It can either open or close the circuit to indicate that we should disable
0186  * RF/Wireless to save power (we also get that from EEPROM).
0187  */
0188 void
0189 ath5k_hw_set_gpio_intr(struct ath5k_hw *ah, unsigned int gpio,
0190         u32 interrupt_level)
0191 {
0192     u32 data;
0193 
0194     if (gpio >= AR5K_NUM_GPIO)
0195         return;
0196 
0197     /*
0198      * Set the GPIO interrupt
0199      */
0200     data = (ath5k_hw_reg_read(ah, AR5K_GPIOCR) &
0201         ~(AR5K_GPIOCR_INT_SEL(gpio) | AR5K_GPIOCR_INT_SELH |
0202         AR5K_GPIOCR_INT_ENA | AR5K_GPIOCR_OUT(gpio))) |
0203         (AR5K_GPIOCR_INT_SEL(gpio) | AR5K_GPIOCR_INT_ENA);
0204 
0205     ath5k_hw_reg_write(ah, interrupt_level ? data :
0206         (data | AR5K_GPIOCR_INT_SELH), AR5K_GPIOCR);
0207 
0208     ah->ah_imr |= AR5K_IMR_GPIO;
0209 
0210     /* Enable GPIO interrupts */
0211     AR5K_REG_ENABLE_BITS(ah, AR5K_PIMR, AR5K_IMR_GPIO);
0212 }
0213