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
 | ||||
| new file mode 100644 | ||||
| index 0000000..4533335
 | ||||
| index 0000000..14d63f1
 | ||||
| --- /dev/null
 | ||||
| +++ b/package/kernel/mac80211/patches/931-ubnt-uap-plus-hsr.patch
 | ||||
| @@ -0,0 +1,346 @@
 | ||||
| @ -347,10 +347,10 @@ index 0000000..4533335 | ||||
| + ath9k-$(CPTCFG_ATH9K_PCI) += pci.o
 | ||||
| +--- a/include/linux/ath9k_platform.h
 | ||||
| ++++ b/include/linux/ath9k_platform.h
 | ||||
| +@@ -44,6 +44,8 @@ struct ath9k_platform_data {
 | ||||
| + 
 | ||||
| + 	int num_leds;
 | ||||
| + 	const struct gpio_led *leds;
 | ||||
| +@@ -50,6 +50,8 @@ struct ath9k_platform_data {
 | ||||
| + 	unsigned num_btns;
 | ||||
| + 	const struct gpio_keys_button *btns;
 | ||||
| + 	unsigned btn_poll_interval;
 | ||||
| ++
 | ||||
| ++	bool ubnt_hsr;
 | ||||
| + };
 | ||||
| @ -368,25 +368,16 @@ index 7803513..d865ed2 100644 | ||||
|  +	ap91_pci_init(ee, NULL); | ||||
|  + | ||||
|  +	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
 | ||||
| new file mode 100644 | ||||
| index 0000000..a0ebbc7
 | ||||
| --- /dev/null
 | ||||
| +++ b/target/linux/generic/patches-3.18/150-ath9k_ubnt_hsr_filter.patch
 | ||||
| @@ -0,0 +1,16 @@
 | ||||
| +Flag that this platform is an Ubiquiti UniFi Outdoor Plus
 | ||||
| +containing a RF filter in ath9k's receive path.
 | ||||
| diff --git a/target/linux/generic/files/include/linux/ath9k_platform.h b/target/linux/generic/files/include/linux/ath9k_platform.h
 | ||||
| index e543a64..2cb0288 100644
 | ||||
| --- a/target/linux/generic/files/include/linux/ath9k_platform.h
 | ||||
| +++ b/target/linux/generic/files/include/linux/ath9k_platform.h
 | ||||
| @@ -50,6 +50,8 @@ struct ath9k_platform_data {
 | ||||
|  	unsigned num_btns; | ||||
|  	const struct gpio_keys_button *btns; | ||||
|  	unsigned btn_poll_interval; | ||||
| +
 | ||||
| +Signed-off-by: Stefan Rompf <stefan@loplof.de>
 | ||||
| +
 | ||||
| +--- a/include/linux/ath9k_platform.h
 | ||||
| ++++ b/include/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 */
 | ||||
| +	bool ubnt_hsr;
 | ||||
|  }; | ||||
|   | ||||
|  #endif /* _LINUX_ATH9K_PLATFORM_H */ | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user