Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 150808
b: refs/heads/master
c: e6a3b61
h: refs/heads/master
v: v3
  • Loading branch information
Tobias Doerffel authored and John W. Linville committed Jun 10, 2009
1 parent a39d914 commit b0b29e1
Show file tree
Hide file tree
Showing 8 changed files with 164 additions and 18 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 207ee1621722876bb79828689582bf77fd1be200
refs/heads/master: e6a3b61681dcb963e6465ffbc4330b44824f35e3
8 changes: 8 additions & 0 deletions trunk/drivers/net/wireless/ath/ath5k/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,11 @@ config ATH5K_DEBUG

modprobe ath5k debug=0x00000400

config ATH5K_RFKILL
bool "Atheros 5xxx rfkill support"
depends on ATH5K
default y
---help---
Include support for enabling/disabling WiFi via rfkill switch
with Atheros 5xxx cards

1 change: 1 addition & 0 deletions trunk/drivers/net/wireless/ath/ath5k/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ ath5k-y += attach.o
ath5k-y += base.o
ath5k-y += led.o
ath5k-$(CONFIG_ATH5K_DEBUG) += debug.o
ath5k-$(CONFIG_ATH5K_RFKILL) += rfkill.o
obj-$(CONFIG_ATH5K) += ath5k.o
9 changes: 9 additions & 0 deletions trunk/drivers/net/wireless/ath/ath5k/ath5k.h
Original file line number Diff line number Diff line change
Expand Up @@ -1256,6 +1256,15 @@ extern u32 ath5k_hw_get_gpio(struct ath5k_hw *ah, u32 gpio);
extern int ath5k_hw_set_gpio(struct ath5k_hw *ah, u32 gpio, u32 val);
extern void ath5k_hw_set_gpio_intr(struct ath5k_hw *ah, unsigned int gpio, u32 interrupt_level);

/* rfkill Functions */
#ifdef CONFIG_ATH5K_RFKILL
extern void ath5k_rfkill_hw_start(struct ath5k_hw *ah);
extern void ath5k_rfkill_hw_stop(struct ath5k_hw *ah);
#else
static inline void ath5k_rfkill_hw_start(struct ath5k_hw *ah) {}
static inline void ath5k_rfkill_hw_stop(struct ath5k_hw *ah) {}
#endif

/* Misc functions */
int ath5k_hw_set_capabilities(struct ath5k_hw *ah);
extern int ath5k_hw_get_capability(struct ath5k_hw *ah, enum ath5k_capability_type cap_type, u32 capability, u32 *result);
Expand Down
10 changes: 10 additions & 0 deletions trunk/drivers/net/wireless/ath/ath5k/base.c
Original file line number Diff line number Diff line change
Expand Up @@ -2360,6 +2360,8 @@ ath5k_init(struct ath5k_softc *sc)
if (ret)
goto done;

ath5k_rfkill_hw_start(ah);

/*
* Reset the key cache since some parts do not reset the
* contents on initial power up or resume from suspend.
Expand Down Expand Up @@ -2468,6 +2470,8 @@ ath5k_stop_hw(struct ath5k_softc *sc)
tasklet_kill(&sc->restq);
tasklet_kill(&sc->beacontq);

ath5k_rfkill_hw_stop(sc->ah);

return ret;
}

Expand Down Expand Up @@ -2526,6 +2530,12 @@ ath5k_intr(int irq, void *dev_id)
*/
ath5k_hw_update_mib_counters(ah, &sc->ll_stats);
}
#ifdef CONFIG_ATH5K_RFKILL
if (status & AR5K_INT_GPIO)
{
tasklet_schedule(&sc->rf_kill.toggleq);
}
#endif
}
} while (ath5k_hw_is_intr_pending(ah) && --counter > 0);

Expand Down
14 changes: 14 additions & 0 deletions trunk/drivers/net/wireless/ath/ath5k/base.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
#include <linux/wireless.h>
#include <linux/if_ether.h>
#include <linux/leds.h>
#include <linux/rfkill.h>

#include "ath5k.h"
#include "debug.h"
Expand Down Expand Up @@ -91,6 +92,15 @@ struct ath5k_led
struct led_classdev led_dev; /* led classdev */
};

/* Rfkill */
struct ath5k_rfkill {
/* GPIO PIN for rfkill */
u16 gpio;
/* polarity of rfkill GPIO PIN */
bool polarity;
/* RFKILL toggle tasklet */
struct tasklet_struct toggleq;
};

#if CHAN_DEBUG
#define ATH_CHAN_MAX (26+26+26+200+200)
Expand Down Expand Up @@ -167,6 +177,10 @@ struct ath5k_softc {
struct tasklet_struct txtq; /* tx intr tasklet */
struct ath5k_led tx_led; /* tx led */

#ifdef CONFIG_ATH5K_RFKILL
struct ath5k_rfkill rf_kill;
#endif

spinlock_t block; /* protects beacon */
struct tasklet_struct beacontq; /* beacon intr tasklet */
struct ath5k_buf *bbuf; /* beacon buffer */
Expand Down
17 changes: 0 additions & 17 deletions trunk/drivers/net/wireless/ath/ath5k/reset.c
Original file line number Diff line number Diff line change
Expand Up @@ -1304,23 +1304,6 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
if (ah->ah_version != AR5K_AR5210)
ath5k_hw_set_imr(ah, ah->ah_imr);

/*
* Setup RFKill interrupt if rfkill flag is set on eeprom.
* TODO: Use gpio pin and polarity infos from eeprom
* TODO: Handle this in ath5k_intr because it'll result
* a nasty interrupt storm.
*/
#if 0
if (AR5K_EEPROM_HDR_RFKILL(ah->ah_capabilities.cap_eeprom.ee_header)) {
ath5k_hw_set_gpio_input(ah, 0);
ah->ah_gpio[0] = ath5k_hw_get_gpio(ah, 0);
if (ah->ah_gpio[0] == 0)
ath5k_hw_set_gpio_intr(ah, 0, 1);
else
ath5k_hw_set_gpio_intr(ah, 0, 0);
}
#endif

/* Enable 32KHz clock function for AR5212+ chips
* Set clocks to 32KHz operation and use an
* external 32KHz crystal when sleeping if one
Expand Down
121 changes: 121 additions & 0 deletions trunk/drivers/net/wireless/ath/ath5k/rfkill.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
/*
* RFKILL support for ath5k
*
* Copyright (c) 2009 Tobias Doerffel <tobias.doerffel@gmail.com>
*
* 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);
}

0 comments on commit b0b29e1

Please sign in to comment.