0082-mac80211-ath9k-enable-access-to-GPIO.patch 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. From: Matthias Schiffer <mschiffer@universe-factory.net>
  2. Date: Sun, 29 May 2016 13:37:59 +0200
  3. Subject: mac80211: ath9k: enable access to GPIO
  4. Enable access to GPIO chip and its pins for Atheros AR92xx
  5. wireless devices. For now AR9285 and AR9287 are supported.
  6. Signed-off-by: Michal Cieslakiewicz <michal.cieslakiewicz@wp.pl>
  7. Acked-by: Hartmut Knaack <knaack.h@gmx.de>
  8. Backport of r48881
  9. diff --git a/package/kernel/mac80211/patches/549-ath9k_enable_gpio_chip.patch b/package/kernel/mac80211/patches/549-ath9k_enable_gpio_chip.patch
  10. new file mode 100644
  11. index 0000000..beee169
  12. --- /dev/null
  13. +++ b/package/kernel/mac80211/patches/549-ath9k_enable_gpio_chip.patch
  14. @@ -0,0 +1,243 @@
  15. +From: Michal Cieslakiewicz <michal.cieslakiewicz@wp.pl>
  16. +Date: Sun, 31 Jan 2016 21:01:31 +0100
  17. +Subject: [PATCH v4 4/8] mac80211: ath9k: enable access to GPIO
  18. +
  19. +Enable access to GPIO chip and its pins for Atheros AR92xx
  20. +wireless devices. For now AR9285 and AR9287 are supported.
  21. +
  22. +Signed-off-by: Michal Cieslakiewicz <michal.cieslakiewicz@wp.pl>
  23. +---
  24. + ath9k.h | 23 ++++++++++++
  25. + gpio.c | 121 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  26. + init.c | 2 +
  27. + 3 files changed, 146 insertions(+)
  28. +
  29. +--- a/drivers/net/wireless/ath/ath9k/ath9k.h
  30. ++++ b/drivers/net/wireless/ath/ath9k/ath9k.h
  31. +@@ -24,6 +24,7 @@
  32. + #include <linux/completion.h>
  33. + #include <linux/time.h>
  34. + #include <linux/hw_random.h>
  35. ++#include <linux/gpio/driver.h>
  36. +
  37. + #include "common.h"
  38. + #include "debug.h"
  39. +@@ -817,6 +818,13 @@ void ath_fill_led_pin(struct ath_softc *
  40. + int ath_create_gpio_led(struct ath_softc *sc, int gpio, const char *name,
  41. + const char *trigger, bool active_low);
  42. +
  43. ++/***************/
  44. ++/* GPIO Chip */
  45. ++/***************/
  46. ++
  47. ++void ath9k_register_gpio_chip(struct ath_softc *sc);
  48. ++void ath9k_unregister_gpio_chip(struct ath_softc *sc);
  49. ++
  50. + #else
  51. + static inline void ath_init_leds(struct ath_softc *sc)
  52. + {
  53. +@@ -828,6 +836,14 @@ static inline void ath_deinit_leds(struc
  54. + static inline void ath_fill_led_pin(struct ath_softc *sc)
  55. + {
  56. + }
  57. ++
  58. ++static inline void ath9k_register_gpio_chip(struct ath_softc *sc)
  59. ++{
  60. ++}
  61. ++
  62. ++static inline void ath9k_unregister_gpio_chip(struct ath_softc *sc)
  63. ++{
  64. ++}
  65. + #endif
  66. +
  67. + /************************/
  68. +@@ -963,6 +979,12 @@ struct ath_led {
  69. + struct led_classdev cdev;
  70. + };
  71. +
  72. ++struct ath9k_gpio_chip {
  73. ++ struct ath_softc *sc;
  74. ++ char label[32];
  75. ++ struct gpio_chip gchip;
  76. ++};
  77. ++
  78. + struct ath_softc {
  79. + struct ieee80211_hw *hw;
  80. + struct device *dev;
  81. +@@ -1017,6 +1039,7 @@ struct ath_softc {
  82. + #ifdef CPTCFG_MAC80211_LEDS
  83. + const char *led_default_trigger;
  84. + struct list_head leds;
  85. ++ struct ath9k_gpio_chip *gpiochip;
  86. + #endif
  87. +
  88. + #ifdef CPTCFG_ATH9K_DEBUGFS
  89. +--- a/drivers/net/wireless/ath/ath9k/gpio.c
  90. ++++ b/drivers/net/wireless/ath/ath9k/gpio.c
  91. +@@ -22,6 +22,9 @@
  92. + /********************************/
  93. +
  94. + #ifdef CPTCFG_MAC80211_LEDS
  95. ++
  96. ++#include <asm-generic/gpio.h>
  97. ++
  98. + static void ath_led_brightness(struct led_classdev *led_cdev,
  99. + enum led_brightness brightness)
  100. + {
  101. +@@ -60,6 +63,10 @@ static int ath_add_led(struct ath_softc
  102. + else
  103. + ath9k_hw_set_gpio(sc->sc_ah, gpio->gpio, gpio->active_low);
  104. +
  105. ++ /* If there is GPIO chip configured, reserve LED pin */
  106. ++ if (sc->gpiochip)
  107. ++ gpio_request(sc->gpiochip->gchip.base + gpio->gpio, gpio->name);
  108. ++
  109. + return 0;
  110. + }
  111. +
  112. +@@ -116,6 +123,9 @@ void ath_deinit_leds(struct ath_softc *s
  113. +
  114. + while (!list_empty(&sc->leds)) {
  115. + led = list_first_entry(&sc->leds, struct ath_led, list);
  116. ++ /* If there is GPIO chip configured, free LED pin */
  117. ++ if (sc->gpiochip)
  118. ++ gpio_free(sc->gpiochip->gchip.base + led->gpio->gpio);
  119. + list_del(&led->list);
  120. + ath_led_brightness(&led->cdev, LED_OFF);
  121. + led_classdev_unregister(&led->cdev);
  122. +@@ -186,6 +196,117 @@ void ath_fill_led_pin(struct ath_softc *
  123. + /* LED off, active low */
  124. + ath9k_hw_set_gpio(ah, ah->led_pin, (ah->config.led_active_high) ? 0 : 1);
  125. + }
  126. ++
  127. ++/***************/
  128. ++/* GPIO Chip */
  129. ++/***************/
  130. ++
  131. ++/* gpio_chip handler : set GPIO to input */
  132. ++static int ath9k_gpio_pin_cfg_input(struct gpio_chip *chip, unsigned offset)
  133. ++{
  134. ++ struct ath9k_gpio_chip *gc = container_of(chip, struct ath9k_gpio_chip,
  135. ++ gchip);
  136. ++
  137. ++ ath9k_hw_cfg_gpio_input(gc->sc->sc_ah, offset);
  138. ++
  139. ++ return 0;
  140. ++}
  141. ++
  142. ++/* gpio_chip handler : set GPIO to output */
  143. ++static int ath9k_gpio_pin_cfg_output(struct gpio_chip *chip, unsigned offset,
  144. ++ int value)
  145. ++{
  146. ++ struct ath9k_gpio_chip *gc = container_of(chip, struct ath9k_gpio_chip,
  147. ++ gchip);
  148. ++
  149. ++ ath9k_hw_cfg_output(gc->sc->sc_ah, offset,
  150. ++ AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
  151. ++ ath9k_hw_set_gpio(gc->sc->sc_ah, offset, value);
  152. ++
  153. ++ return 0;
  154. ++}
  155. ++
  156. ++/* gpio_chip handler : query GPIO direction (0=out, 1=in) */
  157. ++static int ath9k_gpio_pin_get_dir(struct gpio_chip *chip, unsigned offset)
  158. ++{
  159. ++ struct ath9k_gpio_chip *gc = container_of(chip, struct ath9k_gpio_chip,
  160. ++ gchip);
  161. ++ struct ath_hw *ah = gc->sc->sc_ah;
  162. ++
  163. ++ return !((REG_READ(ah, AR_GPIO_OE_OUT) >> (offset * 2)) & 3);
  164. ++}
  165. ++
  166. ++/* gpio_chip handler : get GPIO pin value */
  167. ++static int ath9k_gpio_pin_get(struct gpio_chip *chip, unsigned offset)
  168. ++{
  169. ++ struct ath9k_gpio_chip *gc = container_of(chip, struct ath9k_gpio_chip,
  170. ++ gchip);
  171. ++
  172. ++ return ath9k_hw_gpio_get(gc->sc->sc_ah, offset);
  173. ++}
  174. ++
  175. ++/* gpio_chip handler : set GPIO pin to value */
  176. ++static void ath9k_gpio_pin_set(struct gpio_chip *chip, unsigned offset,
  177. ++ int value)
  178. ++{
  179. ++ struct ath9k_gpio_chip *gc = container_of(chip, struct ath9k_gpio_chip,
  180. ++ gchip);
  181. ++
  182. ++ ath9k_hw_set_gpio(gc->sc->sc_ah, offset, value);
  183. ++}
  184. ++
  185. ++/* register GPIO chip */
  186. ++void ath9k_register_gpio_chip(struct ath_softc *sc)
  187. ++{
  188. ++ struct ath9k_gpio_chip *gc;
  189. ++ u16 ng;
  190. ++
  191. ++ /* for now only AR9285 and AR9287 are recognized */
  192. ++ if (AR_SREV_9287(sc->sc_ah))
  193. ++ ng = AR9287_NUM_GPIO;
  194. ++ else if (AR_SREV_9285(sc->sc_ah))
  195. ++ ng = AR9285_NUM_GPIO;
  196. ++ else
  197. ++ return;
  198. ++
  199. ++ gc = kzalloc(sizeof(struct ath9k_gpio_chip), GFP_KERNEL);
  200. ++ if (!gc)
  201. ++ return;
  202. ++
  203. ++ snprintf(gc->label, sizeof(gc->label), "ath9k-%s",
  204. ++ wiphy_name(sc->hw->wiphy));
  205. ++ gc->gchip.label = gc->label;
  206. ++ gc->gchip.base = -1; /* determine base automatically */
  207. ++ gc->gchip.ngpio = ng;
  208. ++ gc->gchip.direction_input = ath9k_gpio_pin_cfg_input;
  209. ++ gc->gchip.direction_output = ath9k_gpio_pin_cfg_output;
  210. ++ gc->gchip.get_direction = ath9k_gpio_pin_get_dir;
  211. ++ gc->gchip.get = ath9k_gpio_pin_get;
  212. ++ gc->gchip.set = ath9k_gpio_pin_set;
  213. ++ gc->gchip.owner = THIS_MODULE;
  214. ++
  215. ++ if (gpiochip_add(&gc->gchip)) {
  216. ++ kfree(gc);
  217. ++ return;
  218. ++ }
  219. ++
  220. ++ sc->gpiochip = gc;
  221. ++ gc->sc = sc;
  222. ++}
  223. ++
  224. ++/* remove GPIO chip */
  225. ++void ath9k_unregister_gpio_chip(struct ath_softc *sc)
  226. ++{
  227. ++ struct ath9k_gpio_chip *gc = sc->gpiochip;
  228. ++
  229. ++ if (!gc)
  230. ++ return;
  231. ++
  232. ++ gpiochip_remove(&gc->gchip);
  233. ++ kfree(gc);
  234. ++ sc->gpiochip = NULL;
  235. ++}
  236. ++
  237. + #endif
  238. +
  239. + /*******************/
  240. +--- a/drivers/net/wireless/ath/ath9k/init.c
  241. ++++ b/drivers/net/wireless/ath/ath9k/init.c
  242. +@@ -979,6 +979,7 @@ int ath9k_init_device(u16 devid, struct
  243. + goto debug_cleanup;
  244. + }
  245. +
  246. ++ ath9k_register_gpio_chip(sc);
  247. + ath_init_leds(sc);
  248. + ath_start_rfkill_poll(sc);
  249. +
  250. +@@ -1026,6 +1027,7 @@ void ath9k_deinit_device(struct ath_soft
  251. +
  252. + wiphy_rfkill_stop_polling(sc->hw->wiphy);
  253. + ath_deinit_leds(sc);
  254. ++ ath9k_unregister_gpio_chip(sc);
  255. +
  256. + ath9k_ps_restore(sc);
  257. +