116 lines · c
1/*2 * RFKILL support for ath5k3 *4 * Copyright (c) 2009 Tobias Doerffel <tobias.doerffel@gmail.com>5 *6 * All rights reserved.7 *8 * Redistribution and use in source and binary forms, with or without9 * modification, are permitted provided that the following conditions10 * are met:11 * 1. Redistributions of source code must retain the above copyright12 * notice, this list of conditions and the following disclaimer,13 * without modification.14 * 2. Redistributions in binary form must reproduce at minimum a disclaimer15 * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any16 * redistribution must be conditioned upon including a substantially17 * similar Disclaimer requirement for further binary redistribution.18 * 3. Neither the names of the above-listed copyright holders nor the names19 * of any contributors may be used to endorse or promote products derived20 * from this software without specific prior written permission.21 *22 * NO WARRANTY23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS24 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT25 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY26 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL27 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,28 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS30 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER31 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)32 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF33 * THE POSSIBILITY OF SUCH DAMAGES.34 */35 36#include "ath5k.h"37 38 39static inline void ath5k_rfkill_disable(struct ath5k_hw *ah)40{41 ATH5K_DBG(ah, ATH5K_DEBUG_ANY, "rfkill disable (gpio:%d polarity:%d)\n",42 ah->rf_kill.gpio, ah->rf_kill.polarity);43 ath5k_hw_set_gpio_output(ah, ah->rf_kill.gpio);44 ath5k_hw_set_gpio(ah, ah->rf_kill.gpio, !ah->rf_kill.polarity);45}46 47 48static inline void ath5k_rfkill_enable(struct ath5k_hw *ah)49{50 ATH5K_DBG(ah, ATH5K_DEBUG_ANY, "rfkill enable (gpio:%d polarity:%d)\n",51 ah->rf_kill.gpio, ah->rf_kill.polarity);52 ath5k_hw_set_gpio_output(ah, ah->rf_kill.gpio);53 ath5k_hw_set_gpio(ah, ah->rf_kill.gpio, ah->rf_kill.polarity);54}55 56static inline void ath5k_rfkill_set_intr(struct ath5k_hw *ah, bool enable)57{58 u32 curval;59 60 ath5k_hw_set_gpio_input(ah, ah->rf_kill.gpio);61 curval = ath5k_hw_get_gpio(ah, ah->rf_kill.gpio);62 ath5k_hw_set_gpio_intr(ah, ah->rf_kill.gpio, enable ?63 !!curval : !curval);64}65 66static bool67ath5k_is_rfkill_set(struct ath5k_hw *ah)68{69 /* configuring GPIO for input for some reason disables rfkill */70 /*ath5k_hw_set_gpio_input(ah, ah->rf_kill.gpio);*/71 return ath5k_hw_get_gpio(ah, ah->rf_kill.gpio) ==72 ah->rf_kill.polarity;73}74 75static void76ath5k_tasklet_rfkill_toggle(struct tasklet_struct *t)77{78 struct ath5k_hw *ah = from_tasklet(ah, t, rf_kill.toggleq);79 bool blocked;80 81 blocked = ath5k_is_rfkill_set(ah);82 wiphy_rfkill_set_hw_state(ah->hw->wiphy, blocked);83}84 85 86void87ath5k_rfkill_hw_start(struct ath5k_hw *ah)88{89 /* read rfkill GPIO configuration from EEPROM header */90 ah->rf_kill.gpio = ah->ah_capabilities.cap_eeprom.ee_rfkill_pin;91 ah->rf_kill.polarity = ah->ah_capabilities.cap_eeprom.ee_rfkill_pol;92 93 tasklet_setup(&ah->rf_kill.toggleq, ath5k_tasklet_rfkill_toggle);94 95 ath5k_rfkill_disable(ah);96 97 /* enable interrupt for rfkill switch */98 if (AR5K_EEPROM_HDR_RFKILL(ah->ah_capabilities.cap_eeprom.ee_header))99 ath5k_rfkill_set_intr(ah, true);100}101 102 103void104ath5k_rfkill_hw_stop(struct ath5k_hw *ah)105{106 /* disable interrupt for rfkill switch */107 if (AR5K_EEPROM_HDR_RFKILL(ah->ah_capabilities.cap_eeprom.ee_header))108 ath5k_rfkill_set_intr(ah, false);109 110 tasklet_kill(&ah->rf_kill.toggleq);111 112 /* enable RFKILL when stopping HW so Wifi LED is turned off */113 ath5k_rfkill_enable(ah);114}115 116