mac80211: backport ath9k GPIO support
This commit is contained in:
parent
59d4b3056f
commit
b56b6640e6
@ -0,0 +1,121 @@
|
|||||||
|
From: Matthias Schiffer <mschiffer@universe-factory.net>
|
||||||
|
Date: Sun, 29 May 2016 12:56:43 +0200
|
||||||
|
Subject: mac80211: ath9k: enable platform WLAN LED name
|
||||||
|
|
||||||
|
Enable platform-supplied WLAN LED name for ath9k device.
|
||||||
|
|
||||||
|
Signed-off-by: Michal Cieslakiewicz <michal.cieslakiewicz@wp.pl>
|
||||||
|
Acked-by: Hartmut Knaack <knaack.h@gmx.de>
|
||||||
|
|
||||||
|
Backport of r48879
|
||||||
|
|
||||||
|
diff --git a/package/kernel/mac80211/patches/546-ath9k_platform_led_name.patch b/package/kernel/mac80211/patches/546-ath9k_platform_led_name.patch
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..8d2d899
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/package/kernel/mac80211/patches/546-ath9k_platform_led_name.patch
|
||||||
|
@@ -0,0 +1,48 @@
|
||||||
|
+From: Michal Cieslakiewicz <michal.cieslakiewicz@wp.pl>
|
||||||
|
+Date: Sun, 31 Jan 2016 20:45:57 +0100
|
||||||
|
+Subject: [PATCH v4 1/8] mac80211: ath9k: enable platform WLAN LED name
|
||||||
|
+
|
||||||
|
+Enable platform-supplied WLAN LED name for ath9k device. It replaces generic
|
||||||
|
+'ath9k-phy*' label with string set during platform initialization.
|
||||||
|
+
|
||||||
|
+Signed-off-by: Michal Cieslakiewicz <michal.cieslakiewicz@wp.pl>
|
||||||
|
+---
|
||||||
|
+ drivers/net/wireless/ath/ath9k/gpio.c | 10 +++++++---
|
||||||
|
+ include/linux/ath9k_platform.h | 1 +
|
||||||
|
+ 2 files changed, 8 insertions(+), 3 deletions(-)
|
||||||
|
+
|
||||||
|
+--- a/drivers/net/wireless/ath/ath9k/gpio.c
|
||||||
|
++++ b/drivers/net/wireless/ath/ath9k/gpio.c
|
||||||
|
+@@ -132,15 +132,19 @@ void ath_init_leds(struct ath_softc *sc)
|
||||||
|
+ if (AR_SREV_9100(sc->sc_ah))
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+- snprintf(led_name, sizeof(led_name), "ath9k-%s",
|
||||||
|
+- wiphy_name(sc->hw->wiphy));
|
||||||
|
++ if (pdata && pdata->led_name)
|
||||||
|
++ strncpy(led_name, pdata->led_name, sizeof(led_name));
|
||||||
|
++ else
|
||||||
|
++ snprintf(led_name, sizeof(led_name), "ath9k-%s",
|
||||||
|
++ wiphy_name(sc->hw->wiphy));
|
||||||
|
+
|
||||||
|
+ if (ath9k_led_blink)
|
||||||
|
+ trigger = sc->led_default_trigger;
|
||||||
|
+ else
|
||||||
|
+ trigger = ieee80211_get_radio_led_name(sc->hw);
|
||||||
|
+
|
||||||
|
+- ath_create_gpio_led(sc, sc->sc_ah->led_pin, led_name, trigger, !sc->sc_ah->config.led_active_high);
|
||||||
|
++ ath_create_gpio_led(sc, sc->sc_ah->led_pin, led_name, trigger,
|
||||||
|
++ !sc->sc_ah->config.led_active_high);
|
||||||
|
+
|
||||||
|
+ if (!pdata)
|
||||||
|
+ return;
|
||||||
|
+--- a/include/linux/ath9k_platform.h
|
||||||
|
++++ b/include/linux/ath9k_platform.h
|
||||||
|
+@@ -45,6 +45,7 @@ struct ath9k_platform_data {
|
||||||
|
+
|
||||||
|
+ int num_leds;
|
||||||
|
+ const struct gpio_led *leds;
|
||||||
|
++ const char *led_name;
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+ #endif /* _LINUX_ATH9K_PLATFORM_H */
|
||||||
|
diff --git a/target/linux/ar71xx/files/arch/mips/ath79/dev-ap9x-pci.c b/target/linux/ar71xx/files/arch/mips/ath79/dev-ap9x-pci.c
|
||||||
|
index d382453..bf80d4d 100644
|
||||||
|
--- a/target/linux/ar71xx/files/arch/mips/ath79/dev-ap9x-pci.c
|
||||||
|
+++ b/target/linux/ar71xx/files/arch/mips/ath79/dev-ap9x-pci.c
|
||||||
|
@@ -39,6 +39,18 @@ __init void ap9x_pci_setup_wmac_led_pin(unsigned wmac, int pin)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+__init void ap9x_pci_setup_wmac_led_name(unsigned wmac, const char *led_name)
|
||||||
|
+{
|
||||||
|
+ switch (wmac) {
|
||||||
|
+ case 0:
|
||||||
|
+ ap9x_wmac0_data.led_name = led_name;
|
||||||
|
+ break;
|
||||||
|
+ case 1:
|
||||||
|
+ ap9x_wmac1_data.led_name = led_name;
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
__init struct ath9k_platform_data *ap9x_pci_get_wmac_data(unsigned wmac)
|
||||||
|
{
|
||||||
|
switch (wmac) {
|
||||||
|
diff --git a/target/linux/ar71xx/files/arch/mips/ath79/dev-ap9x-pci.h b/target/linux/ar71xx/files/arch/mips/ath79/dev-ap9x-pci.h
|
||||||
|
index ad288cb..dcfe541 100644
|
||||||
|
--- a/target/linux/ar71xx/files/arch/mips/ath79/dev-ap9x-pci.h
|
||||||
|
+++ b/target/linux/ar71xx/files/arch/mips/ath79/dev-ap9x-pci.h
|
||||||
|
@@ -19,6 +19,7 @@ void ap9x_pci_setup_wmac_led_pin(unsigned wmac, int pin);
|
||||||
|
void ap9x_pci_setup_wmac_gpio(unsigned wmac, u32 mask, u32 val);
|
||||||
|
void ap9x_pci_setup_wmac_leds(unsigned wmac, struct gpio_led *leds,
|
||||||
|
int num_leds);
|
||||||
|
+void ap9x_pci_setup_wmac_led_name(unsigned wmac, const char *led_name);
|
||||||
|
struct ath9k_platform_data *ap9x_pci_get_wmac_data(unsigned wmac);
|
||||||
|
|
||||||
|
void ap91_pci_init(u8 *cal_data, u8 *mac_addr);
|
||||||
|
@@ -33,6 +34,8 @@ static inline void ap9x_pci_setup_wmac_gpio(unsigned wmac,
|
||||||
|
static inline void ap9x_pci_setup_wmac_leds(unsigned wmac,
|
||||||
|
struct gpio_led *leds,
|
||||||
|
int num_leds) {}
|
||||||
|
+static inline void ap9x_pci_setup_wmac_led_name(unsigned wmac,
|
||||||
|
+ const char *led_name) {}
|
||||||
|
static inline struct ath9k_platform_data *ap9x_pci_get_wmac_data(unsigned wmac)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
diff --git a/target/linux/generic/files/include/linux/ath9k_platform.h b/target/linux/generic/files/include/linux/ath9k_platform.h
|
||||||
|
index 30ce216..823e5ac 100644
|
||||||
|
--- a/target/linux/generic/files/include/linux/ath9k_platform.h
|
||||||
|
+++ b/target/linux/generic/files/include/linux/ath9k_platform.h
|
||||||
|
@@ -45,6 +45,7 @@ struct ath9k_platform_data {
|
||||||
|
|
||||||
|
int num_leds;
|
||||||
|
const struct gpio_led *leds;
|
||||||
|
+ const char *led_name;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* _LINUX_ATH9K_PLATFORM_H */
|
@ -0,0 +1,47 @@
|
|||||||
|
From: Matthias Schiffer <mschiffer@universe-factory.net>
|
||||||
|
Date: Sun, 29 May 2016 13:37:28 +0200
|
||||||
|
Subject: mac80211: ath9k: set default state for platform LEDs
|
||||||
|
|
||||||
|
Support default state for platform LEDs connected to ath9k device.
|
||||||
|
Now LEDs are correctly set on or off at ath9k module initialization.
|
||||||
|
|
||||||
|
Signed-off-by: Michal Cieslakiewicz <michal.cieslakiewicz@wp.pl>
|
||||||
|
Acked-by: Hartmut Knaack <knaack.h@gmx.de>
|
||||||
|
|
||||||
|
Backport of r48880
|
||||||
|
|
||||||
|
diff --git a/package/kernel/mac80211/patches/547-ath9k_led_defstate_fix.patch b/package/kernel/mac80211/patches/547-ath9k_led_defstate_fix.patch
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..db0b619
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/package/kernel/mac80211/patches/547-ath9k_led_defstate_fix.patch
|
||||||
|
@@ -0,0 +1,29 @@
|
||||||
|
+From: Michal Cieslakiewicz <michal.cieslakiewicz@wp.pl>
|
||||||
|
+Date: Sun, 31 Jan 2016 20:48:49 +0100
|
||||||
|
+Subject: [PATCH v4 2/8] mac80211: ath9k: set default state for platform LEDs
|
||||||
|
+
|
||||||
|
+Support default state for platform LEDs connected to ath9k device.
|
||||||
|
+Now LEDs are correctly set on or off at ath9k module initialization.
|
||||||
|
+Very useful if power LED is connected to wireless chip.
|
||||||
|
+
|
||||||
|
+Signed-off-by: Michal Cieslakiewicz <michal.cieslakiewicz@wp.pl>
|
||||||
|
+---
|
||||||
|
+ gpio.c | 7 +++++--
|
||||||
|
+ 1 file changed, 5 insertions(+), 2 deletions(-)
|
||||||
|
+
|
||||||
|
+--- a/drivers/net/wireless/ath/ath9k/gpio.c
|
||||||
|
++++ b/drivers/net/wireless/ath/ath9k/gpio.c
|
||||||
|
+@@ -54,8 +54,11 @@ static int ath_add_led(struct ath_softc
|
||||||
|
+ ath9k_hw_cfg_output(sc->sc_ah, gpio->gpio,
|
||||||
|
+ AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
|
||||||
|
+
|
||||||
|
+- /* LED off */
|
||||||
|
+- ath9k_hw_set_gpio(sc->sc_ah, gpio->gpio, gpio->active_low);
|
||||||
|
++ /* Set default LED state */
|
||||||
|
++ if (gpio->default_state == LEDS_GPIO_DEFSTATE_ON)
|
||||||
|
++ ath9k_hw_set_gpio(sc->sc_ah, gpio->gpio, !gpio->active_low);
|
||||||
|
++ else
|
||||||
|
++ ath9k_hw_set_gpio(sc->sc_ah, gpio->gpio, gpio->active_low);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
261
patches/openwrt/0082-mac80211-ath9k-enable-access-to-GPIO.patch
Normal file
261
patches/openwrt/0082-mac80211-ath9k-enable-access-to-GPIO.patch
Normal file
@ -0,0 +1,261 @@
|
|||||||
|
From: Matthias Schiffer <mschiffer@universe-factory.net>
|
||||||
|
Date: Sun, 29 May 2016 13:37:59 +0200
|
||||||
|
Subject: mac80211: ath9k: enable access to GPIO
|
||||||
|
|
||||||
|
Enable access to GPIO chip and its pins for Atheros AR92xx
|
||||||
|
wireless devices. For now AR9285 and AR9287 are supported.
|
||||||
|
|
||||||
|
Signed-off-by: Michal Cieslakiewicz <michal.cieslakiewicz@wp.pl>
|
||||||
|
Acked-by: Hartmut Knaack <knaack.h@gmx.de>
|
||||||
|
|
||||||
|
Backport of r48881
|
||||||
|
|
||||||
|
diff --git a/package/kernel/mac80211/patches/549-ath9k_enable_gpio_chip.patch b/package/kernel/mac80211/patches/549-ath9k_enable_gpio_chip.patch
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..beee169
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/package/kernel/mac80211/patches/549-ath9k_enable_gpio_chip.patch
|
||||||
|
@@ -0,0 +1,243 @@
|
||||||
|
+From: Michal Cieslakiewicz <michal.cieslakiewicz@wp.pl>
|
||||||
|
+Date: Sun, 31 Jan 2016 21:01:31 +0100
|
||||||
|
+Subject: [PATCH v4 4/8] mac80211: ath9k: enable access to GPIO
|
||||||
|
+
|
||||||
|
+Enable access to GPIO chip and its pins for Atheros AR92xx
|
||||||
|
+wireless devices. For now AR9285 and AR9287 are supported.
|
||||||
|
+
|
||||||
|
+Signed-off-by: Michal Cieslakiewicz <michal.cieslakiewicz@wp.pl>
|
||||||
|
+---
|
||||||
|
+ ath9k.h | 23 ++++++++++++
|
||||||
|
+ gpio.c | 121 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
+ init.c | 2 +
|
||||||
|
+ 3 files changed, 146 insertions(+)
|
||||||
|
+
|
||||||
|
+--- a/drivers/net/wireless/ath/ath9k/ath9k.h
|
||||||
|
++++ b/drivers/net/wireless/ath/ath9k/ath9k.h
|
||||||
|
+@@ -24,6 +24,7 @@
|
||||||
|
+ #include <linux/completion.h>
|
||||||
|
+ #include <linux/time.h>
|
||||||
|
+ #include <linux/hw_random.h>
|
||||||
|
++#include <linux/gpio/driver.h>
|
||||||
|
+
|
||||||
|
+ #include "common.h"
|
||||||
|
+ #include "debug.h"
|
||||||
|
+@@ -817,6 +818,13 @@ void ath_fill_led_pin(struct ath_softc *
|
||||||
|
+ int ath_create_gpio_led(struct ath_softc *sc, int gpio, const char *name,
|
||||||
|
+ const char *trigger, bool active_low);
|
||||||
|
+
|
||||||
|
++/***************/
|
||||||
|
++/* GPIO Chip */
|
||||||
|
++/***************/
|
||||||
|
++
|
||||||
|
++void ath9k_register_gpio_chip(struct ath_softc *sc);
|
||||||
|
++void ath9k_unregister_gpio_chip(struct ath_softc *sc);
|
||||||
|
++
|
||||||
|
+ #else
|
||||||
|
+ static inline void ath_init_leds(struct ath_softc *sc)
|
||||||
|
+ {
|
||||||
|
+@@ -828,6 +836,14 @@ static inline void ath_deinit_leds(struc
|
||||||
|
+ static inline void ath_fill_led_pin(struct ath_softc *sc)
|
||||||
|
+ {
|
||||||
|
+ }
|
||||||
|
++
|
||||||
|
++static inline void ath9k_register_gpio_chip(struct ath_softc *sc)
|
||||||
|
++{
|
||||||
|
++}
|
||||||
|
++
|
||||||
|
++static inline void ath9k_unregister_gpio_chip(struct ath_softc *sc)
|
||||||
|
++{
|
||||||
|
++}
|
||||||
|
+ #endif
|
||||||
|
+
|
||||||
|
+ /************************/
|
||||||
|
+@@ -963,6 +979,12 @@ struct ath_led {
|
||||||
|
+ struct led_classdev cdev;
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
++struct ath9k_gpio_chip {
|
||||||
|
++ struct ath_softc *sc;
|
||||||
|
++ char label[32];
|
||||||
|
++ struct gpio_chip gchip;
|
||||||
|
++};
|
||||||
|
++
|
||||||
|
+ struct ath_softc {
|
||||||
|
+ struct ieee80211_hw *hw;
|
||||||
|
+ struct device *dev;
|
||||||
|
+@@ -1017,6 +1039,7 @@ struct ath_softc {
|
||||||
|
+ #ifdef CPTCFG_MAC80211_LEDS
|
||||||
|
+ const char *led_default_trigger;
|
||||||
|
+ struct list_head leds;
|
||||||
|
++ struct ath9k_gpio_chip *gpiochip;
|
||||||
|
+ #endif
|
||||||
|
+
|
||||||
|
+ #ifdef CPTCFG_ATH9K_DEBUGFS
|
||||||
|
+--- a/drivers/net/wireless/ath/ath9k/gpio.c
|
||||||
|
++++ b/drivers/net/wireless/ath/ath9k/gpio.c
|
||||||
|
+@@ -22,6 +22,9 @@
|
||||||
|
+ /********************************/
|
||||||
|
+
|
||||||
|
+ #ifdef CPTCFG_MAC80211_LEDS
|
||||||
|
++
|
||||||
|
++#include <asm-generic/gpio.h>
|
||||||
|
++
|
||||||
|
+ static void ath_led_brightness(struct led_classdev *led_cdev,
|
||||||
|
+ enum led_brightness brightness)
|
||||||
|
+ {
|
||||||
|
+@@ -60,6 +63,10 @@ static int ath_add_led(struct ath_softc
|
||||||
|
+ else
|
||||||
|
+ ath9k_hw_set_gpio(sc->sc_ah, gpio->gpio, gpio->active_low);
|
||||||
|
+
|
||||||
|
++ /* If there is GPIO chip configured, reserve LED pin */
|
||||||
|
++ if (sc->gpiochip)
|
||||||
|
++ gpio_request(sc->gpiochip->gchip.base + gpio->gpio, gpio->name);
|
||||||
|
++
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+@@ -116,6 +123,9 @@ void ath_deinit_leds(struct ath_softc *s
|
||||||
|
+
|
||||||
|
+ while (!list_empty(&sc->leds)) {
|
||||||
|
+ led = list_first_entry(&sc->leds, struct ath_led, list);
|
||||||
|
++ /* If there is GPIO chip configured, free LED pin */
|
||||||
|
++ if (sc->gpiochip)
|
||||||
|
++ gpio_free(sc->gpiochip->gchip.base + led->gpio->gpio);
|
||||||
|
+ list_del(&led->list);
|
||||||
|
+ ath_led_brightness(&led->cdev, LED_OFF);
|
||||||
|
+ led_classdev_unregister(&led->cdev);
|
||||||
|
+@@ -186,6 +196,117 @@ void ath_fill_led_pin(struct ath_softc *
|
||||||
|
+ /* LED off, active low */
|
||||||
|
+ ath9k_hw_set_gpio(ah, ah->led_pin, (ah->config.led_active_high) ? 0 : 1);
|
||||||
|
+ }
|
||||||
|
++
|
||||||
|
++/***************/
|
||||||
|
++/* GPIO Chip */
|
||||||
|
++/***************/
|
||||||
|
++
|
||||||
|
++/* gpio_chip handler : set GPIO to input */
|
||||||
|
++static int ath9k_gpio_pin_cfg_input(struct gpio_chip *chip, unsigned offset)
|
||||||
|
++{
|
||||||
|
++ struct ath9k_gpio_chip *gc = container_of(chip, struct ath9k_gpio_chip,
|
||||||
|
++ gchip);
|
||||||
|
++
|
||||||
|
++ ath9k_hw_cfg_gpio_input(gc->sc->sc_ah, offset);
|
||||||
|
++
|
||||||
|
++ return 0;
|
||||||
|
++}
|
||||||
|
++
|
||||||
|
++/* gpio_chip handler : set GPIO to output */
|
||||||
|
++static int ath9k_gpio_pin_cfg_output(struct gpio_chip *chip, unsigned offset,
|
||||||
|
++ int value)
|
||||||
|
++{
|
||||||
|
++ struct ath9k_gpio_chip *gc = container_of(chip, struct ath9k_gpio_chip,
|
||||||
|
++ gchip);
|
||||||
|
++
|
||||||
|
++ ath9k_hw_cfg_output(gc->sc->sc_ah, offset,
|
||||||
|
++ AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
|
||||||
|
++ ath9k_hw_set_gpio(gc->sc->sc_ah, offset, value);
|
||||||
|
++
|
||||||
|
++ return 0;
|
||||||
|
++}
|
||||||
|
++
|
||||||
|
++/* gpio_chip handler : query GPIO direction (0=out, 1=in) */
|
||||||
|
++static int ath9k_gpio_pin_get_dir(struct gpio_chip *chip, unsigned offset)
|
||||||
|
++{
|
||||||
|
++ struct ath9k_gpio_chip *gc = container_of(chip, struct ath9k_gpio_chip,
|
||||||
|
++ gchip);
|
||||||
|
++ struct ath_hw *ah = gc->sc->sc_ah;
|
||||||
|
++
|
||||||
|
++ return !((REG_READ(ah, AR_GPIO_OE_OUT) >> (offset * 2)) & 3);
|
||||||
|
++}
|
||||||
|
++
|
||||||
|
++/* gpio_chip handler : get GPIO pin value */
|
||||||
|
++static int ath9k_gpio_pin_get(struct gpio_chip *chip, unsigned offset)
|
||||||
|
++{
|
||||||
|
++ struct ath9k_gpio_chip *gc = container_of(chip, struct ath9k_gpio_chip,
|
||||||
|
++ gchip);
|
||||||
|
++
|
||||||
|
++ return ath9k_hw_gpio_get(gc->sc->sc_ah, offset);
|
||||||
|
++}
|
||||||
|
++
|
||||||
|
++/* gpio_chip handler : set GPIO pin to value */
|
||||||
|
++static void ath9k_gpio_pin_set(struct gpio_chip *chip, unsigned offset,
|
||||||
|
++ int value)
|
||||||
|
++{
|
||||||
|
++ struct ath9k_gpio_chip *gc = container_of(chip, struct ath9k_gpio_chip,
|
||||||
|
++ gchip);
|
||||||
|
++
|
||||||
|
++ ath9k_hw_set_gpio(gc->sc->sc_ah, offset, value);
|
||||||
|
++}
|
||||||
|
++
|
||||||
|
++/* register GPIO chip */
|
||||||
|
++void ath9k_register_gpio_chip(struct ath_softc *sc)
|
||||||
|
++{
|
||||||
|
++ struct ath9k_gpio_chip *gc;
|
||||||
|
++ u16 ng;
|
||||||
|
++
|
||||||
|
++ /* for now only AR9285 and AR9287 are recognized */
|
||||||
|
++ if (AR_SREV_9287(sc->sc_ah))
|
||||||
|
++ ng = AR9287_NUM_GPIO;
|
||||||
|
++ else if (AR_SREV_9285(sc->sc_ah))
|
||||||
|
++ ng = AR9285_NUM_GPIO;
|
||||||
|
++ else
|
||||||
|
++ return;
|
||||||
|
++
|
||||||
|
++ gc = kzalloc(sizeof(struct ath9k_gpio_chip), GFP_KERNEL);
|
||||||
|
++ if (!gc)
|
||||||
|
++ return;
|
||||||
|
++
|
||||||
|
++ snprintf(gc->label, sizeof(gc->label), "ath9k-%s",
|
||||||
|
++ wiphy_name(sc->hw->wiphy));
|
||||||
|
++ gc->gchip.label = gc->label;
|
||||||
|
++ gc->gchip.base = -1; /* determine base automatically */
|
||||||
|
++ gc->gchip.ngpio = ng;
|
||||||
|
++ gc->gchip.direction_input = ath9k_gpio_pin_cfg_input;
|
||||||
|
++ gc->gchip.direction_output = ath9k_gpio_pin_cfg_output;
|
||||||
|
++ gc->gchip.get_direction = ath9k_gpio_pin_get_dir;
|
||||||
|
++ gc->gchip.get = ath9k_gpio_pin_get;
|
||||||
|
++ gc->gchip.set = ath9k_gpio_pin_set;
|
||||||
|
++ gc->gchip.owner = THIS_MODULE;
|
||||||
|
++
|
||||||
|
++ if (gpiochip_add(&gc->gchip)) {
|
||||||
|
++ kfree(gc);
|
||||||
|
++ return;
|
||||||
|
++ }
|
||||||
|
++
|
||||||
|
++ sc->gpiochip = gc;
|
||||||
|
++ gc->sc = sc;
|
||||||
|
++}
|
||||||
|
++
|
||||||
|
++/* remove GPIO chip */
|
||||||
|
++void ath9k_unregister_gpio_chip(struct ath_softc *sc)
|
||||||
|
++{
|
||||||
|
++ struct ath9k_gpio_chip *gc = sc->gpiochip;
|
||||||
|
++
|
||||||
|
++ if (!gc)
|
||||||
|
++ return;
|
||||||
|
++
|
||||||
|
++ gpiochip_remove(&gc->gchip);
|
||||||
|
++ kfree(gc);
|
||||||
|
++ sc->gpiochip = NULL;
|
||||||
|
++}
|
||||||
|
++
|
||||||
|
+ #endif
|
||||||
|
+
|
||||||
|
+ /*******************/
|
||||||
|
+--- a/drivers/net/wireless/ath/ath9k/init.c
|
||||||
|
++++ b/drivers/net/wireless/ath/ath9k/init.c
|
||||||
|
+@@ -979,6 +979,7 @@ int ath9k_init_device(u16 devid, struct
|
||||||
|
+ goto debug_cleanup;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
++ ath9k_register_gpio_chip(sc);
|
||||||
|
+ ath_init_leds(sc);
|
||||||
|
+ ath_start_rfkill_poll(sc);
|
||||||
|
+
|
||||||
|
+@@ -1026,6 +1027,7 @@ void ath9k_deinit_device(struct ath_soft
|
||||||
|
+
|
||||||
|
+ wiphy_rfkill_stop_polling(sc->hw->wiphy);
|
||||||
|
+ ath_deinit_leds(sc);
|
||||||
|
++ ath9k_unregister_gpio_chip(sc);
|
||||||
|
+
|
||||||
|
+ ath9k_ps_restore(sc);
|
||||||
|
+
|
30
patches/openwrt/0083-mac80211-refresh-patch.patch
Normal file
30
patches/openwrt/0083-mac80211-refresh-patch.patch
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
From: Matthias Schiffer <mschiffer@universe-factory.net>
|
||||||
|
Date: Sun, 29 May 2016 13:38:19 +0200
|
||||||
|
Subject: mac80211: refresh patch
|
||||||
|
|
||||||
|
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
|
||||||
|
|
||||||
|
Backport of r48882
|
||||||
|
|
||||||
|
diff --git a/package/kernel/mac80211/patches/549-ath9k_enable_gpio_chip.patch b/package/kernel/mac80211/patches/549-ath9k_enable_gpio_chip.patch
|
||||||
|
index beee169..55bb991 100644
|
||||||
|
--- a/package/kernel/mac80211/patches/549-ath9k_enable_gpio_chip.patch
|
||||||
|
+++ b/package/kernel/mac80211/patches/549-ath9k_enable_gpio_chip.patch
|
||||||
|
@@ -225,7 +225,7 @@ Signed-off-by: Michal Cieslakiewicz <michal.cieslakiewicz@wp.pl>
|
||||||
|
/*******************/
|
||||||
|
--- a/drivers/net/wireless/ath/ath9k/init.c
|
||||||
|
+++ b/drivers/net/wireless/ath/ath9k/init.c
|
||||||
|
-@@ -979,6 +979,7 @@ int ath9k_init_device(u16 devid, struct
|
||||||
|
+@@ -975,6 +975,7 @@ int ath9k_init_device(u16 devid, struct
|
||||||
|
goto debug_cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -233,7 +233,7 @@ Signed-off-by: Michal Cieslakiewicz <michal.cieslakiewicz@wp.pl>
|
||||||
|
ath_init_leds(sc);
|
||||||
|
ath_start_rfkill_poll(sc);
|
||||||
|
|
||||||
|
-@@ -1026,6 +1027,7 @@ void ath9k_deinit_device(struct ath_soft
|
||||||
|
+@@ -1022,6 +1023,7 @@ void ath9k_deinit_device(struct ath_soft
|
||||||
|
|
||||||
|
wiphy_rfkill_stop_polling(sc->hw->wiphy);
|
||||||
|
ath_deinit_leds(sc);
|
259
patches/openwrt/0084-mac80211-ath9k-enable-GPIO-buttons.patch
Normal file
259
patches/openwrt/0084-mac80211-ath9k-enable-GPIO-buttons.patch
Normal file
@ -0,0 +1,259 @@
|
|||||||
|
From: Matthias Schiffer <mschiffer@universe-factory.net>
|
||||||
|
Date: Sun, 29 May 2016 13:38:45 +0200
|
||||||
|
Subject: mac80211: ath9k: enable GPIO buttons
|
||||||
|
|
||||||
|
Enable platform-defined GPIO button support for ath9k device.
|
||||||
|
Key poller is activated for attached platform buttons.
|
||||||
|
Requires ath9k GPIO chip access.
|
||||||
|
|
||||||
|
Signed-off-by: Michal Cieslakiewicz <michal.cieslakiewicz@wp.pl>
|
||||||
|
|
||||||
|
Backport of r48921
|
||||||
|
|
||||||
|
diff --git a/package/kernel/mac80211/patches/550-ath9k_enable_gpio_buttons.patch b/package/kernel/mac80211/patches/550-ath9k_enable_gpio_buttons.patch
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..e3a8cec
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/package/kernel/mac80211/patches/550-ath9k_enable_gpio_buttons.patch
|
||||||
|
@@ -0,0 +1,169 @@
|
||||||
|
+From: Michal Cieslakiewicz <michal.cieslakiewicz@wp.pl>
|
||||||
|
+Subject: [PATCH v5 5/8] mac80211: ath9k: enable GPIO buttons
|
||||||
|
+
|
||||||
|
+Enable platform-defined GPIO button support for ath9k device.
|
||||||
|
+Key poller is activated for attached platform buttons.
|
||||||
|
+Requires ath9k GPIO chip access.
|
||||||
|
+
|
||||||
|
+Signed-off-by: Michal Cieslakiewicz <michal.cieslakiewicz@wp.pl>
|
||||||
|
+---
|
||||||
|
+ drivers/net/wireless/ath/ath9k/ath9k.h | 16 ++++++
|
||||||
|
+ drivers/net/wireless/ath/ath9k/gpio.c | 77 +++++++++++++++++++++++++++++++++
|
||||||
|
+ drivers/net/wireless/ath/ath9k/init.c | 2
|
||||||
|
+ include/linux/ath9k_platform.h | 4 +
|
||||||
|
+ 4 files changed, 99 insertions(+)
|
||||||
|
+
|
||||||
|
+--- a/drivers/net/wireless/ath/ath9k/ath9k.h
|
||||||
|
++++ b/drivers/net/wireless/ath/ath9k/ath9k.h
|
||||||
|
+@@ -825,6 +825,13 @@ int ath_create_gpio_led(struct ath_softc
|
||||||
|
+ void ath9k_register_gpio_chip(struct ath_softc *sc);
|
||||||
|
+ void ath9k_unregister_gpio_chip(struct ath_softc *sc);
|
||||||
|
+
|
||||||
|
++/******************/
|
||||||
|
++/* GPIO Buttons */
|
||||||
|
++/******************/
|
||||||
|
++
|
||||||
|
++void ath9k_init_buttons(struct ath_softc *sc);
|
||||||
|
++void ath9k_deinit_buttons(struct ath_softc *sc);
|
||||||
|
++
|
||||||
|
+ #else
|
||||||
|
+ static inline void ath_init_leds(struct ath_softc *sc)
|
||||||
|
+ {
|
||||||
|
+@@ -844,6 +851,14 @@ static inline void ath9k_register_gpio_c
|
||||||
|
+ static inline void ath9k_unregister_gpio_chip(struct ath_softc *sc)
|
||||||
|
+ {
|
||||||
|
+ }
|
||||||
|
++
|
||||||
|
++static inline void ath9k_init_buttons(struct ath_softc *sc)
|
||||||
|
++{
|
||||||
|
++}
|
||||||
|
++
|
||||||
|
++static inline void ath9k_deinit_buttons(struct ath_softc *sc)
|
||||||
|
++{
|
||||||
|
++}
|
||||||
|
+ #endif
|
||||||
|
+
|
||||||
|
+ /************************/
|
||||||
|
+@@ -1040,6 +1055,7 @@ struct ath_softc {
|
||||||
|
+ const char *led_default_trigger;
|
||||||
|
+ struct list_head leds;
|
||||||
|
+ struct ath9k_gpio_chip *gpiochip;
|
||||||
|
++ struct platform_device *btnpdev; /* gpio-keys-polled */
|
||||||
|
+ #endif
|
||||||
|
+
|
||||||
|
+ #ifdef CPTCFG_ATH9K_DEBUGFS
|
||||||
|
+--- a/drivers/net/wireless/ath/ath9k/gpio.c
|
||||||
|
++++ b/drivers/net/wireless/ath/ath9k/gpio.c
|
||||||
|
+@@ -24,6 +24,8 @@
|
||||||
|
+ #ifdef CPTCFG_MAC80211_LEDS
|
||||||
|
+
|
||||||
|
+ #include <asm-generic/gpio.h>
|
||||||
|
++#include <linux/platform_device.h>
|
||||||
|
++#include <linux/gpio_keys.h>
|
||||||
|
+
|
||||||
|
+ static void ath_led_brightness(struct led_classdev *led_cdev,
|
||||||
|
+ enum led_brightness brightness)
|
||||||
|
+@@ -159,7 +161,7 @@ void ath_init_leds(struct ath_softc *sc)
|
||||||
|
+ ath_create_gpio_led(sc, sc->sc_ah->led_pin, led_name, trigger,
|
||||||
|
+ !sc->sc_ah->config.led_active_high);
|
||||||
|
+
|
||||||
|
+- if (!pdata)
|
||||||
|
++ if (!pdata || !pdata->leds || !pdata->num_leds)
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ for (i = 0; i < pdata->num_leds; i++)
|
||||||
|
+@@ -307,6 +309,63 @@ void ath9k_unregister_gpio_chip(struct a
|
||||||
|
+ sc->gpiochip = NULL;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
++/******************/
|
||||||
|
++/* GPIO Buttons */
|
||||||
|
++/******************/
|
||||||
|
++
|
||||||
|
++/* add GPIO buttons */
|
||||||
|
++void ath9k_init_buttons(struct ath_softc *sc)
|
||||||
|
++{
|
||||||
|
++ struct ath9k_platform_data *pdata = sc->dev->platform_data;
|
||||||
|
++ struct platform_device *pdev;
|
||||||
|
++ struct gpio_keys_platform_data gkpdata;
|
||||||
|
++ struct gpio_keys_button *bt;
|
||||||
|
++ int i;
|
||||||
|
++
|
||||||
|
++ if (!sc->gpiochip)
|
||||||
|
++ return;
|
||||||
|
++
|
||||||
|
++ if (!pdata || !pdata->btns || !pdata->num_btns)
|
||||||
|
++ return;
|
||||||
|
++
|
||||||
|
++ bt = devm_kmemdup(sc->dev, pdata->btns,
|
||||||
|
++ pdata->num_btns * sizeof(struct gpio_keys_button),
|
||||||
|
++ GFP_KERNEL);
|
||||||
|
++ if (!bt)
|
||||||
|
++ return;
|
||||||
|
++
|
||||||
|
++ for (i = 0; i < pdata->num_btns; i++) {
|
||||||
|
++ ath9k_hw_cfg_gpio_input(sc->sc_ah, pdata->btns[i].gpio);
|
||||||
|
++ bt[i].gpio = sc->gpiochip->gchip.base + pdata->btns[i].gpio;
|
||||||
|
++ }
|
||||||
|
++
|
||||||
|
++ memset(&gkpdata, 0, sizeof(struct gpio_keys_platform_data));
|
||||||
|
++ gkpdata.buttons = bt;
|
||||||
|
++ gkpdata.nbuttons = pdata->num_btns;
|
||||||
|
++ gkpdata.poll_interval = pdata->btn_poll_interval;
|
||||||
|
++
|
||||||
|
++ pdev = platform_device_register_data(sc->dev, "gpio-keys-polled",
|
||||||
|
++ PLATFORM_DEVID_AUTO, &gkpdata,
|
||||||
|
++ sizeof(gkpdata));
|
||||||
|
++ if (!IS_ERR_OR_NULL(pdev))
|
||||||
|
++ sc->btnpdev = pdev;
|
||||||
|
++ else {
|
||||||
|
++ sc->btnpdev = NULL;
|
||||||
|
++ devm_kfree(sc->dev, bt);
|
||||||
|
++ }
|
||||||
|
++}
|
||||||
|
++
|
||||||
|
++/* remove GPIO buttons */
|
||||||
|
++void ath9k_deinit_buttons(struct ath_softc *sc)
|
||||||
|
++{
|
||||||
|
++ if (!sc->gpiochip || !sc->btnpdev)
|
||||||
|
++ return;
|
||||||
|
++
|
||||||
|
++ platform_device_unregister(sc->btnpdev);
|
||||||
|
++
|
||||||
|
++ sc->btnpdev = NULL;
|
||||||
|
++}
|
||||||
|
++
|
||||||
|
+ #endif
|
||||||
|
+
|
||||||
|
+ /*******************/
|
||||||
|
+--- a/drivers/net/wireless/ath/ath9k/init.c
|
||||||
|
++++ b/drivers/net/wireless/ath/ath9k/init.c
|
||||||
|
+@@ -977,6 +977,7 @@ int ath9k_init_device(u16 devid, struct
|
||||||
|
+
|
||||||
|
+ ath9k_register_gpio_chip(sc);
|
||||||
|
+ ath_init_leds(sc);
|
||||||
|
++ ath9k_init_buttons(sc);
|
||||||
|
+ ath_start_rfkill_poll(sc);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+@@ -1022,6 +1023,7 @@ void ath9k_deinit_device(struct ath_soft
|
||||||
|
+ ath9k_ps_wakeup(sc);
|
||||||
|
+
|
||||||
|
+ wiphy_rfkill_stop_polling(sc->hw->wiphy);
|
||||||
|
++ ath9k_deinit_buttons(sc);
|
||||||
|
+ ath_deinit_leds(sc);
|
||||||
|
+ ath9k_unregister_gpio_chip(sc);
|
||||||
|
+
|
||||||
|
+--- a/include/linux/ath9k_platform.h
|
||||||
|
++++ b/include/linux/ath9k_platform.h
|
||||||
|
+@@ -46,6 +46,10 @@ struct ath9k_platform_data {
|
||||||
|
+ int num_leds;
|
||||||
|
+ const struct gpio_led *leds;
|
||||||
|
+ const char *led_name;
|
||||||
|
++
|
||||||
|
++ unsigned num_btns;
|
||||||
|
++ const struct gpio_keys_button *btns;
|
||||||
|
++ unsigned btn_poll_interval;
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+ #endif /* _LINUX_ATH9K_PLATFORM_H */
|
||||||
|
diff --git a/target/linux/ar71xx/files/arch/mips/ath79/dev-ap9x-pci.c b/target/linux/ar71xx/files/arch/mips/ath79/dev-ap9x-pci.c
|
||||||
|
index bf80d4d..20bb06e 100644
|
||||||
|
--- a/target/linux/ar71xx/files/arch/mips/ath79/dev-ap9x-pci.c
|
||||||
|
+++ b/target/linux/ar71xx/files/arch/mips/ath79/dev-ap9x-pci.c
|
||||||
|
@@ -93,6 +93,20 @@ __init void ap9x_pci_setup_wmac_leds(unsigned wmac, struct gpio_led *leds,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+__init void ap9x_pci_setup_wmac_btns(unsigned wmac,
|
||||||
|
+ struct gpio_keys_button *btns,
|
||||||
|
+ unsigned num_btns, unsigned poll_interval)
|
||||||
|
+{
|
||||||
|
+ struct ath9k_platform_data *ap9x_wmac_data;
|
||||||
|
+
|
||||||
|
+ if (!(ap9x_wmac_data = ap9x_pci_get_wmac_data(wmac)))
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ ap9x_wmac_data->btns = btns;
|
||||||
|
+ ap9x_wmac_data->num_btns = num_btns;
|
||||||
|
+ ap9x_wmac_data->btn_poll_interval = poll_interval;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static int ap91_pci_plat_dev_init(struct pci_dev *dev)
|
||||||
|
{
|
||||||
|
switch (PCI_SLOT(dev->devfn)) {
|
||||||
|
diff --git a/target/linux/ar71xx/files/arch/mips/ath79/dev-ap9x-pci.h b/target/linux/ar71xx/files/arch/mips/ath79/dev-ap9x-pci.h
|
||||||
|
index dcfe541..d7c0185 100644
|
||||||
|
--- a/target/linux/ar71xx/files/arch/mips/ath79/dev-ap9x-pci.h
|
||||||
|
+++ b/target/linux/ar71xx/files/arch/mips/ath79/dev-ap9x-pci.h
|
||||||
|
@@ -12,6 +12,7 @@
|
||||||
|
#define _ATH79_DEV_AP9X_PCI_H
|
||||||
|
|
||||||
|
struct gpio_led;
|
||||||
|
+struct gpio_keys_button;
|
||||||
|
struct ath9k_platform_data;
|
||||||
|
|
||||||
|
#if defined(CONFIG_ATH79_DEV_AP9X_PCI)
|
||||||
|
@@ -20,6 +21,8 @@ void ap9x_pci_setup_wmac_gpio(unsigned wmac, u32 mask, u32 val);
|
||||||
|
void ap9x_pci_setup_wmac_leds(unsigned wmac, struct gpio_led *leds,
|
||||||
|
int num_leds);
|
||||||
|
void ap9x_pci_setup_wmac_led_name(unsigned wmac, const char *led_name);
|
||||||
|
+void ap9x_pci_setup_wmac_btns(unsigned wmac, struct gpio_keys_button *btns,
|
||||||
|
+ unsigned num_btns, unsigned poll_interval);
|
||||||
|
struct ath9k_platform_data *ap9x_pci_get_wmac_data(unsigned wmac);
|
||||||
|
|
||||||
|
void ap91_pci_init(u8 *cal_data, u8 *mac_addr);
|
||||||
|
@@ -36,6 +39,10 @@ static inline void ap9x_pci_setup_wmac_leds(unsigned wmac,
|
||||||
|
int num_leds) {}
|
||||||
|
static inline void ap9x_pci_setup_wmac_led_name(unsigned wmac,
|
||||||
|
const char *led_name) {}
|
||||||
|
+static inline void ap9x_pci_setup_wmac_btns(unsigned wmac,
|
||||||
|
+ struct gpio_keys_button *btns,
|
||||||
|
+ unsigned num_btns,
|
||||||
|
+ unsigned poll_interval) {}
|
||||||
|
static inline struct ath9k_platform_data *ap9x_pci_get_wmac_data(unsigned wmac)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
diff --git a/target/linux/generic/files/include/linux/ath9k_platform.h b/target/linux/generic/files/include/linux/ath9k_platform.h
|
||||||
|
index 823e5ac..e543a64 100644
|
||||||
|
--- a/target/linux/generic/files/include/linux/ath9k_platform.h
|
||||||
|
+++ b/target/linux/generic/files/include/linux/ath9k_platform.h
|
||||||
|
@@ -46,6 +46,10 @@ struct ath9k_platform_data {
|
||||||
|
int num_leds;
|
||||||
|
const struct gpio_led *leds;
|
||||||
|
const char *led_name;
|
||||||
|
+
|
||||||
|
+ unsigned num_btns;
|
||||||
|
+ const struct gpio_keys_button *btns;
|
||||||
|
+ unsigned btn_poll_interval;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* _LINUX_ATH9K_PLATFORM_H */
|
@ -0,0 +1,827 @@
|
|||||||
|
From: Matthias Schiffer <mschiffer@universe-factory.net>
|
||||||
|
Date: Sun, 29 May 2016 13:39:10 +0200
|
||||||
|
Subject: mac80211: rework gpio chip/button support to build on platforms without CONFIG_GPIOLIB
|
||||||
|
|
||||||
|
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
|
||||||
|
|
||||||
|
Backport of r48938
|
||||||
|
|
||||||
|
diff --git a/package/kernel/mac80211/patches/548-ath9k_enable_gpio_chip.patch b/package/kernel/mac80211/patches/548-ath9k_enable_gpio_chip.patch
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..f91d85c
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/package/kernel/mac80211/patches/548-ath9k_enable_gpio_chip.patch
|
||||||
|
@@ -0,0 +1,235 @@
|
||||||
|
+From: Michal Cieslakiewicz <michal.cieslakiewicz@wp.pl>
|
||||||
|
+Date: Sun, 31 Jan 2016 21:01:31 +0100
|
||||||
|
+Subject: [PATCH v4 4/8] mac80211: ath9k: enable access to GPIO
|
||||||
|
+
|
||||||
|
+Enable access to GPIO chip and its pins for Atheros AR92xx
|
||||||
|
+wireless devices. For now AR9285 and AR9287 are supported.
|
||||||
|
+
|
||||||
|
+Signed-off-by: Michal Cieslakiewicz <michal.cieslakiewicz@wp.pl>
|
||||||
|
+Signed-off-by: Felix Fietkau <nbd@openwrt.org>
|
||||||
|
+---
|
||||||
|
+--- a/drivers/net/wireless/ath/ath9k/ath9k.h
|
||||||
|
++++ b/drivers/net/wireless/ath/ath9k/ath9k.h
|
||||||
|
+@@ -24,6 +24,7 @@
|
||||||
|
+ #include <linux/completion.h>
|
||||||
|
+ #include <linux/time.h>
|
||||||
|
+ #include <linux/hw_random.h>
|
||||||
|
++#include <linux/gpio/driver.h>
|
||||||
|
+
|
||||||
|
+ #include "common.h"
|
||||||
|
+ #include "debug.h"
|
||||||
|
+@@ -963,6 +964,14 @@ struct ath_led {
|
||||||
|
+ struct led_classdev cdev;
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
++#ifdef CONFIG_GPIOLIB
|
||||||
|
++struct ath9k_gpio_chip {
|
||||||
|
++ struct ath_softc *sc;
|
||||||
|
++ char label[32];
|
||||||
|
++ struct gpio_chip gchip;
|
||||||
|
++};
|
||||||
|
++#endif
|
||||||
|
++
|
||||||
|
+ struct ath_softc {
|
||||||
|
+ struct ieee80211_hw *hw;
|
||||||
|
+ struct device *dev;
|
||||||
|
+@@ -1017,6 +1026,9 @@ struct ath_softc {
|
||||||
|
+ #ifdef CPTCFG_MAC80211_LEDS
|
||||||
|
+ const char *led_default_trigger;
|
||||||
|
+ struct list_head leds;
|
||||||
|
++#ifdef CONFIG_GPIOLIB
|
||||||
|
++ struct ath9k_gpio_chip *gpiochip;
|
||||||
|
++#endif
|
||||||
|
+ #endif
|
||||||
|
+
|
||||||
|
+ #ifdef CPTCFG_ATH9K_DEBUGFS
|
||||||
|
+--- a/drivers/net/wireless/ath/ath9k/gpio.c
|
||||||
|
++++ b/drivers/net/wireless/ath/ath9k/gpio.c
|
||||||
|
+@@ -16,12 +16,138 @@
|
||||||
|
+
|
||||||
|
+ #include "ath9k.h"
|
||||||
|
+ #include <linux/ath9k_platform.h>
|
||||||
|
++#include <linux/gpio.h>
|
||||||
|
++
|
||||||
|
++#ifdef CPTCFG_MAC80211_LEDS
|
||||||
|
++
|
||||||
|
++#ifdef CONFIG_GPIOLIB
|
||||||
|
++
|
||||||
|
++/***************/
|
||||||
|
++/* GPIO Chip */
|
||||||
|
++/***************/
|
||||||
|
++
|
||||||
|
++/* gpio_chip handler : set GPIO to input */
|
||||||
|
++static int ath9k_gpio_pin_cfg_input(struct gpio_chip *chip, unsigned offset)
|
||||||
|
++{
|
||||||
|
++ struct ath9k_gpio_chip *gc = container_of(chip, struct ath9k_gpio_chip,
|
||||||
|
++ gchip);
|
||||||
|
++
|
||||||
|
++ ath9k_hw_cfg_gpio_input(gc->sc->sc_ah, offset);
|
||||||
|
++
|
||||||
|
++ return 0;
|
||||||
|
++}
|
||||||
|
++
|
||||||
|
++/* gpio_chip handler : set GPIO to output */
|
||||||
|
++static int ath9k_gpio_pin_cfg_output(struct gpio_chip *chip, unsigned offset,
|
||||||
|
++ int value)
|
||||||
|
++{
|
||||||
|
++ struct ath9k_gpio_chip *gc = container_of(chip, struct ath9k_gpio_chip,
|
||||||
|
++ gchip);
|
||||||
|
++
|
||||||
|
++ ath9k_hw_cfg_output(gc->sc->sc_ah, offset,
|
||||||
|
++ AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
|
||||||
|
++ ath9k_hw_set_gpio(gc->sc->sc_ah, offset, value);
|
||||||
|
++
|
||||||
|
++ return 0;
|
||||||
|
++}
|
||||||
|
++
|
||||||
|
++/* gpio_chip handler : query GPIO direction (0=out, 1=in) */
|
||||||
|
++static int ath9k_gpio_pin_get_dir(struct gpio_chip *chip, unsigned offset)
|
||||||
|
++{
|
||||||
|
++ struct ath9k_gpio_chip *gc = container_of(chip, struct ath9k_gpio_chip,
|
||||||
|
++ gchip);
|
||||||
|
++ struct ath_hw *ah = gc->sc->sc_ah;
|
||||||
|
++
|
||||||
|
++ return !((REG_READ(ah, AR_GPIO_OE_OUT) >> (offset * 2)) & 3);
|
||||||
|
++}
|
||||||
|
++
|
||||||
|
++/* gpio_chip handler : get GPIO pin value */
|
||||||
|
++static int ath9k_gpio_pin_get(struct gpio_chip *chip, unsigned offset)
|
||||||
|
++{
|
||||||
|
++ struct ath9k_gpio_chip *gc = container_of(chip, struct ath9k_gpio_chip,
|
||||||
|
++ gchip);
|
||||||
|
++
|
||||||
|
++ return ath9k_hw_gpio_get(gc->sc->sc_ah, offset);
|
||||||
|
++}
|
||||||
|
++
|
||||||
|
++/* gpio_chip handler : set GPIO pin to value */
|
||||||
|
++static void ath9k_gpio_pin_set(struct gpio_chip *chip, unsigned offset,
|
||||||
|
++ int value)
|
||||||
|
++{
|
||||||
|
++ struct ath9k_gpio_chip *gc = container_of(chip, struct ath9k_gpio_chip,
|
||||||
|
++ gchip);
|
||||||
|
++
|
||||||
|
++ ath9k_hw_set_gpio(gc->sc->sc_ah, offset, value);
|
||||||
|
++}
|
||||||
|
++
|
||||||
|
++/* register GPIO chip */
|
||||||
|
++static void ath9k_register_gpio_chip(struct ath_softc *sc)
|
||||||
|
++{
|
||||||
|
++ struct ath9k_gpio_chip *gc;
|
||||||
|
++ u16 ng;
|
||||||
|
++
|
||||||
|
++ /* for now only AR9285 and AR9287 are recognized */
|
||||||
|
++ if (AR_SREV_9287(sc->sc_ah))
|
||||||
|
++ ng = AR9287_NUM_GPIO;
|
||||||
|
++ else if (AR_SREV_9285(sc->sc_ah))
|
||||||
|
++ ng = AR9285_NUM_GPIO;
|
||||||
|
++ else
|
||||||
|
++ return;
|
||||||
|
++
|
||||||
|
++ gc = kzalloc(sizeof(struct ath9k_gpio_chip), GFP_KERNEL);
|
||||||
|
++ if (!gc)
|
||||||
|
++ return;
|
||||||
|
++
|
||||||
|
++ snprintf(gc->label, sizeof(gc->label), "ath9k-%s",
|
||||||
|
++ wiphy_name(sc->hw->wiphy));
|
||||||
|
++ gc->gchip.label = gc->label;
|
||||||
|
++ gc->gchip.base = -1; /* determine base automatically */
|
||||||
|
++ gc->gchip.ngpio = ng;
|
||||||
|
++ gc->gchip.direction_input = ath9k_gpio_pin_cfg_input;
|
||||||
|
++ gc->gchip.direction_output = ath9k_gpio_pin_cfg_output;
|
||||||
|
++ gc->gchip.get_direction = ath9k_gpio_pin_get_dir;
|
||||||
|
++ gc->gchip.get = ath9k_gpio_pin_get;
|
||||||
|
++ gc->gchip.set = ath9k_gpio_pin_set;
|
||||||
|
++ gc->gchip.owner = THIS_MODULE;
|
||||||
|
++
|
||||||
|
++ if (gpiochip_add(&gc->gchip)) {
|
||||||
|
++ kfree(gc);
|
||||||
|
++ return;
|
||||||
|
++ }
|
||||||
|
++
|
||||||
|
++ sc->gpiochip = gc;
|
||||||
|
++ gc->sc = sc;
|
||||||
|
++}
|
||||||
|
++
|
||||||
|
++/* remove GPIO chip */
|
||||||
|
++static void ath9k_unregister_gpio_chip(struct ath_softc *sc)
|
||||||
|
++{
|
||||||
|
++ struct ath9k_gpio_chip *gc = sc->gpiochip;
|
||||||
|
++
|
||||||
|
++ if (!gc)
|
||||||
|
++ return;
|
||||||
|
++
|
||||||
|
++ gpiochip_remove(&gc->gchip);
|
||||||
|
++ kfree(gc);
|
||||||
|
++ sc->gpiochip = NULL;
|
||||||
|
++}
|
||||||
|
++
|
||||||
|
++#else /* CONFIG_GPIOLIB */
|
||||||
|
++
|
||||||
|
++static inline void ath9k_register_gpio_chip(struct ath_softc *sc)
|
||||||
|
++{
|
||||||
|
++}
|
||||||
|
++
|
||||||
|
++static inline void ath9k_unregister_gpio_chip(struct ath_softc *sc)
|
||||||
|
++{
|
||||||
|
++}
|
||||||
|
++
|
||||||
|
++#endif /* CONFIG_GPIOLIB */
|
||||||
|
+
|
||||||
|
+ /********************************/
|
||||||
|
+ /* LED functions */
|
||||||
|
+ /********************************/
|
||||||
|
+
|
||||||
|
+-#ifdef CPTCFG_MAC80211_LEDS
|
||||||
|
+ static void ath_led_brightness(struct led_classdev *led_cdev,
|
||||||
|
+ enum led_brightness brightness)
|
||||||
|
+ {
|
||||||
|
+@@ -60,6 +186,12 @@ static int ath_add_led(struct ath_softc
|
||||||
|
+ else
|
||||||
|
+ ath9k_hw_set_gpio(sc->sc_ah, gpio->gpio, gpio->active_low);
|
||||||
|
+
|
||||||
|
++#ifdef CONFIG_GPIOLIB
|
||||||
|
++ /* If there is GPIO chip configured, reserve LED pin */
|
||||||
|
++ if (sc->gpiochip)
|
||||||
|
++ gpio_request(sc->gpiochip->gchip.base + gpio->gpio, gpio->name);
|
||||||
|
++#endif
|
||||||
|
++
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+@@ -116,11 +248,17 @@ void ath_deinit_leds(struct ath_softc *s
|
||||||
|
+
|
||||||
|
+ while (!list_empty(&sc->leds)) {
|
||||||
|
+ led = list_first_entry(&sc->leds, struct ath_led, list);
|
||||||
|
++#ifdef CONFIG_GPIOLIB
|
||||||
|
++ /* If there is GPIO chip configured, free LED pin */
|
||||||
|
++ if (sc->gpiochip)
|
||||||
|
++ gpio_free(sc->gpiochip->gchip.base + led->gpio->gpio);
|
||||||
|
++#endif
|
||||||
|
+ list_del(&led->list);
|
||||||
|
+ ath_led_brightness(&led->cdev, LED_OFF);
|
||||||
|
+ led_classdev_unregister(&led->cdev);
|
||||||
|
+ kfree(led);
|
||||||
|
+ }
|
||||||
|
++ ath9k_unregister_gpio_chip(sc);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ void ath_init_leds(struct ath_softc *sc)
|
||||||
|
+@@ -135,6 +273,8 @@ void ath_init_leds(struct ath_softc *sc)
|
||||||
|
+ if (AR_SREV_9100(sc->sc_ah))
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
++ ath9k_register_gpio_chip(sc);
|
||||||
|
++
|
||||||
|
+ if (pdata && pdata->led_name)
|
||||||
|
+ strncpy(led_name, pdata->led_name, sizeof(led_name));
|
||||||
|
+ else
|
||||||
|
+@@ -186,6 +326,7 @@ void ath_fill_led_pin(struct ath_softc *
|
||||||
|
+ /* LED off, active low */
|
||||||
|
+ ath9k_hw_set_gpio(ah, ah->led_pin, (ah->config.led_active_high) ? 0 : 1);
|
||||||
|
+ }
|
||||||
|
++
|
||||||
|
+ #endif
|
||||||
|
+
|
||||||
|
+ /*******************/
|
||||||
|
diff --git a/package/kernel/mac80211/patches/549-ath9k_enable_gpio_buttons.patch b/package/kernel/mac80211/patches/549-ath9k_enable_gpio_buttons.patch
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..0527406
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/package/kernel/mac80211/patches/549-ath9k_enable_gpio_buttons.patch
|
||||||
|
@@ -0,0 +1,148 @@
|
||||||
|
+From: Michal Cieslakiewicz <michal.cieslakiewicz@wp.pl>
|
||||||
|
+Subject: [PATCH v5 5/8] mac80211: ath9k: enable GPIO buttons
|
||||||
|
+
|
||||||
|
+Enable platform-defined GPIO button support for ath9k device.
|
||||||
|
+Key poller is activated for attached platform buttons.
|
||||||
|
+Requires ath9k GPIO chip access.
|
||||||
|
+
|
||||||
|
+Signed-off-by: Michal Cieslakiewicz <michal.cieslakiewicz@wp.pl>
|
||||||
|
+Signed-off-by: Felix Fietkau <nbd@openwrt.org>
|
||||||
|
+---
|
||||||
|
+--- a/drivers/net/wireless/ath/ath9k/ath9k.h
|
||||||
|
++++ b/drivers/net/wireless/ath/ath9k/ath9k.h
|
||||||
|
+@@ -1028,6 +1028,7 @@ struct ath_softc {
|
||||||
|
+ struct list_head leds;
|
||||||
|
+ #ifdef CONFIG_GPIOLIB
|
||||||
|
+ struct ath9k_gpio_chip *gpiochip;
|
||||||
|
++ struct platform_device *btnpdev; /* gpio-keys-polled */
|
||||||
|
+ #endif
|
||||||
|
+ #endif
|
||||||
|
+
|
||||||
|
+--- a/drivers/net/wireless/ath/ath9k/gpio.c
|
||||||
|
++++ b/drivers/net/wireless/ath/ath9k/gpio.c
|
||||||
|
+@@ -17,6 +17,8 @@
|
||||||
|
+ #include "ath9k.h"
|
||||||
|
+ #include <linux/ath9k_platform.h>
|
||||||
|
+ #include <linux/gpio.h>
|
||||||
|
++#include <linux/platform_device.h>
|
||||||
|
++#include <linux/gpio_keys.h>
|
||||||
|
+
|
||||||
|
+ #ifdef CPTCFG_MAC80211_LEDS
|
||||||
|
+
|
||||||
|
+@@ -132,6 +134,63 @@ static void ath9k_unregister_gpio_chip(s
|
||||||
|
+ sc->gpiochip = NULL;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
++/******************/
|
||||||
|
++/* GPIO Buttons */
|
||||||
|
++/******************/
|
||||||
|
++
|
||||||
|
++/* add GPIO buttons */
|
||||||
|
++static void ath9k_init_buttons(struct ath_softc *sc)
|
||||||
|
++{
|
||||||
|
++ struct ath9k_platform_data *pdata = sc->dev->platform_data;
|
||||||
|
++ struct platform_device *pdev;
|
||||||
|
++ struct gpio_keys_platform_data gkpdata;
|
||||||
|
++ struct gpio_keys_button *bt;
|
||||||
|
++ int i;
|
||||||
|
++
|
||||||
|
++ if (!sc->gpiochip)
|
||||||
|
++ return;
|
||||||
|
++
|
||||||
|
++ if (!pdata || !pdata->btns || !pdata->num_btns)
|
||||||
|
++ return;
|
||||||
|
++
|
||||||
|
++ bt = devm_kmemdup(sc->dev, pdata->btns,
|
||||||
|
++ pdata->num_btns * sizeof(struct gpio_keys_button),
|
||||||
|
++ GFP_KERNEL);
|
||||||
|
++ if (!bt)
|
||||||
|
++ return;
|
||||||
|
++
|
||||||
|
++ for (i = 0; i < pdata->num_btns; i++) {
|
||||||
|
++ ath9k_hw_cfg_gpio_input(sc->sc_ah, pdata->btns[i].gpio);
|
||||||
|
++ bt[i].gpio = sc->gpiochip->gchip.base + pdata->btns[i].gpio;
|
||||||
|
++ }
|
||||||
|
++
|
||||||
|
++ memset(&gkpdata, 0, sizeof(struct gpio_keys_platform_data));
|
||||||
|
++ gkpdata.buttons = bt;
|
||||||
|
++ gkpdata.nbuttons = pdata->num_btns;
|
||||||
|
++ gkpdata.poll_interval = pdata->btn_poll_interval;
|
||||||
|
++
|
||||||
|
++ pdev = platform_device_register_data(sc->dev, "gpio-keys-polled",
|
||||||
|
++ PLATFORM_DEVID_AUTO, &gkpdata,
|
||||||
|
++ sizeof(gkpdata));
|
||||||
|
++ if (!IS_ERR_OR_NULL(pdev))
|
||||||
|
++ sc->btnpdev = pdev;
|
||||||
|
++ else {
|
||||||
|
++ sc->btnpdev = NULL;
|
||||||
|
++ devm_kfree(sc->dev, bt);
|
||||||
|
++ }
|
||||||
|
++}
|
||||||
|
++
|
||||||
|
++/* remove GPIO buttons */
|
||||||
|
++static void ath9k_deinit_buttons(struct ath_softc *sc)
|
||||||
|
++{
|
||||||
|
++ if (!sc->gpiochip || !sc->btnpdev)
|
||||||
|
++ return;
|
||||||
|
++
|
||||||
|
++ platform_device_unregister(sc->btnpdev);
|
||||||
|
++
|
||||||
|
++ sc->btnpdev = NULL;
|
||||||
|
++}
|
||||||
|
++
|
||||||
|
+ #else /* CONFIG_GPIOLIB */
|
||||||
|
+
|
||||||
|
+ static inline void ath9k_register_gpio_chip(struct ath_softc *sc)
|
||||||
|
+@@ -142,6 +201,14 @@ static inline void ath9k_unregister_gpio
|
||||||
|
+ {
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
++static inline void ath9k_init_buttons(struct ath_softc *sc)
|
||||||
|
++{
|
||||||
|
++}
|
||||||
|
++
|
||||||
|
++static inline void ath9k_deinit_buttons(struct ath_softc *sc)
|
||||||
|
++{
|
||||||
|
++}
|
||||||
|
++
|
||||||
|
+ #endif /* CONFIG_GPIOLIB */
|
||||||
|
+
|
||||||
|
+ /********************************/
|
||||||
|
+@@ -246,6 +313,7 @@ void ath_deinit_leds(struct ath_softc *s
|
||||||
|
+ {
|
||||||
|
+ struct ath_led *led;
|
||||||
|
+
|
||||||
|
++ ath9k_deinit_buttons(sc);
|
||||||
|
+ while (!list_empty(&sc->leds)) {
|
||||||
|
+ led = list_first_entry(&sc->leds, struct ath_led, list);
|
||||||
|
+ #ifdef CONFIG_GPIOLIB
|
||||||
|
+@@ -274,6 +342,7 @@ void ath_init_leds(struct ath_softc *sc)
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ ath9k_register_gpio_chip(sc);
|
||||||
|
++ ath9k_init_buttons(sc);
|
||||||
|
+
|
||||||
|
+ if (pdata && pdata->led_name)
|
||||||
|
+ strncpy(led_name, pdata->led_name, sizeof(led_name));
|
||||||
|
+@@ -289,7 +358,7 @@ void ath_init_leds(struct ath_softc *sc)
|
||||||
|
+ ath_create_gpio_led(sc, sc->sc_ah->led_pin, led_name, trigger,
|
||||||
|
+ !sc->sc_ah->config.led_active_high);
|
||||||
|
+
|
||||||
|
+- if (!pdata)
|
||||||
|
++ if (!pdata || !pdata->leds || !pdata->num_leds)
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ for (i = 0; i < pdata->num_leds; i++)
|
||||||
|
+--- a/include/linux/ath9k_platform.h
|
||||||
|
++++ b/include/linux/ath9k_platform.h
|
||||||
|
+@@ -46,6 +46,10 @@ struct ath9k_platform_data {
|
||||||
|
+ int num_leds;
|
||||||
|
+ const struct gpio_led *leds;
|
||||||
|
+ const char *led_name;
|
||||||
|
++
|
||||||
|
++ unsigned num_btns;
|
||||||
|
++ const struct gpio_keys_button *btns;
|
||||||
|
++ unsigned btn_poll_interval;
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+ #endif /* _LINUX_ATH9K_PLATFORM_H */
|
||||||
|
diff --git a/package/kernel/mac80211/patches/549-ath9k_enable_gpio_chip.patch b/package/kernel/mac80211/patches/549-ath9k_enable_gpio_chip.patch
|
||||||
|
deleted file mode 100644
|
||||||
|
index 55bb991..0000000
|
||||||
|
--- a/package/kernel/mac80211/patches/549-ath9k_enable_gpio_chip.patch
|
||||||
|
+++ /dev/null
|
||||||
|
@@ -1,243 +0,0 @@
|
||||||
|
-From: Michal Cieslakiewicz <michal.cieslakiewicz@wp.pl>
|
||||||
|
-Date: Sun, 31 Jan 2016 21:01:31 +0100
|
||||||
|
-Subject: [PATCH v4 4/8] mac80211: ath9k: enable access to GPIO
|
||||||
|
-
|
||||||
|
-Enable access to GPIO chip and its pins for Atheros AR92xx
|
||||||
|
-wireless devices. For now AR9285 and AR9287 are supported.
|
||||||
|
-
|
||||||
|
-Signed-off-by: Michal Cieslakiewicz <michal.cieslakiewicz@wp.pl>
|
||||||
|
----
|
||||||
|
- ath9k.h | 23 ++++++++++++
|
||||||
|
- gpio.c | 121 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
- init.c | 2 +
|
||||||
|
- 3 files changed, 146 insertions(+)
|
||||||
|
-
|
||||||
|
---- a/drivers/net/wireless/ath/ath9k/ath9k.h
|
||||||
|
-+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
|
||||||
|
-@@ -24,6 +24,7 @@
|
||||||
|
- #include <linux/completion.h>
|
||||||
|
- #include <linux/time.h>
|
||||||
|
- #include <linux/hw_random.h>
|
||||||
|
-+#include <linux/gpio/driver.h>
|
||||||
|
-
|
||||||
|
- #include "common.h"
|
||||||
|
- #include "debug.h"
|
||||||
|
-@@ -817,6 +818,13 @@ void ath_fill_led_pin(struct ath_softc *
|
||||||
|
- int ath_create_gpio_led(struct ath_softc *sc, int gpio, const char *name,
|
||||||
|
- const char *trigger, bool active_low);
|
||||||
|
-
|
||||||
|
-+/***************/
|
||||||
|
-+/* GPIO Chip */
|
||||||
|
-+/***************/
|
||||||
|
-+
|
||||||
|
-+void ath9k_register_gpio_chip(struct ath_softc *sc);
|
||||||
|
-+void ath9k_unregister_gpio_chip(struct ath_softc *sc);
|
||||||
|
-+
|
||||||
|
- #else
|
||||||
|
- static inline void ath_init_leds(struct ath_softc *sc)
|
||||||
|
- {
|
||||||
|
-@@ -828,6 +836,14 @@ static inline void ath_deinit_leds(struc
|
||||||
|
- static inline void ath_fill_led_pin(struct ath_softc *sc)
|
||||||
|
- {
|
||||||
|
- }
|
||||||
|
-+
|
||||||
|
-+static inline void ath9k_register_gpio_chip(struct ath_softc *sc)
|
||||||
|
-+{
|
||||||
|
-+}
|
||||||
|
-+
|
||||||
|
-+static inline void ath9k_unregister_gpio_chip(struct ath_softc *sc)
|
||||||
|
-+{
|
||||||
|
-+}
|
||||||
|
- #endif
|
||||||
|
-
|
||||||
|
- /************************/
|
||||||
|
-@@ -963,6 +979,12 @@ struct ath_led {
|
||||||
|
- struct led_classdev cdev;
|
||||||
|
- };
|
||||||
|
-
|
||||||
|
-+struct ath9k_gpio_chip {
|
||||||
|
-+ struct ath_softc *sc;
|
||||||
|
-+ char label[32];
|
||||||
|
-+ struct gpio_chip gchip;
|
||||||
|
-+};
|
||||||
|
-+
|
||||||
|
- struct ath_softc {
|
||||||
|
- struct ieee80211_hw *hw;
|
||||||
|
- struct device *dev;
|
||||||
|
-@@ -1017,6 +1039,7 @@ struct ath_softc {
|
||||||
|
- #ifdef CPTCFG_MAC80211_LEDS
|
||||||
|
- const char *led_default_trigger;
|
||||||
|
- struct list_head leds;
|
||||||
|
-+ struct ath9k_gpio_chip *gpiochip;
|
||||||
|
- #endif
|
||||||
|
-
|
||||||
|
- #ifdef CPTCFG_ATH9K_DEBUGFS
|
||||||
|
---- a/drivers/net/wireless/ath/ath9k/gpio.c
|
||||||
|
-+++ b/drivers/net/wireless/ath/ath9k/gpio.c
|
||||||
|
-@@ -22,6 +22,9 @@
|
||||||
|
- /********************************/
|
||||||
|
-
|
||||||
|
- #ifdef CPTCFG_MAC80211_LEDS
|
||||||
|
-+
|
||||||
|
-+#include <asm-generic/gpio.h>
|
||||||
|
-+
|
||||||
|
- static void ath_led_brightness(struct led_classdev *led_cdev,
|
||||||
|
- enum led_brightness brightness)
|
||||||
|
- {
|
||||||
|
-@@ -60,6 +63,10 @@ static int ath_add_led(struct ath_softc
|
||||||
|
- else
|
||||||
|
- ath9k_hw_set_gpio(sc->sc_ah, gpio->gpio, gpio->active_low);
|
||||||
|
-
|
||||||
|
-+ /* If there is GPIO chip configured, reserve LED pin */
|
||||||
|
-+ if (sc->gpiochip)
|
||||||
|
-+ gpio_request(sc->gpiochip->gchip.base + gpio->gpio, gpio->name);
|
||||||
|
-+
|
||||||
|
- return 0;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
-@@ -116,6 +123,9 @@ void ath_deinit_leds(struct ath_softc *s
|
||||||
|
-
|
||||||
|
- while (!list_empty(&sc->leds)) {
|
||||||
|
- led = list_first_entry(&sc->leds, struct ath_led, list);
|
||||||
|
-+ /* If there is GPIO chip configured, free LED pin */
|
||||||
|
-+ if (sc->gpiochip)
|
||||||
|
-+ gpio_free(sc->gpiochip->gchip.base + led->gpio->gpio);
|
||||||
|
- list_del(&led->list);
|
||||||
|
- ath_led_brightness(&led->cdev, LED_OFF);
|
||||||
|
- led_classdev_unregister(&led->cdev);
|
||||||
|
-@@ -186,6 +196,117 @@ void ath_fill_led_pin(struct ath_softc *
|
||||||
|
- /* LED off, active low */
|
||||||
|
- ath9k_hw_set_gpio(ah, ah->led_pin, (ah->config.led_active_high) ? 0 : 1);
|
||||||
|
- }
|
||||||
|
-+
|
||||||
|
-+/***************/
|
||||||
|
-+/* GPIO Chip */
|
||||||
|
-+/***************/
|
||||||
|
-+
|
||||||
|
-+/* gpio_chip handler : set GPIO to input */
|
||||||
|
-+static int ath9k_gpio_pin_cfg_input(struct gpio_chip *chip, unsigned offset)
|
||||||
|
-+{
|
||||||
|
-+ struct ath9k_gpio_chip *gc = container_of(chip, struct ath9k_gpio_chip,
|
||||||
|
-+ gchip);
|
||||||
|
-+
|
||||||
|
-+ ath9k_hw_cfg_gpio_input(gc->sc->sc_ah, offset);
|
||||||
|
-+
|
||||||
|
-+ return 0;
|
||||||
|
-+}
|
||||||
|
-+
|
||||||
|
-+/* gpio_chip handler : set GPIO to output */
|
||||||
|
-+static int ath9k_gpio_pin_cfg_output(struct gpio_chip *chip, unsigned offset,
|
||||||
|
-+ int value)
|
||||||
|
-+{
|
||||||
|
-+ struct ath9k_gpio_chip *gc = container_of(chip, struct ath9k_gpio_chip,
|
||||||
|
-+ gchip);
|
||||||
|
-+
|
||||||
|
-+ ath9k_hw_cfg_output(gc->sc->sc_ah, offset,
|
||||||
|
-+ AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
|
||||||
|
-+ ath9k_hw_set_gpio(gc->sc->sc_ah, offset, value);
|
||||||
|
-+
|
||||||
|
-+ return 0;
|
||||||
|
-+}
|
||||||
|
-+
|
||||||
|
-+/* gpio_chip handler : query GPIO direction (0=out, 1=in) */
|
||||||
|
-+static int ath9k_gpio_pin_get_dir(struct gpio_chip *chip, unsigned offset)
|
||||||
|
-+{
|
||||||
|
-+ struct ath9k_gpio_chip *gc = container_of(chip, struct ath9k_gpio_chip,
|
||||||
|
-+ gchip);
|
||||||
|
-+ struct ath_hw *ah = gc->sc->sc_ah;
|
||||||
|
-+
|
||||||
|
-+ return !((REG_READ(ah, AR_GPIO_OE_OUT) >> (offset * 2)) & 3);
|
||||||
|
-+}
|
||||||
|
-+
|
||||||
|
-+/* gpio_chip handler : get GPIO pin value */
|
||||||
|
-+static int ath9k_gpio_pin_get(struct gpio_chip *chip, unsigned offset)
|
||||||
|
-+{
|
||||||
|
-+ struct ath9k_gpio_chip *gc = container_of(chip, struct ath9k_gpio_chip,
|
||||||
|
-+ gchip);
|
||||||
|
-+
|
||||||
|
-+ return ath9k_hw_gpio_get(gc->sc->sc_ah, offset);
|
||||||
|
-+}
|
||||||
|
-+
|
||||||
|
-+/* gpio_chip handler : set GPIO pin to value */
|
||||||
|
-+static void ath9k_gpio_pin_set(struct gpio_chip *chip, unsigned offset,
|
||||||
|
-+ int value)
|
||||||
|
-+{
|
||||||
|
-+ struct ath9k_gpio_chip *gc = container_of(chip, struct ath9k_gpio_chip,
|
||||||
|
-+ gchip);
|
||||||
|
-+
|
||||||
|
-+ ath9k_hw_set_gpio(gc->sc->sc_ah, offset, value);
|
||||||
|
-+}
|
||||||
|
-+
|
||||||
|
-+/* register GPIO chip */
|
||||||
|
-+void ath9k_register_gpio_chip(struct ath_softc *sc)
|
||||||
|
-+{
|
||||||
|
-+ struct ath9k_gpio_chip *gc;
|
||||||
|
-+ u16 ng;
|
||||||
|
-+
|
||||||
|
-+ /* for now only AR9285 and AR9287 are recognized */
|
||||||
|
-+ if (AR_SREV_9287(sc->sc_ah))
|
||||||
|
-+ ng = AR9287_NUM_GPIO;
|
||||||
|
-+ else if (AR_SREV_9285(sc->sc_ah))
|
||||||
|
-+ ng = AR9285_NUM_GPIO;
|
||||||
|
-+ else
|
||||||
|
-+ return;
|
||||||
|
-+
|
||||||
|
-+ gc = kzalloc(sizeof(struct ath9k_gpio_chip), GFP_KERNEL);
|
||||||
|
-+ if (!gc)
|
||||||
|
-+ return;
|
||||||
|
-+
|
||||||
|
-+ snprintf(gc->label, sizeof(gc->label), "ath9k-%s",
|
||||||
|
-+ wiphy_name(sc->hw->wiphy));
|
||||||
|
-+ gc->gchip.label = gc->label;
|
||||||
|
-+ gc->gchip.base = -1; /* determine base automatically */
|
||||||
|
-+ gc->gchip.ngpio = ng;
|
||||||
|
-+ gc->gchip.direction_input = ath9k_gpio_pin_cfg_input;
|
||||||
|
-+ gc->gchip.direction_output = ath9k_gpio_pin_cfg_output;
|
||||||
|
-+ gc->gchip.get_direction = ath9k_gpio_pin_get_dir;
|
||||||
|
-+ gc->gchip.get = ath9k_gpio_pin_get;
|
||||||
|
-+ gc->gchip.set = ath9k_gpio_pin_set;
|
||||||
|
-+ gc->gchip.owner = THIS_MODULE;
|
||||||
|
-+
|
||||||
|
-+ if (gpiochip_add(&gc->gchip)) {
|
||||||
|
-+ kfree(gc);
|
||||||
|
-+ return;
|
||||||
|
-+ }
|
||||||
|
-+
|
||||||
|
-+ sc->gpiochip = gc;
|
||||||
|
-+ gc->sc = sc;
|
||||||
|
-+}
|
||||||
|
-+
|
||||||
|
-+/* remove GPIO chip */
|
||||||
|
-+void ath9k_unregister_gpio_chip(struct ath_softc *sc)
|
||||||
|
-+{
|
||||||
|
-+ struct ath9k_gpio_chip *gc = sc->gpiochip;
|
||||||
|
-+
|
||||||
|
-+ if (!gc)
|
||||||
|
-+ return;
|
||||||
|
-+
|
||||||
|
-+ gpiochip_remove(&gc->gchip);
|
||||||
|
-+ kfree(gc);
|
||||||
|
-+ sc->gpiochip = NULL;
|
||||||
|
-+}
|
||||||
|
-+
|
||||||
|
- #endif
|
||||||
|
-
|
||||||
|
- /*******************/
|
||||||
|
---- a/drivers/net/wireless/ath/ath9k/init.c
|
||||||
|
-+++ b/drivers/net/wireless/ath/ath9k/init.c
|
||||||
|
-@@ -975,6 +975,7 @@ int ath9k_init_device(u16 devid, struct
|
||||||
|
- goto debug_cleanup;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
-+ ath9k_register_gpio_chip(sc);
|
||||||
|
- ath_init_leds(sc);
|
||||||
|
- ath_start_rfkill_poll(sc);
|
||||||
|
-
|
||||||
|
-@@ -1022,6 +1023,7 @@ void ath9k_deinit_device(struct ath_soft
|
||||||
|
-
|
||||||
|
- wiphy_rfkill_stop_polling(sc->hw->wiphy);
|
||||||
|
- ath_deinit_leds(sc);
|
||||||
|
-+ ath9k_unregister_gpio_chip(sc);
|
||||||
|
-
|
||||||
|
- ath9k_ps_restore(sc);
|
||||||
|
-
|
||||||
|
diff --git a/package/kernel/mac80211/patches/550-ath9k_enable_gpio_buttons.patch b/package/kernel/mac80211/patches/550-ath9k_enable_gpio_buttons.patch
|
||||||
|
deleted file mode 100644
|
||||||
|
index e3a8cec..0000000
|
||||||
|
--- a/package/kernel/mac80211/patches/550-ath9k_enable_gpio_buttons.patch
|
||||||
|
+++ /dev/null
|
||||||
|
@@ -1,169 +0,0 @@
|
||||||
|
-From: Michal Cieslakiewicz <michal.cieslakiewicz@wp.pl>
|
||||||
|
-Subject: [PATCH v5 5/8] mac80211: ath9k: enable GPIO buttons
|
||||||
|
-
|
||||||
|
-Enable platform-defined GPIO button support for ath9k device.
|
||||||
|
-Key poller is activated for attached platform buttons.
|
||||||
|
-Requires ath9k GPIO chip access.
|
||||||
|
-
|
||||||
|
-Signed-off-by: Michal Cieslakiewicz <michal.cieslakiewicz@wp.pl>
|
||||||
|
----
|
||||||
|
- drivers/net/wireless/ath/ath9k/ath9k.h | 16 ++++++
|
||||||
|
- drivers/net/wireless/ath/ath9k/gpio.c | 77 +++++++++++++++++++++++++++++++++
|
||||||
|
- drivers/net/wireless/ath/ath9k/init.c | 2
|
||||||
|
- include/linux/ath9k_platform.h | 4 +
|
||||||
|
- 4 files changed, 99 insertions(+)
|
||||||
|
-
|
||||||
|
---- a/drivers/net/wireless/ath/ath9k/ath9k.h
|
||||||
|
-+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
|
||||||
|
-@@ -825,6 +825,13 @@ int ath_create_gpio_led(struct ath_softc
|
||||||
|
- void ath9k_register_gpio_chip(struct ath_softc *sc);
|
||||||
|
- void ath9k_unregister_gpio_chip(struct ath_softc *sc);
|
||||||
|
-
|
||||||
|
-+/******************/
|
||||||
|
-+/* GPIO Buttons */
|
||||||
|
-+/******************/
|
||||||
|
-+
|
||||||
|
-+void ath9k_init_buttons(struct ath_softc *sc);
|
||||||
|
-+void ath9k_deinit_buttons(struct ath_softc *sc);
|
||||||
|
-+
|
||||||
|
- #else
|
||||||
|
- static inline void ath_init_leds(struct ath_softc *sc)
|
||||||
|
- {
|
||||||
|
-@@ -844,6 +851,14 @@ static inline void ath9k_register_gpio_c
|
||||||
|
- static inline void ath9k_unregister_gpio_chip(struct ath_softc *sc)
|
||||||
|
- {
|
||||||
|
- }
|
||||||
|
-+
|
||||||
|
-+static inline void ath9k_init_buttons(struct ath_softc *sc)
|
||||||
|
-+{
|
||||||
|
-+}
|
||||||
|
-+
|
||||||
|
-+static inline void ath9k_deinit_buttons(struct ath_softc *sc)
|
||||||
|
-+{
|
||||||
|
-+}
|
||||||
|
- #endif
|
||||||
|
-
|
||||||
|
- /************************/
|
||||||
|
-@@ -1040,6 +1055,7 @@ struct ath_softc {
|
||||||
|
- const char *led_default_trigger;
|
||||||
|
- struct list_head leds;
|
||||||
|
- struct ath9k_gpio_chip *gpiochip;
|
||||||
|
-+ struct platform_device *btnpdev; /* gpio-keys-polled */
|
||||||
|
- #endif
|
||||||
|
-
|
||||||
|
- #ifdef CPTCFG_ATH9K_DEBUGFS
|
||||||
|
---- a/drivers/net/wireless/ath/ath9k/gpio.c
|
||||||
|
-+++ b/drivers/net/wireless/ath/ath9k/gpio.c
|
||||||
|
-@@ -24,6 +24,8 @@
|
||||||
|
- #ifdef CPTCFG_MAC80211_LEDS
|
||||||
|
-
|
||||||
|
- #include <asm-generic/gpio.h>
|
||||||
|
-+#include <linux/platform_device.h>
|
||||||
|
-+#include <linux/gpio_keys.h>
|
||||||
|
-
|
||||||
|
- static void ath_led_brightness(struct led_classdev *led_cdev,
|
||||||
|
- enum led_brightness brightness)
|
||||||
|
-@@ -159,7 +161,7 @@ void ath_init_leds(struct ath_softc *sc)
|
||||||
|
- ath_create_gpio_led(sc, sc->sc_ah->led_pin, led_name, trigger,
|
||||||
|
- !sc->sc_ah->config.led_active_high);
|
||||||
|
-
|
||||||
|
-- if (!pdata)
|
||||||
|
-+ if (!pdata || !pdata->leds || !pdata->num_leds)
|
||||||
|
- return;
|
||||||
|
-
|
||||||
|
- for (i = 0; i < pdata->num_leds; i++)
|
||||||
|
-@@ -307,6 +309,63 @@ void ath9k_unregister_gpio_chip(struct a
|
||||||
|
- sc->gpiochip = NULL;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
-+/******************/
|
||||||
|
-+/* GPIO Buttons */
|
||||||
|
-+/******************/
|
||||||
|
-+
|
||||||
|
-+/* add GPIO buttons */
|
||||||
|
-+void ath9k_init_buttons(struct ath_softc *sc)
|
||||||
|
-+{
|
||||||
|
-+ struct ath9k_platform_data *pdata = sc->dev->platform_data;
|
||||||
|
-+ struct platform_device *pdev;
|
||||||
|
-+ struct gpio_keys_platform_data gkpdata;
|
||||||
|
-+ struct gpio_keys_button *bt;
|
||||||
|
-+ int i;
|
||||||
|
-+
|
||||||
|
-+ if (!sc->gpiochip)
|
||||||
|
-+ return;
|
||||||
|
-+
|
||||||
|
-+ if (!pdata || !pdata->btns || !pdata->num_btns)
|
||||||
|
-+ return;
|
||||||
|
-+
|
||||||
|
-+ bt = devm_kmemdup(sc->dev, pdata->btns,
|
||||||
|
-+ pdata->num_btns * sizeof(struct gpio_keys_button),
|
||||||
|
-+ GFP_KERNEL);
|
||||||
|
-+ if (!bt)
|
||||||
|
-+ return;
|
||||||
|
-+
|
||||||
|
-+ for (i = 0; i < pdata->num_btns; i++) {
|
||||||
|
-+ ath9k_hw_cfg_gpio_input(sc->sc_ah, pdata->btns[i].gpio);
|
||||||
|
-+ bt[i].gpio = sc->gpiochip->gchip.base + pdata->btns[i].gpio;
|
||||||
|
-+ }
|
||||||
|
-+
|
||||||
|
-+ memset(&gkpdata, 0, sizeof(struct gpio_keys_platform_data));
|
||||||
|
-+ gkpdata.buttons = bt;
|
||||||
|
-+ gkpdata.nbuttons = pdata->num_btns;
|
||||||
|
-+ gkpdata.poll_interval = pdata->btn_poll_interval;
|
||||||
|
-+
|
||||||
|
-+ pdev = platform_device_register_data(sc->dev, "gpio-keys-polled",
|
||||||
|
-+ PLATFORM_DEVID_AUTO, &gkpdata,
|
||||||
|
-+ sizeof(gkpdata));
|
||||||
|
-+ if (!IS_ERR_OR_NULL(pdev))
|
||||||
|
-+ sc->btnpdev = pdev;
|
||||||
|
-+ else {
|
||||||
|
-+ sc->btnpdev = NULL;
|
||||||
|
-+ devm_kfree(sc->dev, bt);
|
||||||
|
-+ }
|
||||||
|
-+}
|
||||||
|
-+
|
||||||
|
-+/* remove GPIO buttons */
|
||||||
|
-+void ath9k_deinit_buttons(struct ath_softc *sc)
|
||||||
|
-+{
|
||||||
|
-+ if (!sc->gpiochip || !sc->btnpdev)
|
||||||
|
-+ return;
|
||||||
|
-+
|
||||||
|
-+ platform_device_unregister(sc->btnpdev);
|
||||||
|
-+
|
||||||
|
-+ sc->btnpdev = NULL;
|
||||||
|
-+}
|
||||||
|
-+
|
||||||
|
- #endif
|
||||||
|
-
|
||||||
|
- /*******************/
|
||||||
|
---- a/drivers/net/wireless/ath/ath9k/init.c
|
||||||
|
-+++ b/drivers/net/wireless/ath/ath9k/init.c
|
||||||
|
-@@ -977,6 +977,7 @@ int ath9k_init_device(u16 devid, struct
|
||||||
|
-
|
||||||
|
- ath9k_register_gpio_chip(sc);
|
||||||
|
- ath_init_leds(sc);
|
||||||
|
-+ ath9k_init_buttons(sc);
|
||||||
|
- ath_start_rfkill_poll(sc);
|
||||||
|
-
|
||||||
|
- return 0;
|
||||||
|
-@@ -1022,6 +1023,7 @@ void ath9k_deinit_device(struct ath_soft
|
||||||
|
- ath9k_ps_wakeup(sc);
|
||||||
|
-
|
||||||
|
- wiphy_rfkill_stop_polling(sc->hw->wiphy);
|
||||||
|
-+ ath9k_deinit_buttons(sc);
|
||||||
|
- ath_deinit_leds(sc);
|
||||||
|
- ath9k_unregister_gpio_chip(sc);
|
||||||
|
-
|
||||||
|
---- a/include/linux/ath9k_platform.h
|
||||||
|
-+++ b/include/linux/ath9k_platform.h
|
||||||
|
-@@ -46,6 +46,10 @@ struct ath9k_platform_data {
|
||||||
|
- int num_leds;
|
||||||
|
- const struct gpio_led *leds;
|
||||||
|
- const char *led_name;
|
||||||
|
-+
|
||||||
|
-+ unsigned num_btns;
|
||||||
|
-+ const struct gpio_keys_button *btns;
|
||||||
|
-+ unsigned btn_poll_interval;
|
||||||
|
- };
|
||||||
|
-
|
||||||
|
- #endif /* _LINUX_ATH9K_PLATFORM_H */
|
@ -6,7 +6,7 @@ Patch-by: Stefan Rompf <stefan@loplof.de>
|
|||||||
|
|
||||||
diff --git a/package/kernel/mac80211/patches/931-ubnt-uap-plus-hsr.patch b/package/kernel/mac80211/patches/931-ubnt-uap-plus-hsr.patch
|
diff --git a/package/kernel/mac80211/patches/931-ubnt-uap-plus-hsr.patch b/package/kernel/mac80211/patches/931-ubnt-uap-plus-hsr.patch
|
||||||
new file mode 100644
|
new file mode 100644
|
||||||
index 0000000..4533335
|
index 0000000..14d63f1
|
||||||
--- /dev/null
|
--- /dev/null
|
||||||
+++ b/package/kernel/mac80211/patches/931-ubnt-uap-plus-hsr.patch
|
+++ b/package/kernel/mac80211/patches/931-ubnt-uap-plus-hsr.patch
|
||||||
@@ -0,0 +1,346 @@
|
@@ -0,0 +1,346 @@
|
||||||
@ -347,10 +347,10 @@ index 0000000..4533335
|
|||||||
+ ath9k-$(CPTCFG_ATH9K_PCI) += pci.o
|
+ ath9k-$(CPTCFG_ATH9K_PCI) += pci.o
|
||||||
+--- a/include/linux/ath9k_platform.h
|
+--- a/include/linux/ath9k_platform.h
|
||||||
++++ b/include/linux/ath9k_platform.h
|
++++ b/include/linux/ath9k_platform.h
|
||||||
+@@ -44,6 +44,8 @@ struct ath9k_platform_data {
|
+@@ -50,6 +50,8 @@ struct ath9k_platform_data {
|
||||||
+
|
+ unsigned num_btns;
|
||||||
+ int num_leds;
|
+ const struct gpio_keys_button *btns;
|
||||||
+ const struct gpio_led *leds;
|
+ unsigned btn_poll_interval;
|
||||||
++
|
++
|
||||||
++ bool ubnt_hsr;
|
++ bool ubnt_hsr;
|
||||||
+ };
|
+ };
|
||||||
@ -368,25 +368,16 @@ index 7803513..d865ed2 100644
|
|||||||
+ ap91_pci_init(ee, NULL);
|
+ ap91_pci_init(ee, NULL);
|
||||||
+
|
+
|
||||||
+ ath79_register_leds_gpio(-1, ARRAY_SIZE(ubnt_unifi_outdoor_plus_leds_gpio),
|
+ ath79_register_leds_gpio(-1, ARRAY_SIZE(ubnt_unifi_outdoor_plus_leds_gpio),
|
||||||
diff --git a/target/linux/generic/patches-3.18/150-ath9k_ubnt_hsr_filter.patch b/target/linux/generic/patches-3.18/150-ath9k_ubnt_hsr_filter.patch
|
diff --git a/target/linux/generic/files/include/linux/ath9k_platform.h b/target/linux/generic/files/include/linux/ath9k_platform.h
|
||||||
new file mode 100644
|
index e543a64..2cb0288 100644
|
||||||
index 0000000..a0ebbc7
|
--- a/target/linux/generic/files/include/linux/ath9k_platform.h
|
||||||
--- /dev/null
|
+++ b/target/linux/generic/files/include/linux/ath9k_platform.h
|
||||||
+++ b/target/linux/generic/patches-3.18/150-ath9k_ubnt_hsr_filter.patch
|
@@ -50,6 +50,8 @@ struct ath9k_platform_data {
|
||||||
@@ -0,0 +1,16 @@
|
unsigned num_btns;
|
||||||
+Flag that this platform is an Ubiquiti UniFi Outdoor Plus
|
const struct gpio_keys_button *btns;
|
||||||
+containing a RF filter in ath9k's receive path.
|
unsigned btn_poll_interval;
|
||||||
+
|
+
|
||||||
+Signed-off-by: Stefan Rompf <stefan@loplof.de>
|
+ bool ubnt_hsr;
|
||||||
+
|
};
|
||||||
+--- a/include/linux/ath9k_platform.h
|
|
||||||
++++ b/include/linux/ath9k_platform.h
|
#endif /* _LINUX_ATH9K_PLATFORM_H */
|
||||||
+@@ -44,6 +44,8 @@ struct ath9k_platform_data {
|
|
||||||
+
|
|
||||||
+ int num_leds;
|
|
||||||
+ const struct gpio_led *leds;
|
|
||||||
++
|
|
||||||
++ bool ubnt_hsr;
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ #endif /* _LINUX_ATH9K_PLATFORM_H */
|
|
Loading…
Reference in New Issue
Block a user