7b7ea91e24
This enables ath9k's built-in GPIO controller for all chip versions (instead of an explicit whitelist). This also allows us to get rid of some duplicate code between hw.c and gpio.c because hw.c already determines the number of GPIOs. Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
149 lines
3.8 KiB
Diff
149 lines
3.8 KiB
Diff
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@nbd.name>
|
|
---
|
|
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
|
|
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
|
|
@@ -1024,6 +1024,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
|
|
|
|
@@ -124,6 +126,64 @@ 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_gpio_request_in(sc->sc_ah, pdata->btns[i].gpio,
|
|
+ "ath9k-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)
|
|
@@ -134,6 +194,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 */
|
|
|
|
/********************************/
|
|
@@ -257,6 +325,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
|
|
@@ -288,6 +357,7 @@ void ath_init_leds(struct ath_softc *sc)
|
|
ath_fill_led_pin(sc);
|
|
|
|
ath9k_register_gpio_chip(sc);
|
|
+ ath9k_init_buttons(sc);
|
|
|
|
if (pdata && pdata->led_name)
|
|
strncpy(led_name, pdata->led_name, sizeof(led_name));
|
|
@@ -303,7 +373,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
|
|
@@ -50,6 +50,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 */
|