1
0

548-ath9k_enable_gpio_chip.patch 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  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. @@ -973,6 +974,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. @@ -1027,6 +1036,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,135 @@
  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. + struct ath_hw *ah = sc->sc_ah;
  115. +
  116. + gc = kzalloc(sizeof(struct ath9k_gpio_chip), GFP_KERNEL);
  117. + if (!gc)
  118. + return;
  119. +
  120. + snprintf(gc->label, sizeof(gc->label), "ath9k-%s",
  121. + wiphy_name(sc->hw->wiphy));
  122. +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,5,0)
  123. + gc->gchip.parent = sc->dev;
  124. +#else
  125. + gc->gchip.dev = sc->dev;
  126. +#endif
  127. + gc->gchip.label = gc->label;
  128. + gc->gchip.base = -1; /* determine base automatically */
  129. + gc->gchip.ngpio = ah->caps.num_gpio_pins;
  130. + gc->gchip.direction_input = ath9k_gpio_pin_cfg_input;
  131. + gc->gchip.direction_output = ath9k_gpio_pin_cfg_output;
  132. + gc->gchip.get_direction = ath9k_gpio_pin_get_dir;
  133. + gc->gchip.get = ath9k_gpio_pin_get;
  134. + gc->gchip.set = ath9k_gpio_pin_set;
  135. +
  136. + if (gpiochip_add(&gc->gchip)) {
  137. + kfree(gc);
  138. + return;
  139. + }
  140. +
  141. + gc->gchip.owner = NULL;
  142. + sc->gpiochip = gc;
  143. + gc->sc = sc;
  144. +}
  145. +
  146. +/* remove GPIO chip */
  147. +static void ath9k_unregister_gpio_chip(struct ath_softc *sc)
  148. +{
  149. + struct ath9k_gpio_chip *gc = sc->gpiochip;
  150. +
  151. + if (!gc)
  152. + return;
  153. +
  154. + gpiochip_remove(&gc->gchip);
  155. + kfree(gc);
  156. + sc->gpiochip = NULL;
  157. +}
  158. +
  159. +#else /* CONFIG_GPIOLIB */
  160. +
  161. +static inline void ath9k_register_gpio_chip(struct ath_softc *sc)
  162. +{
  163. +}
  164. +
  165. +static inline void ath9k_unregister_gpio_chip(struct ath_softc *sc)
  166. +{
  167. +}
  168. +
  169. +#endif /* CONFIG_GPIOLIB */
  170. /********************************/
  171. /* LED functions */
  172. /********************************/
  173. -#ifdef CPTCFG_MAC80211_LEDS
  174. -
  175. static void ath_fill_led_pin(struct ath_softc *sc)
  176. {
  177. struct ath_hw *ah = sc->sc_ah;
  178. @@ -80,6 +202,12 @@ static int ath_add_led(struct ath_softc
  179. else
  180. ath9k_hw_set_gpio(sc->sc_ah, gpio->gpio, gpio->active_low);
  181. +#ifdef CONFIG_GPIOLIB
  182. + /* If there is GPIO chip configured, reserve LED pin */
  183. + if (sc->gpiochip)
  184. + gpio_request(sc->gpiochip->gchip.base + gpio->gpio, gpio->name);
  185. +#endif
  186. +
  187. return 0;
  188. }
  189. @@ -136,12 +264,18 @@ void ath_deinit_leds(struct ath_softc *s
  190. while (!list_empty(&sc->leds)) {
  191. led = list_first_entry(&sc->leds, struct ath_led, list);
  192. +#ifdef CONFIG_GPIOLIB
  193. + /* If there is GPIO chip configured, free LED pin */
  194. + if (sc->gpiochip)
  195. + gpio_free(sc->gpiochip->gchip.base + led->gpio->gpio);
  196. +#endif
  197. list_del(&led->list);
  198. ath_led_brightness(&led->cdev, LED_OFF);
  199. led_classdev_unregister(&led->cdev);
  200. ath9k_hw_gpio_free(sc->sc_ah, led->gpio->gpio);
  201. kfree(led);
  202. }
  203. + ath9k_unregister_gpio_chip(sc);
  204. }
  205. void ath_init_leds(struct ath_softc *sc)
  206. @@ -158,6 +292,8 @@ void ath_init_leds(struct ath_softc *sc)
  207. ath_fill_led_pin(sc);
  208. + ath9k_register_gpio_chip(sc);
  209. +
  210. if (pdata && pdata->led_name)
  211. strncpy(led_name, pdata->led_name, sizeof(led_name));
  212. else
  213. @@ -178,6 +314,7 @@ void ath_init_leds(struct ath_softc *sc)
  214. for (i = 0; i < pdata->num_leds; i++)
  215. ath_create_platform_led(sc, &pdata->leds[i]);
  216. }
  217. +
  218. #endif
  219. /*******************/