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