18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * RFKILL support for ath5k
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * Copyright (c) 2009 Tobias Doerffel <tobias.doerffel@gmail.com>
58c2ecf20Sopenharmony_ci *
68c2ecf20Sopenharmony_ci * All rights reserved.
78c2ecf20Sopenharmony_ci *
88c2ecf20Sopenharmony_ci * Redistribution and use in source and binary forms, with or without
98c2ecf20Sopenharmony_ci * modification, are permitted provided that the following conditions
108c2ecf20Sopenharmony_ci * are met:
118c2ecf20Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright
128c2ecf20Sopenharmony_ci *    notice, this list of conditions and the following disclaimer,
138c2ecf20Sopenharmony_ci *    without modification.
148c2ecf20Sopenharmony_ci * 2. Redistributions in binary form must reproduce at minimum a disclaimer
158c2ecf20Sopenharmony_ci *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
168c2ecf20Sopenharmony_ci *    redistribution must be conditioned upon including a substantially
178c2ecf20Sopenharmony_ci *    similar Disclaimer requirement for further binary redistribution.
188c2ecf20Sopenharmony_ci * 3. Neither the names of the above-listed copyright holders nor the names
198c2ecf20Sopenharmony_ci *    of any contributors may be used to endorse or promote products derived
208c2ecf20Sopenharmony_ci *    from this software without specific prior written permission.
218c2ecf20Sopenharmony_ci *
228c2ecf20Sopenharmony_ci * NO WARRANTY
238c2ecf20Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
248c2ecf20Sopenharmony_ci * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
258c2ecf20Sopenharmony_ci * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
268c2ecf20Sopenharmony_ci * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
278c2ecf20Sopenharmony_ci * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
288c2ecf20Sopenharmony_ci * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
298c2ecf20Sopenharmony_ci * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
308c2ecf20Sopenharmony_ci * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
318c2ecf20Sopenharmony_ci * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
328c2ecf20Sopenharmony_ci * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
338c2ecf20Sopenharmony_ci * THE POSSIBILITY OF SUCH DAMAGES.
348c2ecf20Sopenharmony_ci */
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci#include "ath5k.h"
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_cistatic inline void ath5k_rfkill_disable(struct ath5k_hw *ah)
408c2ecf20Sopenharmony_ci{
418c2ecf20Sopenharmony_ci	ATH5K_DBG(ah, ATH5K_DEBUG_ANY, "rfkill disable (gpio:%d polarity:%d)\n",
428c2ecf20Sopenharmony_ci		ah->rf_kill.gpio, ah->rf_kill.polarity);
438c2ecf20Sopenharmony_ci	ath5k_hw_set_gpio_output(ah, ah->rf_kill.gpio);
448c2ecf20Sopenharmony_ci	ath5k_hw_set_gpio(ah, ah->rf_kill.gpio, !ah->rf_kill.polarity);
458c2ecf20Sopenharmony_ci}
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_cistatic inline void ath5k_rfkill_enable(struct ath5k_hw *ah)
498c2ecf20Sopenharmony_ci{
508c2ecf20Sopenharmony_ci	ATH5K_DBG(ah, ATH5K_DEBUG_ANY, "rfkill enable (gpio:%d polarity:%d)\n",
518c2ecf20Sopenharmony_ci		ah->rf_kill.gpio, ah->rf_kill.polarity);
528c2ecf20Sopenharmony_ci	ath5k_hw_set_gpio_output(ah, ah->rf_kill.gpio);
538c2ecf20Sopenharmony_ci	ath5k_hw_set_gpio(ah, ah->rf_kill.gpio, ah->rf_kill.polarity);
548c2ecf20Sopenharmony_ci}
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_cistatic inline void ath5k_rfkill_set_intr(struct ath5k_hw *ah, bool enable)
578c2ecf20Sopenharmony_ci{
588c2ecf20Sopenharmony_ci	u32 curval;
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_ci	ath5k_hw_set_gpio_input(ah, ah->rf_kill.gpio);
618c2ecf20Sopenharmony_ci	curval = ath5k_hw_get_gpio(ah, ah->rf_kill.gpio);
628c2ecf20Sopenharmony_ci	ath5k_hw_set_gpio_intr(ah, ah->rf_kill.gpio, enable ?
638c2ecf20Sopenharmony_ci					!!curval : !curval);
648c2ecf20Sopenharmony_ci}
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_cistatic bool
678c2ecf20Sopenharmony_ciath5k_is_rfkill_set(struct ath5k_hw *ah)
688c2ecf20Sopenharmony_ci{
698c2ecf20Sopenharmony_ci	/* configuring GPIO for input for some reason disables rfkill */
708c2ecf20Sopenharmony_ci	/*ath5k_hw_set_gpio_input(ah, ah->rf_kill.gpio);*/
718c2ecf20Sopenharmony_ci	return ath5k_hw_get_gpio(ah, ah->rf_kill.gpio) ==
728c2ecf20Sopenharmony_ci							ah->rf_kill.polarity;
738c2ecf20Sopenharmony_ci}
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_cistatic void
768c2ecf20Sopenharmony_ciath5k_tasklet_rfkill_toggle(struct tasklet_struct *t)
778c2ecf20Sopenharmony_ci{
788c2ecf20Sopenharmony_ci	struct ath5k_hw *ah = from_tasklet(ah, t, rf_kill.toggleq);
798c2ecf20Sopenharmony_ci	bool blocked;
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_ci	blocked = ath5k_is_rfkill_set(ah);
828c2ecf20Sopenharmony_ci	wiphy_rfkill_set_hw_state(ah->hw->wiphy, blocked);
838c2ecf20Sopenharmony_ci}
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_civoid
878c2ecf20Sopenharmony_ciath5k_rfkill_hw_start(struct ath5k_hw *ah)
888c2ecf20Sopenharmony_ci{
898c2ecf20Sopenharmony_ci	/* read rfkill GPIO configuration from EEPROM header */
908c2ecf20Sopenharmony_ci	ah->rf_kill.gpio = ah->ah_capabilities.cap_eeprom.ee_rfkill_pin;
918c2ecf20Sopenharmony_ci	ah->rf_kill.polarity = ah->ah_capabilities.cap_eeprom.ee_rfkill_pol;
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_ci	tasklet_setup(&ah->rf_kill.toggleq, ath5k_tasklet_rfkill_toggle);
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_ci	ath5k_rfkill_disable(ah);
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_ci	/* enable interrupt for rfkill switch */
988c2ecf20Sopenharmony_ci	if (AR5K_EEPROM_HDR_RFKILL(ah->ah_capabilities.cap_eeprom.ee_header))
998c2ecf20Sopenharmony_ci		ath5k_rfkill_set_intr(ah, true);
1008c2ecf20Sopenharmony_ci}
1018c2ecf20Sopenharmony_ci
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_civoid
1048c2ecf20Sopenharmony_ciath5k_rfkill_hw_stop(struct ath5k_hw *ah)
1058c2ecf20Sopenharmony_ci{
1068c2ecf20Sopenharmony_ci	/* disable interrupt for rfkill switch */
1078c2ecf20Sopenharmony_ci	if (AR5K_EEPROM_HDR_RFKILL(ah->ah_capabilities.cap_eeprom.ee_header))
1088c2ecf20Sopenharmony_ci		ath5k_rfkill_set_intr(ah, false);
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_ci	tasklet_kill(&ah->rf_kill.toggleq);
1118c2ecf20Sopenharmony_ci
1128c2ecf20Sopenharmony_ci	/* enable RFKILL when stopping HW so Wifi LED is turned off */
1138c2ecf20Sopenharmony_ci	ath5k_rfkill_enable(ah);
1148c2ecf20Sopenharmony_ci}
1158c2ecf20Sopenharmony_ci
116