OpenWrt – Blame information for rev 4
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
4 | office | 1 | From: Michal Cieslakiewicz <michal.cieslakiewicz@wp.pl> |
2 | Subject: [PATCH v5 5/8] mac80211: ath9k: enable GPIO buttons |
||
3 | |||
4 | Enable platform-defined GPIO button support for ath9k device. |
||
5 | Key poller is activated for attached platform buttons. |
||
6 | Requires ath9k GPIO chip access. |
||
7 | |||
8 | Signed-off-by: Michal Cieslakiewicz <michal.cieslakiewicz@wp.pl> |
||
9 | Signed-off-by: Felix Fietkau <nbd@nbd.name> |
||
10 | --- |
||
11 | --- a/drivers/net/wireless/ath/ath9k/ath9k.h |
||
12 | +++ b/drivers/net/wireless/ath/ath9k/ath9k.h |
||
13 | @@ -1069,6 +1069,7 @@ struct ath_softc { |
||
14 | struct list_head leds; |
||
15 | #ifdef CONFIG_GPIOLIB |
||
16 | struct ath9k_gpio_chip *gpiochip; |
||
17 | + struct platform_device *btnpdev; /* gpio-keys-polled */ |
||
18 | #endif |
||
19 | #endif |
||
20 | |||
21 | --- a/drivers/net/wireless/ath/ath9k/gpio.c |
||
22 | +++ b/drivers/net/wireless/ath/ath9k/gpio.c |
||
23 | @@ -17,6 +17,8 @@ |
||
24 | #include "ath9k.h" |
||
25 | #include <linux/ath9k_platform.h> |
||
26 | #include <linux/gpio.h> |
||
27 | +#include <linux/platform_device.h> |
||
28 | +#include <linux/gpio_keys.h> |
||
29 | |||
30 | #ifdef CPTCFG_MAC80211_LEDS |
||
31 | |||
32 | @@ -129,6 +131,67 @@ static void ath9k_unregister_gpio_chip(s |
||
33 | sc->gpiochip = NULL; |
||
34 | } |
||
35 | |||
36 | +/******************/ |
||
37 | +/* GPIO Buttons */ |
||
38 | +/******************/ |
||
39 | + |
||
40 | +/* add GPIO buttons */ |
||
41 | +static void ath9k_init_buttons(struct ath_softc *sc) |
||
42 | +{ |
||
43 | + struct ath9k_platform_data *pdata = sc->dev->platform_data; |
||
44 | + struct platform_device *pdev; |
||
45 | + struct gpio_keys_platform_data gkpdata; |
||
46 | + struct gpio_keys_button *bt; |
||
47 | + int i; |
||
48 | + |
||
49 | + if (!sc->gpiochip) |
||
50 | + return; |
||
51 | + |
||
52 | + if (!pdata || !pdata->btns || !pdata->num_btns) |
||
53 | + return; |
||
54 | + |
||
55 | + bt = devm_kmemdup(sc->dev, pdata->btns, |
||
56 | + pdata->num_btns * sizeof(struct gpio_keys_button), |
||
57 | + GFP_KERNEL); |
||
58 | + if (!bt) |
||
59 | + return; |
||
60 | + |
||
61 | + for (i = 0; i < pdata->num_btns; i++) { |
||
62 | + if (pdata->btns[i].gpio == sc->sc_ah->led_pin) |
||
63 | + sc->sc_ah->led_pin = -1; |
||
64 | + |
||
65 | + ath9k_hw_gpio_request_in(sc->sc_ah, pdata->btns[i].gpio, |
||
66 | + "ath9k-gpio"); |
||
67 | + bt[i].gpio = sc->gpiochip->gchip.base + pdata->btns[i].gpio; |
||
68 | + } |
||
69 | + |
||
70 | + memset(&gkpdata, 0, sizeof(struct gpio_keys_platform_data)); |
||
71 | + gkpdata.buttons = bt; |
||
72 | + gkpdata.nbuttons = pdata->num_btns; |
||
73 | + gkpdata.poll_interval = pdata->btn_poll_interval; |
||
74 | + |
||
75 | + pdev = platform_device_register_data(sc->dev, "gpio-keys-polled", |
||
76 | + PLATFORM_DEVID_AUTO, &gkpdata, |
||
77 | + sizeof(gkpdata)); |
||
78 | + if (!IS_ERR_OR_NULL(pdev)) |
||
79 | + sc->btnpdev = pdev; |
||
80 | + else { |
||
81 | + sc->btnpdev = NULL; |
||
82 | + devm_kfree(sc->dev, bt); |
||
83 | + } |
||
84 | +} |
||
85 | + |
||
86 | +/* remove GPIO buttons */ |
||
87 | +static void ath9k_deinit_buttons(struct ath_softc *sc) |
||
88 | +{ |
||
89 | + if (!sc->gpiochip || !sc->btnpdev) |
||
90 | + return; |
||
91 | + |
||
92 | + platform_device_unregister(sc->btnpdev); |
||
93 | + |
||
94 | + sc->btnpdev = NULL; |
||
95 | +} |
||
96 | + |
||
97 | #else /* CONFIG_GPIOLIB */ |
||
98 | |||
99 | static inline void ath9k_register_gpio_chip(struct ath_softc *sc) |
||
100 | @@ -139,6 +202,14 @@ static inline void ath9k_unregister_gpio |
||
101 | { |
||
102 | } |
||
103 | |||
104 | +static inline void ath9k_init_buttons(struct ath_softc *sc) |
||
105 | +{ |
||
106 | +} |
||
107 | + |
||
108 | +static inline void ath9k_deinit_buttons(struct ath_softc *sc) |
||
109 | +{ |
||
110 | +} |
||
111 | + |
||
112 | #endif /* CONFIG_GPIOLIB */ |
||
113 | |||
114 | /********************************/ |
||
115 | @@ -262,6 +333,7 @@ void ath_deinit_leds(struct ath_softc *s |
||
116 | { |
||
117 | struct ath_led *led; |
||
118 | |||
119 | + ath9k_deinit_buttons(sc); |
||
120 | while (!list_empty(&sc->leds)) { |
||
121 | led = list_first_entry(&sc->leds, struct ath_led, list); |
||
122 | #ifdef CONFIG_GPIOLIB |
||
123 | @@ -301,6 +373,7 @@ void ath_init_leds(struct ath_softc *sc) |
||
124 | } |
||
125 | |||
126 | ath_fill_led_pin(sc); |
||
127 | + ath9k_init_buttons(sc); |
||
128 | |||
129 | if (pdata && pdata->leds && pdata->num_leds) |
||
130 | for (i = 0; i < pdata->num_leds; i++) { |
||
131 | --- a/include/linux/ath9k_platform.h |
||
132 | +++ b/include/linux/ath9k_platform.h |
||
133 | @@ -49,6 +49,10 @@ struct ath9k_platform_data { |
||
134 | |||
135 | int num_leds; |
||
136 | const struct gpio_led *leds; |
||
137 | + |
||
138 | + unsigned num_btns; |
||
139 | + const struct gpio_keys_button *btns; |
||
140 | + unsigned btn_poll_interval; |
||
141 | }; |
||
142 | |||
143 | #endif /* _LINUX_ATH9K_PLATFORM_H */ |