summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/drivers/net/ath5k/ath5k.c9
-rw-r--r--src/drivers/net/ath5k/ath5k.h4
-rw-r--r--src/drivers/net/ath5k/ath5k_eeprom.c11
-rw-r--r--src/drivers/net/ath5k/ath5k_initvals.c4
-rw-r--r--src/drivers/net/ath5k/ath5k_pcu.c2
-rw-r--r--src/drivers/net/ath5k/ath5k_rfkill.c107
-rw-r--r--src/drivers/net/ath5k/base.h5
-rw-r--r--src/drivers/net/ath5k/eeprom.h10
8 files changed, 147 insertions, 5 deletions
diff --git a/src/drivers/net/ath5k/ath5k.c b/src/drivers/net/ath5k/ath5k.c
index 5101a54f..86ec7354 100644
--- a/src/drivers/net/ath5k/ath5k.c
+++ b/src/drivers/net/ath5k/ath5k.c
@@ -1195,11 +1195,12 @@ ath5k_handle_rx(struct ath5k_softc *sc)
if (rs.rs_status) {
if (rs.rs_status & AR5K_RXERR_PHY) {
- DBG("ath5k: rx PHY error\n");
+ /* These are uncommon, and may indicate a real problem. */
+ net80211_rx_err(sc->dev, NULL, EIO);
goto next;
}
if (rs.rs_status & AR5K_RXERR_CRC) {
- net80211_rx_err(sc->dev, NULL, EIO);
+ /* These occur *all the time*. */
goto next;
}
if (rs.rs_status & AR5K_RXERR_DECRYPT) {
@@ -1358,6 +1359,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.
@@ -1405,6 +1408,8 @@ ath5k_stop_hw(struct ath5k_softc *sc)
} else
sc->rxlink = NULL;
+ ath5k_rfkill_hw_stop(sc->ah);
+
return 0;
}
diff --git a/src/drivers/net/ath5k/ath5k.h b/src/drivers/net/ath5k/ath5k.h
index c79fbec0..e54433d7 100644
--- a/src/drivers/net/ath5k/ath5k.h
+++ b/src/drivers/net/ath5k/ath5k.h
@@ -1153,6 +1153,10 @@ 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 */
+extern void ath5k_rfkill_hw_start(struct ath5k_hw *ah);
+extern void ath5k_rfkill_hw_stop(struct ath5k_hw *ah);
+
/* 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);
diff --git a/src/drivers/net/ath5k/ath5k_eeprom.c b/src/drivers/net/ath5k/ath5k_eeprom.c
index 592714dd..0f62c4c7 100644
--- a/src/drivers/net/ath5k/ath5k_eeprom.c
+++ b/src/drivers/net/ath5k/ath5k_eeprom.c
@@ -146,6 +146,17 @@ ath5k_eeprom_init_header(struct ath5k_hw *ah)
ee->ee_db[AR5K_EEPROM_MODE_11G][0] = (val >> 3) & 0x7;
}
+ AR5K_EEPROM_READ(AR5K_EEPROM_IS_HB63, val);
+
+ if ((ah->ah_mac_version == (AR5K_SREV_AR2425 >> 4)) && val)
+ ee->ee_is_hb63 = 1;
+ else
+ ee->ee_is_hb63 = 0;
+
+ AR5K_EEPROM_READ(AR5K_EEPROM_RFKILL, val);
+ ee->ee_rfkill_pin = (u8) AR5K_REG_MS(val, AR5K_EEPROM_RFKILL_GPIO_SEL);
+ ee->ee_rfkill_pol = val & AR5K_EEPROM_RFKILL_POLARITY ? 1 : 0;
+
return 0;
}
diff --git a/src/drivers/net/ath5k/ath5k_initvals.c b/src/drivers/net/ath5k/ath5k_initvals.c
index 5911be89..92011c83 100644
--- a/src/drivers/net/ath5k/ath5k_initvals.c
+++ b/src/drivers/net/ath5k/ath5k_initvals.c
@@ -723,7 +723,7 @@ static const struct ath5k_ini_mode ar5212_ini_mode_start[] = {
{ AR5K_PHY_SETTLING,
{ 0x1372161c, 0x13721c25, 0x13721722, 0x137216a2, 0x13721c25 } },
{ AR5K_PHY_AGCCTL,
- { 0x00009d10, 0x00009d10, 0x00009d18, 0x00009d18, 0x00009d18 } },
+ { 0x00009d10, 0x00009d10, 0x00009d18, 0x00009d18, 0x00009d10 } },
{ AR5K_PHY_NF,
{ 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 } },
{ AR5K_PHY_WEAK_OFDM_HIGH_THR,
@@ -804,7 +804,7 @@ static const struct ath5k_ini_mode rf5112_ini_mode_end[] = {
{ AR5K_PHY_DESIRED_SIZE,
{ 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0 } },
{ AR5K_PHY_SIG,
- { 0x7e800d2e, 0x7e800d2e, 0x7ee80d2e, 0x7ee80d2e, 0x7ee80d2e } },
+ { 0x7e800d2e, 0x7e800d2e, 0x7ee80d2e, 0x7ee80d2e, 0x7e800d2e } },
{ AR5K_PHY_AGCCOARSE,
{ 0x3137665e, 0x3137665e, 0x3137665e, 0x3137665e, 0x3137665e } },
{ AR5K_PHY_WEAK_OFDM_LOW_THR,
diff --git a/src/drivers/net/ath5k/ath5k_pcu.c b/src/drivers/net/ath5k/ath5k_pcu.c
index 1e90a94e..d3e144c4 100644
--- a/src/drivers/net/ath5k/ath5k_pcu.c
+++ b/src/drivers/net/ath5k/ath5k_pcu.c
@@ -520,7 +520,7 @@ int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry)
* Note2: Windows driver (ndiswrapper) sets this to
* 0x00000714 instead of 0x00000007
*/
- if (ah->ah_version > AR5K_AR5211) {
+ if (ah->ah_version >= AR5K_AR5211) {
ath5k_hw_reg_write(ah, AR5K_KEYTABLE_TYPE_NULL,
AR5K_KEYTABLE_TYPE(entry));
diff --git a/src/drivers/net/ath5k/ath5k_rfkill.c b/src/drivers/net/ath5k/ath5k_rfkill.c
new file mode 100644
index 00000000..9d0a2ff1
--- /dev/null
+++ b/src/drivers/net/ath5k/ath5k_rfkill.c
@@ -0,0 +1,107 @@
+/*
+ * RFKILL support for ath5k
+ *
+ * Copyright (c) 2009 Tobias Doerffel <tobias.doerffel@gmail.com>
+ * Lightly modified for gPXE, Sep 2008 by Joshua Oreman <oremanj@rwcr.net>
+ *
+ * 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.
+ */
+
+FILE_LICENCE ( MIT );
+
+#include "base.h"
+
+
+static inline void ath5k_rfkill_disable(struct ath5k_softc *sc)
+{
+ DBG("ath5k: 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)
+{
+ DBG("ath5k: 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, int enable)
+{
+ struct ath5k_hw *ah = sc->ah;
+ u32 curval;
+
+ ath5k_hw_set_gpio_input(ah, sc->rf_kill.gpio);
+ curval = ath5k_hw_get_gpio(ah, sc->rf_kill.gpio);
+ ath5k_hw_set_gpio_intr(ah, sc->rf_kill.gpio, enable ?
+ !!curval : !curval);
+}
+
+static int __unused
+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);
+}
+
+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;
+
+ 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, 1);
+}
+
+
+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, 0);
+
+ /* enable RFKILL when stopping HW so Wifi LED is turned off */
+ ath5k_rfkill_enable(sc);
+}
diff --git a/src/drivers/net/ath5k/base.h b/src/drivers/net/ath5k/base.h
index 45dad073..870b0ed4 100644
--- a/src/drivers/net/ath5k/base.h
+++ b/src/drivers/net/ath5k/base.h
@@ -123,6 +123,11 @@ struct ath5k_softc {
unsigned int txbuf_len; /* buf count in txbuf list */
struct ath5k_txq txq; /* tx queue */
+ struct {
+ u16 gpio;
+ unsigned polarity;
+ } rf_kill;
+
int last_calib_ticks;
int power_level; /* Requested tx power in dbm */
diff --git a/src/drivers/net/ath5k/eeprom.h b/src/drivers/net/ath5k/eeprom.h
index 4d6250af..da454339 100644
--- a/src/drivers/net/ath5k/eeprom.h
+++ b/src/drivers/net/ath5k/eeprom.h
@@ -26,6 +26,13 @@
#define AR5K_EEPROM_MAGIC_5210 0x0000145a /* 5210 */
#define AR5K_EEPROM_IS_HB63 0x000b /* Talon detect */
+
+#define AR5K_EEPROM_RFKILL 0x0f
+#define AR5K_EEPROM_RFKILL_GPIO_SEL 0x0000001c
+#define AR5K_EEPROM_RFKILL_GPIO_SEL_S 2
+#define AR5K_EEPROM_RFKILL_POLARITY 0x00000002
+#define AR5K_EEPROM_RFKILL_POLARITY_S 1
+
#define AR5K_EEPROM_REG_DOMAIN 0x00bf /* EEPROM regdom */
#define AR5K_EEPROM_CHECKSUM 0x00c0 /* EEPROM checksum */
#define AR5K_EEPROM_INFO_BASE 0x00c0 /* EEPROM header */
@@ -369,6 +376,9 @@ struct ath5k_eeprom_info {
u16 ee_version;
u16 ee_header;
u16 ee_ant_gain;
+ u8 ee_rfkill_pin;
+ int ee_rfkill_pol;
+ int ee_is_hb63;
u16 ee_misc0;
u16 ee_misc1;
u16 ee_misc2;