548-ath9k_enable_gpio_chip.patch 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. From: Michal Cieslakiewicz <michal.cieslakiewicz@wp.pl>
  2. Date: Sun, 31 Jan 2016 21:01:31 +0100
  3. Subject: [PATCH v4 4/8] 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. Signed-off-by: Felix Fietkau <nbd@nbd.name>
  8. ---
  9. --- a/drivers/net/wireless/ath/ath9k/ath9k.h
  10. +++ b/drivers/net/wireless/ath/ath9k/ath9k.h
  11. @@ -24,6 +24,7 @@
  12. #include <linux/completion.h>
  13. #include <linux/time.h>
  14. #include <linux/hw_random.h>
  15. +#include <linux/gpio/driver.h>
  16. #include "common.h"
  17. #include "debug.h"
  18. @@ -959,6 +960,14 @@ struct ath_led {
  19. struct led_classdev cdev;
  20. };
  21. +#ifdef CONFIG_GPIOLIB
  22. +struct ath9k_gpio_chip {
  23. + struct ath_softc *sc;
  24. + char label[32];
  25. + struct gpio_chip gchip;
  26. +};
  27. +#endif
  28. +
  29. struct ath_softc {
  30. struct ieee80211_hw *hw;
  31. struct device *dev;
  32. @@ -1013,6 +1022,9 @@ struct ath_softc {
  33. #ifdef CPTCFG_MAC80211_LEDS
  34. const char *led_default_trigger;
  35. struct list_head leds;
  36. +#ifdef CONFIG_GPIOLIB
  37. + struct ath9k_gpio_chip *gpiochip;
  38. +#endif
  39. #endif
  40. #ifdef CPTCFG_ATH9K_DEBUGFS
  41. --- a/drivers/net/wireless/ath/ath9k/gpio.c
  42. +++ b/drivers/net/wireless/ath/ath9k/gpio.c
  43. @@ -16,13 +16,138 @@
  44. #include "ath9k.h"
  45. #include <linux/ath9k_platform.h>
  46. +#include <linux/gpio.h>
  47. +
  48. +#ifdef CPTCFG_MAC80211_LEDS
  49. +
  50. +#ifdef CONFIG_GPIOLIB
  51. +
  52. +/***************/
  53. +/* GPIO Chip */
  54. +/***************/
  55. +
  56. +/* gpio_chip handler : set GPIO to input */
  57. +static int ath9k_gpio_pin_cfg_input(struct gpio_chip *chip, unsigned offset)
  58. +{
  59. + struct ath9k_gpio_chip *gc = container_of(chip, struct ath9k_gpio_chip,
  60. + gchip);
  61. +
  62. + ath9k_hw_gpio_request_in(gc->sc->sc_ah, offset, "ath9k-gpio");
  63. +
  64. + return 0;
  65. +}
  66. +
  67. +/* gpio_chip handler : set GPIO to output */
  68. +static int ath9k_gpio_pin_cfg_output(struct gpio_chip *chip, unsigned offset,
  69. + int value)
  70. +{
  71. + struct ath9k_gpio_chip *gc = container_of(chip, struct ath9k_gpio_chip,
  72. + gchip);
  73. +
  74. + ath9k_hw_gpio_request_out(gc->sc->sc_ah, offset, "ath9k-gpio",
  75. + AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
  76. + ath9k_hw_set_gpio(gc->sc->sc_ah, offset, value);
  77. +
  78. + return 0;
  79. +}
  80. +
  81. +/* gpio_chip handler : query GPIO direction (0=out, 1=in) */
  82. +static int ath9k_gpio_pin_get_dir(struct gpio_chip *chip, unsigned offset)
  83. +{
  84. + struct ath9k_gpio_chip *gc = container_of(chip, struct ath9k_gpio_chip,
  85. + gchip);
  86. + struct ath_hw *ah = gc->sc->sc_ah;
  87. +
  88. + return !((REG_READ(ah, AR_GPIO_OE_OUT) >> (offset * 2)) & 3);
  89. +}
  90. +
  91. +/* gpio_chip handler : get GPIO pin value */
  92. +static int ath9k_gpio_pin_get(struct gpio_chip *chip, unsigned offset)
  93. +{
  94. + struct ath9k_gpio_chip *gc = container_of(chip, struct ath9k_gpio_chip,
  95. + gchip);
  96. +
  97. + return ath9k_hw_gpio_get(gc->sc->sc_ah, offset);
  98. +}
  99. +
  100. +/* gpio_chip handler : set GPIO pin to value */
  101. +static void ath9k_gpio_pin_set(struct gpio_chip *chip, unsigned offset,
  102. + int value)
  103. +{
  104. + struct ath9k_gpio_chip *gc = container_of(chip, struct ath9k_gpio_chip,
  105. + gchip);
  106. +
  107. + ath9k_hw_set_gpio(gc->sc->sc_ah, offset, value);
  108. +}
  109. +
  110. +/* register GPIO chip */
  111. +static void ath9k_register_gpio_chip(struct ath_softc *sc)
  112. +{
  113. + struct ath9k_gpio_chip *gc;
  114. + u16 ng;
  115. +
  116. + /* for now only AR9285 and AR9287 are recognized */
  117. + if (AR_SREV_9287(sc->sc_ah))
  118. + ng = AR9287_NUM_GPIO;
  119. + else if (AR_SREV_9285(sc->sc_ah))
  120. + ng = AR9285_NUM_GPIO;
  121. + else
  122. + return;
  123. +
  124. + gc = kzalloc(sizeof(struct ath9k_gpio_chip), GFP_KERNEL);
  125. + if (!gc)
  126. + return;
  127. +
  128. + snprintf(gc->label, sizeof(gc->label), "ath9k-%s",
  129. + wiphy_name(sc->hw->wiphy));
  130. + gc->gchip.label = gc->label;
  131. + gc->gchip.base = -1; /* determine base automatically */
  132. + gc->gchip.ngpio = ng;
  133. + gc->gchip.direction_input = ath9k_gpio_pin_cfg_input;
  134. + gc->gchip.direction_output = ath9k_gpio_pin_cfg_output;
  135. + gc->gchip.get_direction = ath9k_gpio_pin_get_dir;
  136. + gc->gchip.get = ath9k_gpio_pin_get;
  137. + gc->gchip.set = ath9k_gpio_pin_set;
  138. + gc->gchip.owner = THIS_MODULE;
  139. +
  140. + if (gpiochip_add(&gc->gchip)) {
  141. + kfree(gc);
  142. + return;
  143. + }
  144. +
  145. + sc->gpiochip = gc;
  146. + gc->sc = sc;
  147. +}
  148. +
  149. +/* remove GPIO chip */
  150. +static void ath9k_unregister_gpio_chip(struct ath_softc *sc)
  151. +{
  152. + struct ath9k_gpio_chip *gc = sc->gpiochip;
  153. +
  154. + if (!gc)
  155. + return;
  156. +
  157. + gpiochip_remove(&gc->gchip);
  158. + kfree(gc);
  159. + sc->gpiochip = NULL;
  160. +}
  161. +
  162. +#else /* CONFIG_GPIOLIB */
  163. +
  164. +static inline void ath9k_register_gpio_chip(struct ath_softc *sc)
  165. +{
  166. +}
  167. +
  168. +static inline void ath9k_unregister_gpio_chip(struct ath_softc *sc)
  169. +{
  170. +}
  171. +
  172. +#endif /* CONFIG_GPIOLIB */
  173. /********************************/
  174. /* LED functions */
  175. /********************************/
  176. -#ifdef CPTCFG_MAC80211_LEDS
  177. -
  178. static void ath_fill_led_pin(struct ath_softc *sc)
  179. {
  180. struct ath_hw *ah = sc->sc_ah;
  181. @@ -80,6 +205,12 @@ static int ath_add_led(struct ath_softc
  182. else
  183. ath9k_hw_set_gpio(sc->sc_ah, gpio->gpio, gpio->active_low);
  184. +#ifdef CONFIG_GPIOLIB
  185. + /* If there is GPIO chip configured, reserve LED pin */
  186. + if (sc->gpiochip)
  187. + gpio_request(sc->gpiochip->gchip.base + gpio->gpio, gpio->name);
  188. +#endif
  189. +
  190. return 0;
  191. }
  192. @@ -136,12 +267,18 @@ void ath_deinit_leds(struct ath_softc *s
  193. while (!list_empty(&sc->leds)) {
  194. led = list_first_entry(&sc->leds, struct ath_led, list);
  195. +#ifdef CONFIG_GPIOLIB
  196. + /* If there is GPIO chip configured, free LED pin */
  197. + if (sc->gpiochip)
  198. + gpio_free(sc->gpiochip->gchip.base + led->gpio->gpio);
  199. +#endif
  200. list_del(&led->list);
  201. ath_led_brightness(&led->cdev, LED_OFF);
  202. led_classdev_unregister(&led->cdev);
  203. ath9k_hw_gpio_free(sc->sc_ah, led->gpio->gpio);
  204. kfree(led);
  205. }
  206. + ath9k_unregister_gpio_chip(sc);
  207. }
  208. void ath_init_leds(struct ath_softc *sc)
  209. @@ -158,6 +295,8 @@ void ath_init_leds(struct ath_softc *sc)
  210. ath_fill_led_pin(sc);
  211. + ath9k_register_gpio_chip(sc);
  212. +
  213. if (pdata && pdata->led_name)
  214. strncpy(led_name, pdata->led_name, sizeof(led_name));
  215. else
  216. @@ -178,6 +317,7 @@ void ath_init_leds(struct ath_softc *sc)
  217. for (i = 0; i < pdata->num_leds; i++)
  218. ath_create_platform_led(sc, &pdata->leds[i]);
  219. }
  220. +
  221. #endif
  222. /*******************/