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> SVN-Revision: 48921
This commit is contained in:
		@@ -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 */
 | 
			
		||||
@@ -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)) {
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
 
 | 
			
		||||
@@ -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 */
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user