forked from Minki/linux
ath9k: Add LED support
Signed-off-by: Vasanthakumar Thiagarajan <vasanth@atheros.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
parent
36aedc903e
commit
c83be6885e
@ -757,14 +757,11 @@ struct ath9k_node_stats {
|
|||||||
|
|
||||||
#define ATH9K_RSSI_EP_MULTIPLIER (1<<7)
|
#define ATH9K_RSSI_EP_MULTIPLIER (1<<7)
|
||||||
|
|
||||||
enum ath9k_gpio_output_mux_type {
|
#define AR_GPIO_OUTPUT_MUX_AS_OUTPUT 0
|
||||||
ATH9K_GPIO_OUTPUT_MUX_AS_OUTPUT,
|
#define AR_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED 1
|
||||||
ATH9K_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED,
|
#define AR_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED 2
|
||||||
ATH9K_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED,
|
#define AR_GPIO_OUTPUT_MUX_AS_MAC_NETWORK_LED 5
|
||||||
ATH9K_GPIO_OUTPUT_MUX_AS_MAC_NETWORK_LED,
|
#define AR_GPIO_OUTPUT_MUX_AS_MAC_POWER_LED 6
|
||||||
ATH9K_GPIO_OUTPUT_MUX_AS_MAC_POWER_LED,
|
|
||||||
ATH9K_GPIO_OUTPUT_MUX_NUM_ENTRIES
|
|
||||||
};
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
ATH9K_RESET_POWER_ON,
|
ATH9K_RESET_POWER_ON,
|
||||||
@ -1008,4 +1005,7 @@ void ath9k_hw_get_channel_centers(struct ath_hal *ah,
|
|||||||
bool ath9k_get_channel_edges(struct ath_hal *ah,
|
bool ath9k_get_channel_edges(struct ath_hal *ah,
|
||||||
u16 flags, u16 *low,
|
u16 flags, u16 *low,
|
||||||
u16 *high);
|
u16 *high);
|
||||||
|
void ath9k_hw_cfg_output(struct ath_hal *ah, u32 gpio,
|
||||||
|
u32 ah_signal_type);
|
||||||
|
void ath9k_hw_set_gpio(struct ath_hal *ah, u32 gpio, u32 value);
|
||||||
#endif
|
#endif
|
||||||
|
@ -39,6 +39,7 @@
|
|||||||
#include <linux/scatterlist.h>
|
#include <linux/scatterlist.h>
|
||||||
#include <asm/page.h>
|
#include <asm/page.h>
|
||||||
#include <net/mac80211.h>
|
#include <net/mac80211.h>
|
||||||
|
#include <linux/leds.h>
|
||||||
|
|
||||||
#include "ath9k.h"
|
#include "ath9k.h"
|
||||||
#include "rc.h"
|
#include "rc.h"
|
||||||
@ -802,6 +803,27 @@ void ath_slow_ant_div(struct ath_antdiv *antdiv,
|
|||||||
struct ath_rx_status *rx_stats);
|
struct ath_rx_status *rx_stats);
|
||||||
void ath_setdefantenna(void *sc, u32 antenna);
|
void ath_setdefantenna(void *sc, u32 antenna);
|
||||||
|
|
||||||
|
/********************/
|
||||||
|
/* LED Control */
|
||||||
|
/********************/
|
||||||
|
|
||||||
|
#define ATH_LED_PIN 1
|
||||||
|
|
||||||
|
enum ath_led_type {
|
||||||
|
ATH_LED_RADIO,
|
||||||
|
ATH_LED_ASSOC,
|
||||||
|
ATH_LED_TX,
|
||||||
|
ATH_LED_RX
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ath_led {
|
||||||
|
struct ath_softc *sc;
|
||||||
|
struct led_classdev led_cdev;
|
||||||
|
enum ath_led_type led_type;
|
||||||
|
char name[32];
|
||||||
|
bool registered;
|
||||||
|
};
|
||||||
|
|
||||||
/********************/
|
/********************/
|
||||||
/* Main driver core */
|
/* Main driver core */
|
||||||
/********************/
|
/********************/
|
||||||
@ -884,6 +906,7 @@ struct ath_ht_info {
|
|||||||
#define SC_OP_PREAMBLE_SHORT BIT(7)
|
#define SC_OP_PREAMBLE_SHORT BIT(7)
|
||||||
#define SC_OP_PROTECT_ENABLE BIT(8)
|
#define SC_OP_PROTECT_ENABLE BIT(8)
|
||||||
#define SC_OP_RXFLUSH BIT(9)
|
#define SC_OP_RXFLUSH BIT(9)
|
||||||
|
#define SC_OP_LED_ASSOCIATED BIT(10)
|
||||||
|
|
||||||
struct ath_softc {
|
struct ath_softc {
|
||||||
struct ieee80211_hw *hw;
|
struct ieee80211_hw *hw;
|
||||||
@ -988,6 +1011,12 @@ struct ath_softc {
|
|||||||
spinlock_t sc_txbuflock;
|
spinlock_t sc_txbuflock;
|
||||||
spinlock_t sc_resetlock;
|
spinlock_t sc_resetlock;
|
||||||
spinlock_t node_lock;
|
spinlock_t node_lock;
|
||||||
|
|
||||||
|
/* LEDs */
|
||||||
|
struct ath_led radio_led;
|
||||||
|
struct ath_led assoc_led;
|
||||||
|
struct ath_led tx_led;
|
||||||
|
struct ath_led rx_led;
|
||||||
};
|
};
|
||||||
|
|
||||||
int ath_init(u16 devid, struct ath_softc *sc);
|
int ath_init(u16 devid, struct ath_softc *sc);
|
||||||
|
@ -2800,32 +2800,11 @@ static void ath9k_hw_gpio_cfg_output_mux(struct ath_hal *ah,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ath9k_hw_cfg_output(struct ath_hal *ah, u32 gpio,
|
void ath9k_hw_cfg_output(struct ath_hal *ah, u32 gpio,
|
||||||
enum ath9k_gpio_output_mux_type
|
u32 ah_signal_type)
|
||||||
halSignalType)
|
|
||||||
{
|
{
|
||||||
u32 ah_signal_type;
|
|
||||||
u32 gpio_shift;
|
u32 gpio_shift;
|
||||||
|
|
||||||
static u32 MuxSignalConversionTable[] = {
|
|
||||||
|
|
||||||
AR_GPIO_OUTPUT_MUX_AS_OUTPUT,
|
|
||||||
|
|
||||||
AR_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED,
|
|
||||||
|
|
||||||
AR_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED,
|
|
||||||
|
|
||||||
AR_GPIO_OUTPUT_MUX_AS_MAC_NETWORK_LED,
|
|
||||||
|
|
||||||
AR_GPIO_OUTPUT_MUX_AS_MAC_POWER_LED,
|
|
||||||
};
|
|
||||||
|
|
||||||
if ((halSignalType >= 0)
|
|
||||||
&& (halSignalType < ARRAY_SIZE(MuxSignalConversionTable)))
|
|
||||||
ah_signal_type = MuxSignalConversionTable[halSignalType];
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
|
|
||||||
ath9k_hw_gpio_cfg_output_mux(ah, gpio, ah_signal_type);
|
ath9k_hw_gpio_cfg_output_mux(ah, gpio, ah_signal_type);
|
||||||
|
|
||||||
gpio_shift = 2 * gpio;
|
gpio_shift = 2 * gpio;
|
||||||
@ -2834,16 +2813,12 @@ static bool ath9k_hw_cfg_output(struct ath_hal *ah, u32 gpio,
|
|||||||
AR_GPIO_OE_OUT,
|
AR_GPIO_OE_OUT,
|
||||||
(AR_GPIO_OE_OUT_DRV_ALL << gpio_shift),
|
(AR_GPIO_OE_OUT_DRV_ALL << gpio_shift),
|
||||||
(AR_GPIO_OE_OUT_DRV << gpio_shift));
|
(AR_GPIO_OE_OUT_DRV << gpio_shift));
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ath9k_hw_set_gpio(struct ath_hal *ah, u32 gpio,
|
void ath9k_hw_set_gpio(struct ath_hal *ah, u32 gpio, u32 val)
|
||||||
u32 val)
|
|
||||||
{
|
{
|
||||||
REG_RMW(ah, AR_GPIO_IN_OUT, ((val & 1) << gpio),
|
REG_RMW(ah, AR_GPIO_IN_OUT, ((val & 1) << gpio),
|
||||||
AR_GPIO_BIT(gpio));
|
AR_GPIO_BIT(gpio));
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static u32 ath9k_hw_gpio_get(struct ath_hal *ah, u32 gpio)
|
static u32 ath9k_hw_gpio_get(struct ath_hal *ah, u32 gpio)
|
||||||
@ -5923,7 +5898,7 @@ bool ath9k_hw_reset(struct ath_hal *ah,
|
|||||||
else
|
else
|
||||||
ath9k_hw_set_gpio(ah, 9, 1);
|
ath9k_hw_set_gpio(ah, 9, 1);
|
||||||
}
|
}
|
||||||
ath9k_hw_cfg_output(ah, 9, ATH9K_GPIO_OUTPUT_MUX_AS_OUTPUT);
|
ath9k_hw_cfg_output(ah, 9, AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
ecode = ath9k_hw_process_ini(ah, chan, macmode);
|
ecode = ath9k_hw_process_ini(ah, chan, macmode);
|
||||||
|
@ -1172,12 +1172,130 @@ enum ath9k_ht_macmode ath_cwm_macmode(struct ath_softc *sc)
|
|||||||
return sc->sc_ht_info.tx_chan_width;
|
return sc->sc_ht_info.tx_chan_width;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/********************************/
|
||||||
|
/* LED functions */
|
||||||
|
/********************************/
|
||||||
|
|
||||||
|
static void ath_led_brightness(struct led_classdev *led_cdev,
|
||||||
|
enum led_brightness brightness)
|
||||||
|
{
|
||||||
|
struct ath_led *led = container_of(led_cdev, struct ath_led, led_cdev);
|
||||||
|
struct ath_softc *sc = led->sc;
|
||||||
|
|
||||||
|
switch (brightness) {
|
||||||
|
case LED_OFF:
|
||||||
|
if (led->led_type == ATH_LED_ASSOC ||
|
||||||
|
led->led_type == ATH_LED_RADIO)
|
||||||
|
sc->sc_flags &= ~SC_OP_LED_ASSOCIATED;
|
||||||
|
ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN,
|
||||||
|
(led->led_type == ATH_LED_RADIO) ? 1 :
|
||||||
|
!!(sc->sc_flags & SC_OP_LED_ASSOCIATED));
|
||||||
|
break;
|
||||||
|
case LED_FULL:
|
||||||
|
if (led->led_type == ATH_LED_ASSOC)
|
||||||
|
sc->sc_flags |= SC_OP_LED_ASSOCIATED;
|
||||||
|
ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ath_register_led(struct ath_softc *sc, struct ath_led *led,
|
||||||
|
char *trigger)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
led->sc = sc;
|
||||||
|
led->led_cdev.name = led->name;
|
||||||
|
led->led_cdev.default_trigger = trigger;
|
||||||
|
led->led_cdev.brightness_set = ath_led_brightness;
|
||||||
|
|
||||||
|
ret = led_classdev_register(wiphy_dev(sc->hw->wiphy), &led->led_cdev);
|
||||||
|
if (ret)
|
||||||
|
DPRINTF(sc, ATH_DBG_FATAL,
|
||||||
|
"Failed to register led:%s", led->name);
|
||||||
|
else
|
||||||
|
led->registered = 1;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ath_unregister_led(struct ath_led *led)
|
||||||
|
{
|
||||||
|
if (led->registered) {
|
||||||
|
led_classdev_unregister(&led->led_cdev);
|
||||||
|
led->registered = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ath_deinit_leds(struct ath_softc *sc)
|
||||||
|
{
|
||||||
|
ath_unregister_led(&sc->assoc_led);
|
||||||
|
sc->sc_flags &= ~SC_OP_LED_ASSOCIATED;
|
||||||
|
ath_unregister_led(&sc->tx_led);
|
||||||
|
ath_unregister_led(&sc->rx_led);
|
||||||
|
ath_unregister_led(&sc->radio_led);
|
||||||
|
ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ath_init_leds(struct ath_softc *sc)
|
||||||
|
{
|
||||||
|
char *trigger;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* Configure gpio 1 for output */
|
||||||
|
ath9k_hw_cfg_output(sc->sc_ah, ATH_LED_PIN,
|
||||||
|
AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
|
||||||
|
/* LED off, active low */
|
||||||
|
ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1);
|
||||||
|
|
||||||
|
trigger = ieee80211_get_radio_led_name(sc->hw);
|
||||||
|
snprintf(sc->radio_led.name, sizeof(sc->radio_led.name),
|
||||||
|
"ath9k-%s:radio", wiphy_name(sc->hw->wiphy));
|
||||||
|
ret = ath_register_led(sc, &sc->radio_led, trigger);
|
||||||
|
sc->radio_led.led_type = ATH_LED_RADIO;
|
||||||
|
if (ret)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
trigger = ieee80211_get_assoc_led_name(sc->hw);
|
||||||
|
snprintf(sc->assoc_led.name, sizeof(sc->assoc_led.name),
|
||||||
|
"ath9k-%s:assoc", wiphy_name(sc->hw->wiphy));
|
||||||
|
ret = ath_register_led(sc, &sc->assoc_led, trigger);
|
||||||
|
sc->assoc_led.led_type = ATH_LED_ASSOC;
|
||||||
|
if (ret)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
trigger = ieee80211_get_tx_led_name(sc->hw);
|
||||||
|
snprintf(sc->tx_led.name, sizeof(sc->tx_led.name),
|
||||||
|
"ath9k-%s:tx", wiphy_name(sc->hw->wiphy));
|
||||||
|
ret = ath_register_led(sc, &sc->tx_led, trigger);
|
||||||
|
sc->tx_led.led_type = ATH_LED_TX;
|
||||||
|
if (ret)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
trigger = ieee80211_get_rx_led_name(sc->hw);
|
||||||
|
snprintf(sc->rx_led.name, sizeof(sc->rx_led.name),
|
||||||
|
"ath9k-%s:rx", wiphy_name(sc->hw->wiphy));
|
||||||
|
ret = ath_register_led(sc, &sc->rx_led, trigger);
|
||||||
|
sc->rx_led.led_type = ATH_LED_RX;
|
||||||
|
if (ret)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
ath_deinit_leds(sc);
|
||||||
|
}
|
||||||
|
|
||||||
static int ath_detach(struct ath_softc *sc)
|
static int ath_detach(struct ath_softc *sc)
|
||||||
{
|
{
|
||||||
struct ieee80211_hw *hw = sc->hw;
|
struct ieee80211_hw *hw = sc->hw;
|
||||||
|
|
||||||
DPRINTF(sc, ATH_DBG_CONFIG, "%s: Detach ATH hw\n", __func__);
|
DPRINTF(sc, ATH_DBG_CONFIG, "%s: Detach ATH hw\n", __func__);
|
||||||
|
|
||||||
|
/* Deinit LED control */
|
||||||
|
ath_deinit_leds(sc);
|
||||||
|
|
||||||
/* Unregister hw */
|
/* Unregister hw */
|
||||||
|
|
||||||
ieee80211_unregister_hw(hw);
|
ieee80211_unregister_hw(hw);
|
||||||
@ -1271,18 +1389,21 @@ static int ath_attach(u16 devid,
|
|||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Initialize LED control */
|
||||||
|
ath_init_leds(sc);
|
||||||
|
|
||||||
/* initialize tx/rx engine */
|
/* initialize tx/rx engine */
|
||||||
|
|
||||||
error = ath_tx_init(sc, ATH_TXBUF);
|
error = ath_tx_init(sc, ATH_TXBUF);
|
||||||
if (error != 0)
|
if (error != 0)
|
||||||
goto bad1;
|
goto detach;
|
||||||
|
|
||||||
error = ath_rx_init(sc, ATH_RXBUF);
|
error = ath_rx_init(sc, ATH_RXBUF);
|
||||||
if (error != 0)
|
if (error != 0)
|
||||||
goto bad1;
|
goto detach;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
bad1:
|
detach:
|
||||||
ath_detach(sc);
|
ath_detach(sc);
|
||||||
bad:
|
bad:
|
||||||
return error;
|
return error;
|
||||||
@ -1427,6 +1548,10 @@ static void ath_pci_remove(struct pci_dev *pdev)
|
|||||||
|
|
||||||
static int ath_pci_suspend(struct pci_dev *pdev, pm_message_t state)
|
static int ath_pci_suspend(struct pci_dev *pdev, pm_message_t state)
|
||||||
{
|
{
|
||||||
|
struct ieee80211_hw *hw = pci_get_drvdata(pdev);
|
||||||
|
struct ath_softc *sc = hw->priv;
|
||||||
|
|
||||||
|
ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1);
|
||||||
pci_save_state(pdev);
|
pci_save_state(pdev);
|
||||||
pci_disable_device(pdev);
|
pci_disable_device(pdev);
|
||||||
pci_set_power_state(pdev, 3);
|
pci_set_power_state(pdev, 3);
|
||||||
@ -1436,6 +1561,8 @@ static int ath_pci_suspend(struct pci_dev *pdev, pm_message_t state)
|
|||||||
|
|
||||||
static int ath_pci_resume(struct pci_dev *pdev)
|
static int ath_pci_resume(struct pci_dev *pdev)
|
||||||
{
|
{
|
||||||
|
struct ieee80211_hw *hw = pci_get_drvdata(pdev);
|
||||||
|
struct ath_softc *sc = hw->priv;
|
||||||
u32 val;
|
u32 val;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
@ -1452,6 +1579,11 @@ static int ath_pci_resume(struct pci_dev *pdev)
|
|||||||
if ((val & 0x0000ff00) != 0)
|
if ((val & 0x0000ff00) != 0)
|
||||||
pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
|
pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
|
||||||
|
|
||||||
|
/* Enable LED */
|
||||||
|
ath9k_hw_cfg_output(sc->sc_ah, ATH_LED_PIN,
|
||||||
|
AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
|
||||||
|
ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -899,12 +899,6 @@ enum {
|
|||||||
#define AR_GPIO_OUTPUT_MUX2 0x4064
|
#define AR_GPIO_OUTPUT_MUX2 0x4064
|
||||||
#define AR_GPIO_OUTPUT_MUX3 0x4068
|
#define AR_GPIO_OUTPUT_MUX3 0x4068
|
||||||
|
|
||||||
#define AR_GPIO_OUTPUT_MUX_AS_OUTPUT 0
|
|
||||||
#define AR_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED 1
|
|
||||||
#define AR_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED 2
|
|
||||||
#define AR_GPIO_OUTPUT_MUX_AS_MAC_NETWORK_LED 5
|
|
||||||
#define AR_GPIO_OUTPUT_MUX_AS_MAC_POWER_LED 6
|
|
||||||
|
|
||||||
#define AR_INPUT_STATE 0x406c
|
#define AR_INPUT_STATE 0x406c
|
||||||
|
|
||||||
#define AR_EEPROM_STATUS_DATA 0x407c
|
#define AR_EEPROM_STATUS_DATA 0x407c
|
||||||
|
Loading…
Reference in New Issue
Block a user