From e6a3b61681dcb963e6465ffbc4330b44824f35e3 Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Tue, 9 Jun 2009 17:33:27 +0200 Subject: ath5k: added cfg80211 based rfkill support This patch introduces initial rfkill support for the ath5k driver based on rfkill support in the cfg80211 framework. All rfkill related code is separated into newly created rfkill.c. Changes to existing code are minimal: * added a new data structure ath5k_rfkill to the ath5k_softc structure * inserted calls to HW rfkill init/deinit routines * ath5k_intr() has been extended to handle AR5K_INT_GPIO interrupts Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/rfkill.c | 121 ++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 drivers/net/wireless/ath/ath5k/rfkill.c (limited to 'drivers/net/wireless/ath/ath5k/rfkill.c') diff --git a/drivers/net/wireless/ath/ath5k/rfkill.c b/drivers/net/wireless/ath/ath5k/rfkill.c new file mode 100644 index 000000000000..492ada92db56 --- /dev/null +++ b/drivers/net/wireless/ath/ath5k/rfkill.c @@ -0,0 +1,121 @@ +/* + * RFKILL support for ath5k + * + * Copyright (c) 2009 Tobias Doerffel + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGES. + */ + +#include "base.h" + + +static inline void ath5k_rfkill_disable(struct ath5k_softc *sc) +{ + ATH5K_DBG(sc, ATH5K_DEBUG_ANY, "rfkill disable (gpio:%d polarity:%d)\n", + sc->rf_kill.gpio, sc->rf_kill.polarity); + ath5k_hw_set_gpio_output(sc->ah, sc->rf_kill.gpio); + ath5k_hw_set_gpio(sc->ah, sc->rf_kill.gpio, !sc->rf_kill.polarity); +} + + +static inline void ath5k_rfkill_enable(struct ath5k_softc *sc) +{ + ATH5K_DBG(sc, ATH5K_DEBUG_ANY, "rfkill enable (gpio:%d polarity:%d)\n", + sc->rf_kill.gpio, sc->rf_kill.polarity); + ath5k_hw_set_gpio_output(sc->ah, sc->rf_kill.gpio); + ath5k_hw_set_gpio(sc->ah, sc->rf_kill.gpio, sc->rf_kill.polarity); +} + +static inline void ath5k_rfkill_set_intr(struct ath5k_softc *sc, bool enable) +{ + struct ath5k_hw *ah = sc->ah; + ath5k_hw_set_gpio_input(ah, sc->rf_kill.gpio); + ah->ah_gpio[0] = ath5k_hw_get_gpio(ah, sc->rf_kill.gpio); + ath5k_hw_set_gpio_intr(ah, sc->rf_kill.gpio, enable ? + !!ah->ah_gpio[0] : !ah->ah_gpio[0]); +} + +static bool +ath5k_is_rfkill_set(struct ath5k_softc *sc) +{ + /* configuring GPIO for input for some reason disables rfkill */ + /*ath5k_hw_set_gpio_input(sc->ah, sc->rf_kill.gpio);*/ + return ath5k_hw_get_gpio(sc->ah, sc->rf_kill.gpio) == + sc->rf_kill.polarity; +} + +static void +ath5k_tasklet_rfkill_toggle(unsigned long data) +{ + struct ath5k_softc *sc = (void *)data; + bool blocked; + + blocked = ath5k_is_rfkill_set(sc); + wiphy_rfkill_set_hw_state(sc->hw->wiphy, blocked); +} + + +void +ath5k_rfkill_hw_start(struct ath5k_hw *ah) +{ + struct ath5k_softc *sc = ah->ah_sc; + + /* read rfkill GPIO configuration from EEPROM header */ + sc->rf_kill.gpio = ah->ah_capabilities.cap_eeprom.ee_rfkill_pin; + sc->rf_kill.polarity = ah->ah_capabilities.cap_eeprom.ee_rfkill_pol; + + tasklet_init(&sc->rf_kill.toggleq, ath5k_tasklet_rfkill_toggle, + (unsigned long)sc); + + ath5k_rfkill_disable(sc); + + /* enable interrupt for rfkill switch */ + if (AR5K_EEPROM_HDR_RFKILL(ah->ah_capabilities.cap_eeprom.ee_header)) { + ath5k_rfkill_set_intr(sc, true); + } +} + + +void +ath5k_rfkill_hw_stop(struct ath5k_hw *ah) +{ + struct ath5k_softc *sc = ah->ah_sc; + + /* disable interrupt for rfkill switch */ + if (AR5K_EEPROM_HDR_RFKILL(ah->ah_capabilities.cap_eeprom.ee_header)) { + ath5k_rfkill_set_intr(sc, false); + } + + tasklet_kill(&sc->rf_kill.toggleq); + + /* enable RFKILL when stopping HW so Wifi LED is turned off */ + ath5k_rfkill_enable(sc); +} + -- cgit v1.2.3 From a6ae0716e5c3b5f9dbe5ed8f473a6c7b89692365 Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Tue, 9 Jun 2009 23:43:11 -0400 Subject: ath5k: minor rfkill cleanup Always enable rfkill since the ifdefs in the code is not really worth the Kconfig option. Also fix a few code style things, and remove the usage of the ah_gpio[] array so we can remove it later. Signed-off-by: Bob Copeland Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/rfkill.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/net/wireless/ath/ath5k/rfkill.c') diff --git a/drivers/net/wireless/ath/ath5k/rfkill.c b/drivers/net/wireless/ath/ath5k/rfkill.c index 492ada92db56..41a877b73fce 100644 --- a/drivers/net/wireless/ath/ath5k/rfkill.c +++ b/drivers/net/wireless/ath/ath5k/rfkill.c @@ -56,10 +56,12 @@ static inline void ath5k_rfkill_enable(struct ath5k_softc *sc) static inline void ath5k_rfkill_set_intr(struct ath5k_softc *sc, bool enable) { struct ath5k_hw *ah = sc->ah; + u32 curval; + ath5k_hw_set_gpio_input(ah, sc->rf_kill.gpio); - ah->ah_gpio[0] = ath5k_hw_get_gpio(ah, sc->rf_kill.gpio); + curval = ath5k_hw_get_gpio(ah, sc->rf_kill.gpio); ath5k_hw_set_gpio_intr(ah, sc->rf_kill.gpio, enable ? - !!ah->ah_gpio[0] : !ah->ah_gpio[0]); + !!curval : !curval); } static bool @@ -97,9 +99,8 @@ ath5k_rfkill_hw_start(struct ath5k_hw *ah) ath5k_rfkill_disable(sc); /* enable interrupt for rfkill switch */ - if (AR5K_EEPROM_HDR_RFKILL(ah->ah_capabilities.cap_eeprom.ee_header)) { + if (AR5K_EEPROM_HDR_RFKILL(ah->ah_capabilities.cap_eeprom.ee_header)) ath5k_rfkill_set_intr(sc, true); - } } @@ -109,9 +110,8 @@ ath5k_rfkill_hw_stop(struct ath5k_hw *ah) struct ath5k_softc *sc = ah->ah_sc; /* disable interrupt for rfkill switch */ - if (AR5K_EEPROM_HDR_RFKILL(ah->ah_capabilities.cap_eeprom.ee_header)) { + if (AR5K_EEPROM_HDR_RFKILL(ah->ah_capabilities.cap_eeprom.ee_header)) ath5k_rfkill_set_intr(sc, false); - } tasklet_kill(&sc->rf_kill.toggleq); -- cgit v1.2.3