162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * RFKILL support for ath5k 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Copyright (c) 2009 Tobias Doerffel <tobias.doerffel@gmail.com> 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * All rights reserved. 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * Redistribution and use in source and binary forms, with or without 962306a36Sopenharmony_ci * modification, are permitted provided that the following conditions 1062306a36Sopenharmony_ci * are met: 1162306a36Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright 1262306a36Sopenharmony_ci * notice, this list of conditions and the following disclaimer, 1362306a36Sopenharmony_ci * without modification. 1462306a36Sopenharmony_ci * 2. Redistributions in binary form must reproduce at minimum a disclaimer 1562306a36Sopenharmony_ci * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 1662306a36Sopenharmony_ci * redistribution must be conditioned upon including a substantially 1762306a36Sopenharmony_ci * similar Disclaimer requirement for further binary redistribution. 1862306a36Sopenharmony_ci * 3. Neither the names of the above-listed copyright holders nor the names 1962306a36Sopenharmony_ci * of any contributors may be used to endorse or promote products derived 2062306a36Sopenharmony_ci * from this software without specific prior written permission. 2162306a36Sopenharmony_ci * 2262306a36Sopenharmony_ci * NO WARRANTY 2362306a36Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2462306a36Sopenharmony_ci * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2562306a36Sopenharmony_ci * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 2662306a36Sopenharmony_ci * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 2762306a36Sopenharmony_ci * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 2862306a36Sopenharmony_ci * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2962306a36Sopenharmony_ci * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 3062306a36Sopenharmony_ci * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 3162306a36Sopenharmony_ci * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 3262306a36Sopenharmony_ci * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 3362306a36Sopenharmony_ci * THE POSSIBILITY OF SUCH DAMAGES. 3462306a36Sopenharmony_ci */ 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci#include "ath5k.h" 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_cistatic inline void ath5k_rfkill_disable(struct ath5k_hw *ah) 4062306a36Sopenharmony_ci{ 4162306a36Sopenharmony_ci ATH5K_DBG(ah, ATH5K_DEBUG_ANY, "rfkill disable (gpio:%d polarity:%d)\n", 4262306a36Sopenharmony_ci ah->rf_kill.gpio, ah->rf_kill.polarity); 4362306a36Sopenharmony_ci ath5k_hw_set_gpio_output(ah, ah->rf_kill.gpio); 4462306a36Sopenharmony_ci ath5k_hw_set_gpio(ah, ah->rf_kill.gpio, !ah->rf_kill.polarity); 4562306a36Sopenharmony_ci} 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_cistatic inline void ath5k_rfkill_enable(struct ath5k_hw *ah) 4962306a36Sopenharmony_ci{ 5062306a36Sopenharmony_ci ATH5K_DBG(ah, ATH5K_DEBUG_ANY, "rfkill enable (gpio:%d polarity:%d)\n", 5162306a36Sopenharmony_ci ah->rf_kill.gpio, ah->rf_kill.polarity); 5262306a36Sopenharmony_ci ath5k_hw_set_gpio_output(ah, ah->rf_kill.gpio); 5362306a36Sopenharmony_ci ath5k_hw_set_gpio(ah, ah->rf_kill.gpio, ah->rf_kill.polarity); 5462306a36Sopenharmony_ci} 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_cistatic inline void ath5k_rfkill_set_intr(struct ath5k_hw *ah, bool enable) 5762306a36Sopenharmony_ci{ 5862306a36Sopenharmony_ci u32 curval; 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci ath5k_hw_set_gpio_input(ah, ah->rf_kill.gpio); 6162306a36Sopenharmony_ci curval = ath5k_hw_get_gpio(ah, ah->rf_kill.gpio); 6262306a36Sopenharmony_ci ath5k_hw_set_gpio_intr(ah, ah->rf_kill.gpio, enable ? 6362306a36Sopenharmony_ci !!curval : !curval); 6462306a36Sopenharmony_ci} 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_cistatic bool 6762306a36Sopenharmony_ciath5k_is_rfkill_set(struct ath5k_hw *ah) 6862306a36Sopenharmony_ci{ 6962306a36Sopenharmony_ci /* configuring GPIO for input for some reason disables rfkill */ 7062306a36Sopenharmony_ci /*ath5k_hw_set_gpio_input(ah, ah->rf_kill.gpio);*/ 7162306a36Sopenharmony_ci return ath5k_hw_get_gpio(ah, ah->rf_kill.gpio) == 7262306a36Sopenharmony_ci ah->rf_kill.polarity; 7362306a36Sopenharmony_ci} 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_cistatic void 7662306a36Sopenharmony_ciath5k_tasklet_rfkill_toggle(struct tasklet_struct *t) 7762306a36Sopenharmony_ci{ 7862306a36Sopenharmony_ci struct ath5k_hw *ah = from_tasklet(ah, t, rf_kill.toggleq); 7962306a36Sopenharmony_ci bool blocked; 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci blocked = ath5k_is_rfkill_set(ah); 8262306a36Sopenharmony_ci wiphy_rfkill_set_hw_state(ah->hw->wiphy, blocked); 8362306a36Sopenharmony_ci} 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_civoid 8762306a36Sopenharmony_ciath5k_rfkill_hw_start(struct ath5k_hw *ah) 8862306a36Sopenharmony_ci{ 8962306a36Sopenharmony_ci /* read rfkill GPIO configuration from EEPROM header */ 9062306a36Sopenharmony_ci ah->rf_kill.gpio = ah->ah_capabilities.cap_eeprom.ee_rfkill_pin; 9162306a36Sopenharmony_ci ah->rf_kill.polarity = ah->ah_capabilities.cap_eeprom.ee_rfkill_pol; 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci tasklet_setup(&ah->rf_kill.toggleq, ath5k_tasklet_rfkill_toggle); 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ci ath5k_rfkill_disable(ah); 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci /* enable interrupt for rfkill switch */ 9862306a36Sopenharmony_ci if (AR5K_EEPROM_HDR_RFKILL(ah->ah_capabilities.cap_eeprom.ee_header)) 9962306a36Sopenharmony_ci ath5k_rfkill_set_intr(ah, true); 10062306a36Sopenharmony_ci} 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_civoid 10462306a36Sopenharmony_ciath5k_rfkill_hw_stop(struct ath5k_hw *ah) 10562306a36Sopenharmony_ci{ 10662306a36Sopenharmony_ci /* disable interrupt for rfkill switch */ 10762306a36Sopenharmony_ci if (AR5K_EEPROM_HDR_RFKILL(ah->ah_capabilities.cap_eeprom.ee_header)) 10862306a36Sopenharmony_ci ath5k_rfkill_set_intr(ah, false); 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci tasklet_kill(&ah->rf_kill.toggleq); 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci /* enable RFKILL when stopping HW so Wifi LED is turned off */ 11362306a36Sopenharmony_ci ath5k_rfkill_enable(ah); 11462306a36Sopenharmony_ci} 11562306a36Sopenharmony_ci 116