0085-mac80211-rework-gpio-chip-button-support-to-build-on-platforms-without-CONFIG_GPIOLIB.patch 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827
  1. From: Matthias Schiffer <mschiffer@universe-factory.net>
  2. Date: Sun, 29 May 2016 13:39:10 +0200
  3. Subject: mac80211: rework gpio chip/button support to build on platforms without CONFIG_GPIOLIB
  4. Signed-off-by: Felix Fietkau <nbd@openwrt.org>
  5. Backport of r48938
  6. diff --git a/package/kernel/mac80211/patches/548-ath9k_enable_gpio_chip.patch b/package/kernel/mac80211/patches/548-ath9k_enable_gpio_chip.patch
  7. new file mode 100644
  8. index 0000000..f91d85c
  9. --- /dev/null
  10. +++ b/package/kernel/mac80211/patches/548-ath9k_enable_gpio_chip.patch
  11. @@ -0,0 +1,235 @@
  12. +From: Michal Cieslakiewicz <michal.cieslakiewicz@wp.pl>
  13. +Date: Sun, 31 Jan 2016 21:01:31 +0100
  14. +Subject: [PATCH v4 4/8] mac80211: ath9k: enable access to GPIO
  15. +
  16. +Enable access to GPIO chip and its pins for Atheros AR92xx
  17. +wireless devices. For now AR9285 and AR9287 are supported.
  18. +
  19. +Signed-off-by: Michal Cieslakiewicz <michal.cieslakiewicz@wp.pl>
  20. +Signed-off-by: Felix Fietkau <nbd@openwrt.org>
  21. +---
  22. +--- a/drivers/net/wireless/ath/ath9k/ath9k.h
  23. ++++ b/drivers/net/wireless/ath/ath9k/ath9k.h
  24. +@@ -24,6 +24,7 @@
  25. + #include <linux/completion.h>
  26. + #include <linux/time.h>
  27. + #include <linux/hw_random.h>
  28. ++#include <linux/gpio/driver.h>
  29. +
  30. + #include "common.h"
  31. + #include "debug.h"
  32. +@@ -963,6 +964,14 @@ struct ath_led {
  33. + struct led_classdev cdev;
  34. + };
  35. +
  36. ++#ifdef CONFIG_GPIOLIB
  37. ++struct ath9k_gpio_chip {
  38. ++ struct ath_softc *sc;
  39. ++ char label[32];
  40. ++ struct gpio_chip gchip;
  41. ++};
  42. ++#endif
  43. ++
  44. + struct ath_softc {
  45. + struct ieee80211_hw *hw;
  46. + struct device *dev;
  47. +@@ -1017,6 +1026,9 @@ struct ath_softc {
  48. + #ifdef CPTCFG_MAC80211_LEDS
  49. + const char *led_default_trigger;
  50. + struct list_head leds;
  51. ++#ifdef CONFIG_GPIOLIB
  52. ++ struct ath9k_gpio_chip *gpiochip;
  53. ++#endif
  54. + #endif
  55. +
  56. + #ifdef CPTCFG_ATH9K_DEBUGFS
  57. +--- a/drivers/net/wireless/ath/ath9k/gpio.c
  58. ++++ b/drivers/net/wireless/ath/ath9k/gpio.c
  59. +@@ -16,12 +16,138 @@
  60. +
  61. + #include "ath9k.h"
  62. + #include <linux/ath9k_platform.h>
  63. ++#include <linux/gpio.h>
  64. ++
  65. ++#ifdef CPTCFG_MAC80211_LEDS
  66. ++
  67. ++#ifdef CONFIG_GPIOLIB
  68. ++
  69. ++/***************/
  70. ++/* GPIO Chip */
  71. ++/***************/
  72. ++
  73. ++/* gpio_chip handler : set GPIO to input */
  74. ++static int ath9k_gpio_pin_cfg_input(struct gpio_chip *chip, unsigned offset)
  75. ++{
  76. ++ struct ath9k_gpio_chip *gc = container_of(chip, struct ath9k_gpio_chip,
  77. ++ gchip);
  78. ++
  79. ++ ath9k_hw_cfg_gpio_input(gc->sc->sc_ah, offset);
  80. ++
  81. ++ return 0;
  82. ++}
  83. ++
  84. ++/* gpio_chip handler : set GPIO to output */
  85. ++static int ath9k_gpio_pin_cfg_output(struct gpio_chip *chip, unsigned offset,
  86. ++ int value)
  87. ++{
  88. ++ struct ath9k_gpio_chip *gc = container_of(chip, struct ath9k_gpio_chip,
  89. ++ gchip);
  90. ++
  91. ++ ath9k_hw_cfg_output(gc->sc->sc_ah, offset,
  92. ++ AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
  93. ++ ath9k_hw_set_gpio(gc->sc->sc_ah, offset, value);
  94. ++
  95. ++ return 0;
  96. ++}
  97. ++
  98. ++/* gpio_chip handler : query GPIO direction (0=out, 1=in) */
  99. ++static int ath9k_gpio_pin_get_dir(struct gpio_chip *chip, unsigned offset)
  100. ++{
  101. ++ struct ath9k_gpio_chip *gc = container_of(chip, struct ath9k_gpio_chip,
  102. ++ gchip);
  103. ++ struct ath_hw *ah = gc->sc->sc_ah;
  104. ++
  105. ++ return !((REG_READ(ah, AR_GPIO_OE_OUT) >> (offset * 2)) & 3);
  106. ++}
  107. ++
  108. ++/* gpio_chip handler : get GPIO pin value */
  109. ++static int ath9k_gpio_pin_get(struct gpio_chip *chip, unsigned offset)
  110. ++{
  111. ++ struct ath9k_gpio_chip *gc = container_of(chip, struct ath9k_gpio_chip,
  112. ++ gchip);
  113. ++
  114. ++ return ath9k_hw_gpio_get(gc->sc->sc_ah, offset);
  115. ++}
  116. ++
  117. ++/* gpio_chip handler : set GPIO pin to value */
  118. ++static void ath9k_gpio_pin_set(struct gpio_chip *chip, unsigned offset,
  119. ++ int value)
  120. ++{
  121. ++ struct ath9k_gpio_chip *gc = container_of(chip, struct ath9k_gpio_chip,
  122. ++ gchip);
  123. ++
  124. ++ ath9k_hw_set_gpio(gc->sc->sc_ah, offset, value);
  125. ++}
  126. ++
  127. ++/* register GPIO chip */
  128. ++static void ath9k_register_gpio_chip(struct ath_softc *sc)
  129. ++{
  130. ++ struct ath9k_gpio_chip *gc;
  131. ++ u16 ng;
  132. ++
  133. ++ /* for now only AR9285 and AR9287 are recognized */
  134. ++ if (AR_SREV_9287(sc->sc_ah))
  135. ++ ng = AR9287_NUM_GPIO;
  136. ++ else if (AR_SREV_9285(sc->sc_ah))
  137. ++ ng = AR9285_NUM_GPIO;
  138. ++ else
  139. ++ return;
  140. ++
  141. ++ gc = kzalloc(sizeof(struct ath9k_gpio_chip), GFP_KERNEL);
  142. ++ if (!gc)
  143. ++ return;
  144. ++
  145. ++ snprintf(gc->label, sizeof(gc->label), "ath9k-%s",
  146. ++ wiphy_name(sc->hw->wiphy));
  147. ++ gc->gchip.label = gc->label;
  148. ++ gc->gchip.base = -1; /* determine base automatically */
  149. ++ gc->gchip.ngpio = ng;
  150. ++ gc->gchip.direction_input = ath9k_gpio_pin_cfg_input;
  151. ++ gc->gchip.direction_output = ath9k_gpio_pin_cfg_output;
  152. ++ gc->gchip.get_direction = ath9k_gpio_pin_get_dir;
  153. ++ gc->gchip.get = ath9k_gpio_pin_get;
  154. ++ gc->gchip.set = ath9k_gpio_pin_set;
  155. ++ gc->gchip.owner = THIS_MODULE;
  156. ++
  157. ++ if (gpiochip_add(&gc->gchip)) {
  158. ++ kfree(gc);
  159. ++ return;
  160. ++ }
  161. ++
  162. ++ sc->gpiochip = gc;
  163. ++ gc->sc = sc;
  164. ++}
  165. ++
  166. ++/* remove GPIO chip */
  167. ++static void ath9k_unregister_gpio_chip(struct ath_softc *sc)
  168. ++{
  169. ++ struct ath9k_gpio_chip *gc = sc->gpiochip;
  170. ++
  171. ++ if (!gc)
  172. ++ return;
  173. ++
  174. ++ gpiochip_remove(&gc->gchip);
  175. ++ kfree(gc);
  176. ++ sc->gpiochip = NULL;
  177. ++}
  178. ++
  179. ++#else /* CONFIG_GPIOLIB */
  180. ++
  181. ++static inline void ath9k_register_gpio_chip(struct ath_softc *sc)
  182. ++{
  183. ++}
  184. ++
  185. ++static inline void ath9k_unregister_gpio_chip(struct ath_softc *sc)
  186. ++{
  187. ++}
  188. ++
  189. ++#endif /* CONFIG_GPIOLIB */
  190. +
  191. + /********************************/
  192. + /* LED functions */
  193. + /********************************/
  194. +
  195. +-#ifdef CPTCFG_MAC80211_LEDS
  196. + static void ath_led_brightness(struct led_classdev *led_cdev,
  197. + enum led_brightness brightness)
  198. + {
  199. +@@ -60,6 +186,12 @@ static int ath_add_led(struct ath_softc
  200. + else
  201. + ath9k_hw_set_gpio(sc->sc_ah, gpio->gpio, gpio->active_low);
  202. +
  203. ++#ifdef CONFIG_GPIOLIB
  204. ++ /* If there is GPIO chip configured, reserve LED pin */
  205. ++ if (sc->gpiochip)
  206. ++ gpio_request(sc->gpiochip->gchip.base + gpio->gpio, gpio->name);
  207. ++#endif
  208. ++
  209. + return 0;
  210. + }
  211. +
  212. +@@ -116,11 +248,17 @@ void ath_deinit_leds(struct ath_softc *s
  213. +
  214. + while (!list_empty(&sc->leds)) {
  215. + led = list_first_entry(&sc->leds, struct ath_led, list);
  216. ++#ifdef CONFIG_GPIOLIB
  217. ++ /* If there is GPIO chip configured, free LED pin */
  218. ++ if (sc->gpiochip)
  219. ++ gpio_free(sc->gpiochip->gchip.base + led->gpio->gpio);
  220. ++#endif
  221. + list_del(&led->list);
  222. + ath_led_brightness(&led->cdev, LED_OFF);
  223. + led_classdev_unregister(&led->cdev);
  224. + kfree(led);
  225. + }
  226. ++ ath9k_unregister_gpio_chip(sc);
  227. + }
  228. +
  229. + void ath_init_leds(struct ath_softc *sc)
  230. +@@ -135,6 +273,8 @@ void ath_init_leds(struct ath_softc *sc)
  231. + if (AR_SREV_9100(sc->sc_ah))
  232. + return;
  233. +
  234. ++ ath9k_register_gpio_chip(sc);
  235. ++
  236. + if (pdata && pdata->led_name)
  237. + strncpy(led_name, pdata->led_name, sizeof(led_name));
  238. + else
  239. +@@ -186,6 +326,7 @@ void ath_fill_led_pin(struct ath_softc *
  240. + /* LED off, active low */
  241. + ath9k_hw_set_gpio(ah, ah->led_pin, (ah->config.led_active_high) ? 0 : 1);
  242. + }
  243. ++
  244. + #endif
  245. +
  246. + /*******************/
  247. diff --git a/package/kernel/mac80211/patches/549-ath9k_enable_gpio_buttons.patch b/package/kernel/mac80211/patches/549-ath9k_enable_gpio_buttons.patch
  248. new file mode 100644
  249. index 0000000..0527406
  250. --- /dev/null
  251. +++ b/package/kernel/mac80211/patches/549-ath9k_enable_gpio_buttons.patch
  252. @@ -0,0 +1,148 @@
  253. +From: Michal Cieslakiewicz <michal.cieslakiewicz@wp.pl>
  254. +Subject: [PATCH v5 5/8] mac80211: ath9k: enable GPIO buttons
  255. +
  256. +Enable platform-defined GPIO button support for ath9k device.
  257. +Key poller is activated for attached platform buttons.
  258. +Requires ath9k GPIO chip access.
  259. +
  260. +Signed-off-by: Michal Cieslakiewicz <michal.cieslakiewicz@wp.pl>
  261. +Signed-off-by: Felix Fietkau <nbd@openwrt.org>
  262. +---
  263. +--- a/drivers/net/wireless/ath/ath9k/ath9k.h
  264. ++++ b/drivers/net/wireless/ath/ath9k/ath9k.h
  265. +@@ -1028,6 +1028,7 @@ struct ath_softc {
  266. + struct list_head leds;
  267. + #ifdef CONFIG_GPIOLIB
  268. + struct ath9k_gpio_chip *gpiochip;
  269. ++ struct platform_device *btnpdev; /* gpio-keys-polled */
  270. + #endif
  271. + #endif
  272. +
  273. +--- a/drivers/net/wireless/ath/ath9k/gpio.c
  274. ++++ b/drivers/net/wireless/ath/ath9k/gpio.c
  275. +@@ -17,6 +17,8 @@
  276. + #include "ath9k.h"
  277. + #include <linux/ath9k_platform.h>
  278. + #include <linux/gpio.h>
  279. ++#include <linux/platform_device.h>
  280. ++#include <linux/gpio_keys.h>
  281. +
  282. + #ifdef CPTCFG_MAC80211_LEDS
  283. +
  284. +@@ -132,6 +134,63 @@ static void ath9k_unregister_gpio_chip(s
  285. + sc->gpiochip = NULL;
  286. + }
  287. +
  288. ++/******************/
  289. ++/* GPIO Buttons */
  290. ++/******************/
  291. ++
  292. ++/* add GPIO buttons */
  293. ++static void ath9k_init_buttons(struct ath_softc *sc)
  294. ++{
  295. ++ struct ath9k_platform_data *pdata = sc->dev->platform_data;
  296. ++ struct platform_device *pdev;
  297. ++ struct gpio_keys_platform_data gkpdata;
  298. ++ struct gpio_keys_button *bt;
  299. ++ int i;
  300. ++
  301. ++ if (!sc->gpiochip)
  302. ++ return;
  303. ++
  304. ++ if (!pdata || !pdata->btns || !pdata->num_btns)
  305. ++ return;
  306. ++
  307. ++ bt = devm_kmemdup(sc->dev, pdata->btns,
  308. ++ pdata->num_btns * sizeof(struct gpio_keys_button),
  309. ++ GFP_KERNEL);
  310. ++ if (!bt)
  311. ++ return;
  312. ++
  313. ++ for (i = 0; i < pdata->num_btns; i++) {
  314. ++ ath9k_hw_cfg_gpio_input(sc->sc_ah, pdata->btns[i].gpio);
  315. ++ bt[i].gpio = sc->gpiochip->gchip.base + pdata->btns[i].gpio;
  316. ++ }
  317. ++
  318. ++ memset(&gkpdata, 0, sizeof(struct gpio_keys_platform_data));
  319. ++ gkpdata.buttons = bt;
  320. ++ gkpdata.nbuttons = pdata->num_btns;
  321. ++ gkpdata.poll_interval = pdata->btn_poll_interval;
  322. ++
  323. ++ pdev = platform_device_register_data(sc->dev, "gpio-keys-polled",
  324. ++ PLATFORM_DEVID_AUTO, &gkpdata,
  325. ++ sizeof(gkpdata));
  326. ++ if (!IS_ERR_OR_NULL(pdev))
  327. ++ sc->btnpdev = pdev;
  328. ++ else {
  329. ++ sc->btnpdev = NULL;
  330. ++ devm_kfree(sc->dev, bt);
  331. ++ }
  332. ++}
  333. ++
  334. ++/* remove GPIO buttons */
  335. ++static void ath9k_deinit_buttons(struct ath_softc *sc)
  336. ++{
  337. ++ if (!sc->gpiochip || !sc->btnpdev)
  338. ++ return;
  339. ++
  340. ++ platform_device_unregister(sc->btnpdev);
  341. ++
  342. ++ sc->btnpdev = NULL;
  343. ++}
  344. ++
  345. + #else /* CONFIG_GPIOLIB */
  346. +
  347. + static inline void ath9k_register_gpio_chip(struct ath_softc *sc)
  348. +@@ -142,6 +201,14 @@ static inline void ath9k_unregister_gpio
  349. + {
  350. + }
  351. +
  352. ++static inline void ath9k_init_buttons(struct ath_softc *sc)
  353. ++{
  354. ++}
  355. ++
  356. ++static inline void ath9k_deinit_buttons(struct ath_softc *sc)
  357. ++{
  358. ++}
  359. ++
  360. + #endif /* CONFIG_GPIOLIB */
  361. +
  362. + /********************************/
  363. +@@ -246,6 +313,7 @@ void ath_deinit_leds(struct ath_softc *s
  364. + {
  365. + struct ath_led *led;
  366. +
  367. ++ ath9k_deinit_buttons(sc);
  368. + while (!list_empty(&sc->leds)) {
  369. + led = list_first_entry(&sc->leds, struct ath_led, list);
  370. + #ifdef CONFIG_GPIOLIB
  371. +@@ -274,6 +342,7 @@ void ath_init_leds(struct ath_softc *sc)
  372. + return;
  373. +
  374. + ath9k_register_gpio_chip(sc);
  375. ++ ath9k_init_buttons(sc);
  376. +
  377. + if (pdata && pdata->led_name)
  378. + strncpy(led_name, pdata->led_name, sizeof(led_name));
  379. +@@ -289,7 +358,7 @@ void ath_init_leds(struct ath_softc *sc)
  380. + ath_create_gpio_led(sc, sc->sc_ah->led_pin, led_name, trigger,
  381. + !sc->sc_ah->config.led_active_high);
  382. +
  383. +- if (!pdata)
  384. ++ if (!pdata || !pdata->leds || !pdata->num_leds)
  385. + return;
  386. +
  387. + for (i = 0; i < pdata->num_leds; i++)
  388. +--- a/include/linux/ath9k_platform.h
  389. ++++ b/include/linux/ath9k_platform.h
  390. +@@ -46,6 +46,10 @@ struct ath9k_platform_data {
  391. + int num_leds;
  392. + const struct gpio_led *leds;
  393. + const char *led_name;
  394. ++
  395. ++ unsigned num_btns;
  396. ++ const struct gpio_keys_button *btns;
  397. ++ unsigned btn_poll_interval;
  398. + };
  399. +
  400. + #endif /* _LINUX_ATH9K_PLATFORM_H */
  401. diff --git a/package/kernel/mac80211/patches/549-ath9k_enable_gpio_chip.patch b/package/kernel/mac80211/patches/549-ath9k_enable_gpio_chip.patch
  402. deleted file mode 100644
  403. index 55bb991..0000000
  404. --- a/package/kernel/mac80211/patches/549-ath9k_enable_gpio_chip.patch
  405. +++ /dev/null
  406. @@ -1,243 +0,0 @@
  407. -From: Michal Cieslakiewicz <michal.cieslakiewicz@wp.pl>
  408. -Date: Sun, 31 Jan 2016 21:01:31 +0100
  409. -Subject: [PATCH v4 4/8] mac80211: ath9k: enable access to GPIO
  410. -
  411. -Enable access to GPIO chip and its pins for Atheros AR92xx
  412. -wireless devices. For now AR9285 and AR9287 are supported.
  413. -
  414. -Signed-off-by: Michal Cieslakiewicz <michal.cieslakiewicz@wp.pl>
  415. ----
  416. - ath9k.h | 23 ++++++++++++
  417. - gpio.c | 121 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  418. - init.c | 2 +
  419. - 3 files changed, 146 insertions(+)
  420. -
  421. ---- a/drivers/net/wireless/ath/ath9k/ath9k.h
  422. -+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
  423. -@@ -24,6 +24,7 @@
  424. - #include <linux/completion.h>
  425. - #include <linux/time.h>
  426. - #include <linux/hw_random.h>
  427. -+#include <linux/gpio/driver.h>
  428. -
  429. - #include "common.h"
  430. - #include "debug.h"
  431. -@@ -817,6 +818,13 @@ void ath_fill_led_pin(struct ath_softc *
  432. - int ath_create_gpio_led(struct ath_softc *sc, int gpio, const char *name,
  433. - const char *trigger, bool active_low);
  434. -
  435. -+/***************/
  436. -+/* GPIO Chip */
  437. -+/***************/
  438. -+
  439. -+void ath9k_register_gpio_chip(struct ath_softc *sc);
  440. -+void ath9k_unregister_gpio_chip(struct ath_softc *sc);
  441. -+
  442. - #else
  443. - static inline void ath_init_leds(struct ath_softc *sc)
  444. - {
  445. -@@ -828,6 +836,14 @@ static inline void ath_deinit_leds(struc
  446. - static inline void ath_fill_led_pin(struct ath_softc *sc)
  447. - {
  448. - }
  449. -+
  450. -+static inline void ath9k_register_gpio_chip(struct ath_softc *sc)
  451. -+{
  452. -+}
  453. -+
  454. -+static inline void ath9k_unregister_gpio_chip(struct ath_softc *sc)
  455. -+{
  456. -+}
  457. - #endif
  458. -
  459. - /************************/
  460. -@@ -963,6 +979,12 @@ struct ath_led {
  461. - struct led_classdev cdev;
  462. - };
  463. -
  464. -+struct ath9k_gpio_chip {
  465. -+ struct ath_softc *sc;
  466. -+ char label[32];
  467. -+ struct gpio_chip gchip;
  468. -+};
  469. -+
  470. - struct ath_softc {
  471. - struct ieee80211_hw *hw;
  472. - struct device *dev;
  473. -@@ -1017,6 +1039,7 @@ struct ath_softc {
  474. - #ifdef CPTCFG_MAC80211_LEDS
  475. - const char *led_default_trigger;
  476. - struct list_head leds;
  477. -+ struct ath9k_gpio_chip *gpiochip;
  478. - #endif
  479. -
  480. - #ifdef CPTCFG_ATH9K_DEBUGFS
  481. ---- a/drivers/net/wireless/ath/ath9k/gpio.c
  482. -+++ b/drivers/net/wireless/ath/ath9k/gpio.c
  483. -@@ -22,6 +22,9 @@
  484. - /********************************/
  485. -
  486. - #ifdef CPTCFG_MAC80211_LEDS
  487. -+
  488. -+#include <asm-generic/gpio.h>
  489. -+
  490. - static void ath_led_brightness(struct led_classdev *led_cdev,
  491. - enum led_brightness brightness)
  492. - {
  493. -@@ -60,6 +63,10 @@ static int ath_add_led(struct ath_softc
  494. - else
  495. - ath9k_hw_set_gpio(sc->sc_ah, gpio->gpio, gpio->active_low);
  496. -
  497. -+ /* If there is GPIO chip configured, reserve LED pin */
  498. -+ if (sc->gpiochip)
  499. -+ gpio_request(sc->gpiochip->gchip.base + gpio->gpio, gpio->name);
  500. -+
  501. - return 0;
  502. - }
  503. -
  504. -@@ -116,6 +123,9 @@ void ath_deinit_leds(struct ath_softc *s
  505. -
  506. - while (!list_empty(&sc->leds)) {
  507. - led = list_first_entry(&sc->leds, struct ath_led, list);
  508. -+ /* If there is GPIO chip configured, free LED pin */
  509. -+ if (sc->gpiochip)
  510. -+ gpio_free(sc->gpiochip->gchip.base + led->gpio->gpio);
  511. - list_del(&led->list);
  512. - ath_led_brightness(&led->cdev, LED_OFF);
  513. - led_classdev_unregister(&led->cdev);
  514. -@@ -186,6 +196,117 @@ void ath_fill_led_pin(struct ath_softc *
  515. - /* LED off, active low */
  516. - ath9k_hw_set_gpio(ah, ah->led_pin, (ah->config.led_active_high) ? 0 : 1);
  517. - }
  518. -+
  519. -+/***************/
  520. -+/* GPIO Chip */
  521. -+/***************/
  522. -+
  523. -+/* gpio_chip handler : set GPIO to input */
  524. -+static int ath9k_gpio_pin_cfg_input(struct gpio_chip *chip, unsigned offset)
  525. -+{
  526. -+ struct ath9k_gpio_chip *gc = container_of(chip, struct ath9k_gpio_chip,
  527. -+ gchip);
  528. -+
  529. -+ ath9k_hw_cfg_gpio_input(gc->sc->sc_ah, offset);
  530. -+
  531. -+ return 0;
  532. -+}
  533. -+
  534. -+/* gpio_chip handler : set GPIO to output */
  535. -+static int ath9k_gpio_pin_cfg_output(struct gpio_chip *chip, unsigned offset,
  536. -+ int value)
  537. -+{
  538. -+ struct ath9k_gpio_chip *gc = container_of(chip, struct ath9k_gpio_chip,
  539. -+ gchip);
  540. -+
  541. -+ ath9k_hw_cfg_output(gc->sc->sc_ah, offset,
  542. -+ AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
  543. -+ ath9k_hw_set_gpio(gc->sc->sc_ah, offset, value);
  544. -+
  545. -+ return 0;
  546. -+}
  547. -+
  548. -+/* gpio_chip handler : query GPIO direction (0=out, 1=in) */
  549. -+static int ath9k_gpio_pin_get_dir(struct gpio_chip *chip, unsigned offset)
  550. -+{
  551. -+ struct ath9k_gpio_chip *gc = container_of(chip, struct ath9k_gpio_chip,
  552. -+ gchip);
  553. -+ struct ath_hw *ah = gc->sc->sc_ah;
  554. -+
  555. -+ return !((REG_READ(ah, AR_GPIO_OE_OUT) >> (offset * 2)) & 3);
  556. -+}
  557. -+
  558. -+/* gpio_chip handler : get GPIO pin value */
  559. -+static int ath9k_gpio_pin_get(struct gpio_chip *chip, unsigned offset)
  560. -+{
  561. -+ struct ath9k_gpio_chip *gc = container_of(chip, struct ath9k_gpio_chip,
  562. -+ gchip);
  563. -+
  564. -+ return ath9k_hw_gpio_get(gc->sc->sc_ah, offset);
  565. -+}
  566. -+
  567. -+/* gpio_chip handler : set GPIO pin to value */
  568. -+static void ath9k_gpio_pin_set(struct gpio_chip *chip, unsigned offset,
  569. -+ int value)
  570. -+{
  571. -+ struct ath9k_gpio_chip *gc = container_of(chip, struct ath9k_gpio_chip,
  572. -+ gchip);
  573. -+
  574. -+ ath9k_hw_set_gpio(gc->sc->sc_ah, offset, value);
  575. -+}
  576. -+
  577. -+/* register GPIO chip */
  578. -+void ath9k_register_gpio_chip(struct ath_softc *sc)
  579. -+{
  580. -+ struct ath9k_gpio_chip *gc;
  581. -+ u16 ng;
  582. -+
  583. -+ /* for now only AR9285 and AR9287 are recognized */
  584. -+ if (AR_SREV_9287(sc->sc_ah))
  585. -+ ng = AR9287_NUM_GPIO;
  586. -+ else if (AR_SREV_9285(sc->sc_ah))
  587. -+ ng = AR9285_NUM_GPIO;
  588. -+ else
  589. -+ return;
  590. -+
  591. -+ gc = kzalloc(sizeof(struct ath9k_gpio_chip), GFP_KERNEL);
  592. -+ if (!gc)
  593. -+ return;
  594. -+
  595. -+ snprintf(gc->label, sizeof(gc->label), "ath9k-%s",
  596. -+ wiphy_name(sc->hw->wiphy));
  597. -+ gc->gchip.label = gc->label;
  598. -+ gc->gchip.base = -1; /* determine base automatically */
  599. -+ gc->gchip.ngpio = ng;
  600. -+ gc->gchip.direction_input = ath9k_gpio_pin_cfg_input;
  601. -+ gc->gchip.direction_output = ath9k_gpio_pin_cfg_output;
  602. -+ gc->gchip.get_direction = ath9k_gpio_pin_get_dir;
  603. -+ gc->gchip.get = ath9k_gpio_pin_get;
  604. -+ gc->gchip.set = ath9k_gpio_pin_set;
  605. -+ gc->gchip.owner = THIS_MODULE;
  606. -+
  607. -+ if (gpiochip_add(&gc->gchip)) {
  608. -+ kfree(gc);
  609. -+ return;
  610. -+ }
  611. -+
  612. -+ sc->gpiochip = gc;
  613. -+ gc->sc = sc;
  614. -+}
  615. -+
  616. -+/* remove GPIO chip */
  617. -+void ath9k_unregister_gpio_chip(struct ath_softc *sc)
  618. -+{
  619. -+ struct ath9k_gpio_chip *gc = sc->gpiochip;
  620. -+
  621. -+ if (!gc)
  622. -+ return;
  623. -+
  624. -+ gpiochip_remove(&gc->gchip);
  625. -+ kfree(gc);
  626. -+ sc->gpiochip = NULL;
  627. -+}
  628. -+
  629. - #endif
  630. -
  631. - /*******************/
  632. ---- a/drivers/net/wireless/ath/ath9k/init.c
  633. -+++ b/drivers/net/wireless/ath/ath9k/init.c
  634. -@@ -975,6 +975,7 @@ int ath9k_init_device(u16 devid, struct
  635. - goto debug_cleanup;
  636. - }
  637. -
  638. -+ ath9k_register_gpio_chip(sc);
  639. - ath_init_leds(sc);
  640. - ath_start_rfkill_poll(sc);
  641. -
  642. -@@ -1022,6 +1023,7 @@ void ath9k_deinit_device(struct ath_soft
  643. -
  644. - wiphy_rfkill_stop_polling(sc->hw->wiphy);
  645. - ath_deinit_leds(sc);
  646. -+ ath9k_unregister_gpio_chip(sc);
  647. -
  648. - ath9k_ps_restore(sc);
  649. -
  650. diff --git a/package/kernel/mac80211/patches/550-ath9k_enable_gpio_buttons.patch b/package/kernel/mac80211/patches/550-ath9k_enable_gpio_buttons.patch
  651. deleted file mode 100644
  652. index e3a8cec..0000000
  653. --- a/package/kernel/mac80211/patches/550-ath9k_enable_gpio_buttons.patch
  654. +++ /dev/null
  655. @@ -1,169 +0,0 @@
  656. -From: Michal Cieslakiewicz <michal.cieslakiewicz@wp.pl>
  657. -Subject: [PATCH v5 5/8] mac80211: ath9k: enable GPIO buttons
  658. -
  659. -Enable platform-defined GPIO button support for ath9k device.
  660. -Key poller is activated for attached platform buttons.
  661. -Requires ath9k GPIO chip access.
  662. -
  663. -Signed-off-by: Michal Cieslakiewicz <michal.cieslakiewicz@wp.pl>
  664. ----
  665. - drivers/net/wireless/ath/ath9k/ath9k.h | 16 ++++++
  666. - drivers/net/wireless/ath/ath9k/gpio.c | 77 +++++++++++++++++++++++++++++++++
  667. - drivers/net/wireless/ath/ath9k/init.c | 2
  668. - include/linux/ath9k_platform.h | 4 +
  669. - 4 files changed, 99 insertions(+)
  670. -
  671. ---- a/drivers/net/wireless/ath/ath9k/ath9k.h
  672. -+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
  673. -@@ -825,6 +825,13 @@ int ath_create_gpio_led(struct ath_softc
  674. - void ath9k_register_gpio_chip(struct ath_softc *sc);
  675. - void ath9k_unregister_gpio_chip(struct ath_softc *sc);
  676. -
  677. -+/******************/
  678. -+/* GPIO Buttons */
  679. -+/******************/
  680. -+
  681. -+void ath9k_init_buttons(struct ath_softc *sc);
  682. -+void ath9k_deinit_buttons(struct ath_softc *sc);
  683. -+
  684. - #else
  685. - static inline void ath_init_leds(struct ath_softc *sc)
  686. - {
  687. -@@ -844,6 +851,14 @@ static inline void ath9k_register_gpio_c
  688. - static inline void ath9k_unregister_gpio_chip(struct ath_softc *sc)
  689. - {
  690. - }
  691. -+
  692. -+static inline void ath9k_init_buttons(struct ath_softc *sc)
  693. -+{
  694. -+}
  695. -+
  696. -+static inline void ath9k_deinit_buttons(struct ath_softc *sc)
  697. -+{
  698. -+}
  699. - #endif
  700. -
  701. - /************************/
  702. -@@ -1040,6 +1055,7 @@ struct ath_softc {
  703. - const char *led_default_trigger;
  704. - struct list_head leds;
  705. - struct ath9k_gpio_chip *gpiochip;
  706. -+ struct platform_device *btnpdev; /* gpio-keys-polled */
  707. - #endif
  708. -
  709. - #ifdef CPTCFG_ATH9K_DEBUGFS
  710. ---- a/drivers/net/wireless/ath/ath9k/gpio.c
  711. -+++ b/drivers/net/wireless/ath/ath9k/gpio.c
  712. -@@ -24,6 +24,8 @@
  713. - #ifdef CPTCFG_MAC80211_LEDS
  714. -
  715. - #include <asm-generic/gpio.h>
  716. -+#include <linux/platform_device.h>
  717. -+#include <linux/gpio_keys.h>
  718. -
  719. - static void ath_led_brightness(struct led_classdev *led_cdev,
  720. - enum led_brightness brightness)
  721. -@@ -159,7 +161,7 @@ void ath_init_leds(struct ath_softc *sc)
  722. - ath_create_gpio_led(sc, sc->sc_ah->led_pin, led_name, trigger,
  723. - !sc->sc_ah->config.led_active_high);
  724. -
  725. -- if (!pdata)
  726. -+ if (!pdata || !pdata->leds || !pdata->num_leds)
  727. - return;
  728. -
  729. - for (i = 0; i < pdata->num_leds; i++)
  730. -@@ -307,6 +309,63 @@ void ath9k_unregister_gpio_chip(struct a
  731. - sc->gpiochip = NULL;
  732. - }
  733. -
  734. -+/******************/
  735. -+/* GPIO Buttons */
  736. -+/******************/
  737. -+
  738. -+/* add GPIO buttons */
  739. -+void ath9k_init_buttons(struct ath_softc *sc)
  740. -+{
  741. -+ struct ath9k_platform_data *pdata = sc->dev->platform_data;
  742. -+ struct platform_device *pdev;
  743. -+ struct gpio_keys_platform_data gkpdata;
  744. -+ struct gpio_keys_button *bt;
  745. -+ int i;
  746. -+
  747. -+ if (!sc->gpiochip)
  748. -+ return;
  749. -+
  750. -+ if (!pdata || !pdata->btns || !pdata->num_btns)
  751. -+ return;
  752. -+
  753. -+ bt = devm_kmemdup(sc->dev, pdata->btns,
  754. -+ pdata->num_btns * sizeof(struct gpio_keys_button),
  755. -+ GFP_KERNEL);
  756. -+ if (!bt)
  757. -+ return;
  758. -+
  759. -+ for (i = 0; i < pdata->num_btns; i++) {
  760. -+ ath9k_hw_cfg_gpio_input(sc->sc_ah, pdata->btns[i].gpio);
  761. -+ bt[i].gpio = sc->gpiochip->gchip.base + pdata->btns[i].gpio;
  762. -+ }
  763. -+
  764. -+ memset(&gkpdata, 0, sizeof(struct gpio_keys_platform_data));
  765. -+ gkpdata.buttons = bt;
  766. -+ gkpdata.nbuttons = pdata->num_btns;
  767. -+ gkpdata.poll_interval = pdata->btn_poll_interval;
  768. -+
  769. -+ pdev = platform_device_register_data(sc->dev, "gpio-keys-polled",
  770. -+ PLATFORM_DEVID_AUTO, &gkpdata,
  771. -+ sizeof(gkpdata));
  772. -+ if (!IS_ERR_OR_NULL(pdev))
  773. -+ sc->btnpdev = pdev;
  774. -+ else {
  775. -+ sc->btnpdev = NULL;
  776. -+ devm_kfree(sc->dev, bt);
  777. -+ }
  778. -+}
  779. -+
  780. -+/* remove GPIO buttons */
  781. -+void ath9k_deinit_buttons(struct ath_softc *sc)
  782. -+{
  783. -+ if (!sc->gpiochip || !sc->btnpdev)
  784. -+ return;
  785. -+
  786. -+ platform_device_unregister(sc->btnpdev);
  787. -+
  788. -+ sc->btnpdev = NULL;
  789. -+}
  790. -+
  791. - #endif
  792. -
  793. - /*******************/
  794. ---- a/drivers/net/wireless/ath/ath9k/init.c
  795. -+++ b/drivers/net/wireless/ath/ath9k/init.c
  796. -@@ -977,6 +977,7 @@ int ath9k_init_device(u16 devid, struct
  797. -
  798. - ath9k_register_gpio_chip(sc);
  799. - ath_init_leds(sc);
  800. -+ ath9k_init_buttons(sc);
  801. - ath_start_rfkill_poll(sc);
  802. -
  803. - return 0;
  804. -@@ -1022,6 +1023,7 @@ void ath9k_deinit_device(struct ath_soft
  805. - ath9k_ps_wakeup(sc);
  806. -
  807. - wiphy_rfkill_stop_polling(sc->hw->wiphy);
  808. -+ ath9k_deinit_buttons(sc);
  809. - ath_deinit_leds(sc);
  810. - ath9k_unregister_gpio_chip(sc);
  811. -
  812. ---- a/include/linux/ath9k_platform.h
  813. -+++ b/include/linux/ath9k_platform.h
  814. -@@ -46,6 +46,10 @@ struct ath9k_platform_data {
  815. - int num_leds;
  816. - const struct gpio_led *leds;
  817. - const char *led_name;
  818. -+
  819. -+ unsigned num_btns;
  820. -+ const struct gpio_keys_button *btns;
  821. -+ unsigned btn_poll_interval;
  822. - };
  823. -
  824. - #endif /* _LINUX_ATH9K_PLATFORM_H */