diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath5k/rfkill.c')
-rw-r--r-- | drivers/net/wireless/ath/ath5k/rfkill.c | 121 |
1 files changed, 121 insertions, 0 deletions
diff --git a/drivers/net/wireless/ath/ath5k/rfkill.c b/drivers/net/wireless/ath/ath5k/rfkill.c new file mode 100644 index 000000000000..41a877b73fce --- /dev/null +++ b/drivers/net/wireless/ath/ath5k/rfkill.c | |||
@@ -0,0 +1,121 @@ | |||
1 | /* | ||
2 | * RFKILL support for ath5k | ||
3 | * | ||
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 without | ||
9 | * modification, are permitted provided that the following conditions | ||
10 | * are met: | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer, | ||
13 | * without modification. | ||
14 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | ||
15 | * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any | ||
16 | * redistribution must be conditioned upon including a substantially | ||
17 | * similar Disclaimer requirement for further binary redistribution. | ||
18 | * 3. Neither the names of the above-listed copyright holders nor the names | ||
19 | * of any contributors may be used to endorse or promote products derived | ||
20 | * from this software without specific prior written permission. | ||
21 | * | ||
22 | * NO WARRANTY | ||
23 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
24 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
25 | * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY | ||
26 | * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL | ||
27 | * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, | ||
28 | * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
29 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
30 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER | ||
31 | * 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 OF | ||
33 | * THE POSSIBILITY OF SUCH DAMAGES. | ||
34 | */ | ||
35 | |||
36 | #include "base.h" | ||
37 | |||
38 | |||
39 | static inline void ath5k_rfkill_disable(struct ath5k_softc *sc) | ||
40 | { | ||
41 | ATH5K_DBG(sc, ATH5K_DEBUG_ANY, "rfkill disable (gpio:%d polarity:%d)\n", | ||
42 | sc->rf_kill.gpio, sc->rf_kill.polarity); | ||
43 | ath5k_hw_set_gpio_output(sc->ah, sc->rf_kill.gpio); | ||
44 | ath5k_hw_set_gpio(sc->ah, sc->rf_kill.gpio, !sc->rf_kill.polarity); | ||
45 | } | ||
46 | |||
47 | |||
48 | static inline void ath5k_rfkill_enable(struct ath5k_softc *sc) | ||
49 | { | ||
50 | ATH5K_DBG(sc, ATH5K_DEBUG_ANY, "rfkill enable (gpio:%d polarity:%d)\n", | ||
51 | sc->rf_kill.gpio, sc->rf_kill.polarity); | ||
52 | ath5k_hw_set_gpio_output(sc->ah, sc->rf_kill.gpio); | ||
53 | ath5k_hw_set_gpio(sc->ah, sc->rf_kill.gpio, sc->rf_kill.polarity); | ||
54 | } | ||
55 | |||
56 | static inline void ath5k_rfkill_set_intr(struct ath5k_softc *sc, bool enable) | ||
57 | { | ||
58 | struct ath5k_hw *ah = sc->ah; | ||
59 | u32 curval; | ||
60 | |||
61 | ath5k_hw_set_gpio_input(ah, sc->rf_kill.gpio); | ||
62 | curval = ath5k_hw_get_gpio(ah, sc->rf_kill.gpio); | ||
63 | ath5k_hw_set_gpio_intr(ah, sc->rf_kill.gpio, enable ? | ||
64 | !!curval : !curval); | ||
65 | } | ||
66 | |||
67 | static bool | ||
68 | ath5k_is_rfkill_set(struct ath5k_softc *sc) | ||
69 | { | ||
70 | /* configuring GPIO for input for some reason disables rfkill */ | ||
71 | /*ath5k_hw_set_gpio_input(sc->ah, sc->rf_kill.gpio);*/ | ||
72 | return ath5k_hw_get_gpio(sc->ah, sc->rf_kill.gpio) == | ||
73 | sc->rf_kill.polarity; | ||
74 | } | ||
75 | |||
76 | static void | ||
77 | ath5k_tasklet_rfkill_toggle(unsigned long data) | ||
78 | { | ||
79 | struct ath5k_softc *sc = (void *)data; | ||
80 | bool blocked; | ||
81 | |||
82 | blocked = ath5k_is_rfkill_set(sc); | ||
83 | wiphy_rfkill_set_hw_state(sc->hw->wiphy, blocked); | ||
84 | } | ||
85 | |||
86 | |||
87 | void | ||
88 | ath5k_rfkill_hw_start(struct ath5k_hw *ah) | ||
89 | { | ||
90 | struct ath5k_softc *sc = ah->ah_sc; | ||
91 | |||
92 | /* read rfkill GPIO configuration from EEPROM header */ | ||
93 | sc->rf_kill.gpio = ah->ah_capabilities.cap_eeprom.ee_rfkill_pin; | ||
94 | sc->rf_kill.polarity = ah->ah_capabilities.cap_eeprom.ee_rfkill_pol; | ||
95 | |||
96 | tasklet_init(&sc->rf_kill.toggleq, ath5k_tasklet_rfkill_toggle, | ||
97 | (unsigned long)sc); | ||
98 | |||
99 | ath5k_rfkill_disable(sc); | ||
100 | |||
101 | /* enable interrupt for rfkill switch */ | ||
102 | if (AR5K_EEPROM_HDR_RFKILL(ah->ah_capabilities.cap_eeprom.ee_header)) | ||
103 | ath5k_rfkill_set_intr(sc, true); | ||
104 | } | ||
105 | |||
106 | |||
107 | void | ||
108 | ath5k_rfkill_hw_stop(struct ath5k_hw *ah) | ||
109 | { | ||
110 | struct ath5k_softc *sc = ah->ah_sc; | ||
111 | |||
112 | /* disable interrupt for rfkill switch */ | ||
113 | if (AR5K_EEPROM_HDR_RFKILL(ah->ah_capabilities.cap_eeprom.ee_header)) | ||
114 | ath5k_rfkill_set_intr(sc, false); | ||
115 | |||
116 | tasklet_kill(&sc->rf_kill.toggleq); | ||
117 | |||
118 | /* enable RFKILL when stopping HW so Wifi LED is turned off */ | ||
119 | ath5k_rfkill_enable(sc); | ||
120 | } | ||
121 | |||