0025-GPIO-add-gpio_export_with_name.patch 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  1. From 4bf583c17735a759064bc6177718f05fd990a7ab Mon Sep 17 00:00:00 2001
  2. From: John Crispin <[email protected]>
  3. Date: Sun, 23 Jun 2013 00:16:22 +0200
  4. Subject: [PATCH 25/34] GPIO: add gpio_export_with_name
  5. http://lists.infradead.org/pipermail/linux-arm-kernel/2012-November/133856.html
  6. Signed-off-by: John Crispin <[email protected]>
  7. ---
  8. Documentation/devicetree/bindings/gpio/gpio.txt | 60 ++++++++++++++++++++
  9. drivers/gpio/gpiolib-of.c | 68 +++++++++++++++++++++++
  10. drivers/gpio/gpiolib.c | 24 +++++---
  11. include/asm-generic/gpio.h | 6 +-
  12. include/linux/gpio.h | 26 ++++++++-
  13. 5 files changed, 172 insertions(+), 12 deletions(-)
  14. diff --git a/Documentation/devicetree/bindings/gpio/gpio.txt b/Documentation/devicetree/bindings/gpio/gpio.txt
  15. index d933af3..c264748 100644
  16. --- a/Documentation/devicetree/bindings/gpio/gpio.txt
  17. +++ b/Documentation/devicetree/bindings/gpio/gpio.txt
  18. @@ -112,3 +112,63 @@ where,
  19. The pinctrl node must have "#gpio-range-cells" property to show number of
  20. arguments to pass with phandle from gpio controllers node.
  21. +
  22. +3) gpio-export
  23. +--------------
  24. +
  25. +gpio-export will allow you to automatically export gpio
  26. +
  27. +required properties:
  28. +- compatible: Should be "gpio-export"
  29. +
  30. +in each child node will reprensent a gpio or if no name is specified
  31. +a list of gpio to export
  32. +
  33. +required properties:
  34. +- gpios: gpio to export
  35. +
  36. +optional properties:
  37. + - gpio-export,name: export name
  38. + - gpio-export,output: to set the as output with default value
  39. + if no present gpio as input
  40. + - pio-export,direction_may_change: boolean to allow the direction to be controllable
  41. +
  42. +Example:
  43. +
  44. +
  45. +gpio_export {
  46. + compatible = "gpio-export";
  47. + #size-cells = <0>;
  48. +
  49. + in {
  50. + gpio-export,name = "in";
  51. + gpios = <&pioC 20 0>;
  52. + };
  53. +
  54. + out {
  55. + gpio-export,name = "out";
  56. + gpio-export,output = <1>;
  57. + gpio-export,direction_may_change;
  58. + gpios = <&pioC 21 0>;
  59. + };
  60. +
  61. + in_out {
  62. + gpio-export,name = "in_out";
  63. + gpio-export,direction_may_change;
  64. + gpios = <&pioC 21 0>;
  65. + };
  66. +
  67. + gpios_in {
  68. + gpios = <&pioB 0 0
  69. + &pioB 3 0
  70. + &pioC 4 0>;
  71. + gpio-export,direction_may_change;
  72. + };
  73. +
  74. + gpios_out {
  75. + gpios = <&pioB 1 0
  76. + &pioB 2 0
  77. + &pioC 3 0>;
  78. + gpio-export,output = <1>;
  79. + };
  80. +};
  81. diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c
  82. index 665f953..15ec5e5 100644
  83. --- a/drivers/gpio/gpiolib-of.c
  84. +++ b/drivers/gpio/gpiolib-of.c
  85. @@ -21,6 +21,8 @@
  86. #include <linux/of_gpio.h>
  87. #include <linux/pinctrl/pinctrl.h>
  88. #include <linux/slab.h>
  89. +#include <linux/init.h>
  90. +#include <linux/platform_device.h>
  91. /* Private data structure for of_gpiochip_find_and_xlate */
  92. struct gg_data {
  93. @@ -242,3 +244,69 @@ void of_gpiochip_remove(struct gpio_chip *chip)
  94. if (chip->of_node)
  95. of_node_put(chip->of_node);
  96. }
  97. +
  98. +static struct of_device_id gpio_export_ids[] = {
  99. + { .compatible = "gpio-export" },
  100. + { /* sentinel */ }
  101. +};
  102. +
  103. +static int __init of_gpio_export_probe(struct platform_device *pdev)
  104. +{
  105. + struct device_node *np = pdev->dev.of_node;
  106. + struct device_node *cnp;
  107. + u32 val;
  108. + int nb = 0;
  109. +
  110. + for_each_child_of_node(np, cnp) {
  111. + const char *name = NULL;
  112. + int gpio;
  113. + bool dmc;
  114. + int max_gpio = 1;
  115. + int i;
  116. +
  117. + of_property_read_string(cnp, "gpio-export,name", &name);
  118. +
  119. + if (!name)
  120. + max_gpio = of_gpio_count(cnp);
  121. +
  122. + for (i = 0; i < max_gpio; i++) {
  123. + unsigned flags = 0;
  124. + enum of_gpio_flags of_flags;
  125. +
  126. + gpio = of_get_gpio_flags(cnp, i, &of_flags);
  127. +
  128. + if (of_flags == OF_GPIO_ACTIVE_LOW)
  129. + flags |= GPIOF_ACTIVE_LOW;
  130. +
  131. + if (!of_property_read_u32(cnp, "gpio-export,output", &val))
  132. + flags |= val ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW;
  133. + else
  134. + flags |= GPIOF_IN;
  135. +
  136. + if (devm_gpio_request_one(&pdev->dev, gpio, flags, name ? name : of_node_full_name(np)))
  137. + continue;
  138. +
  139. + dmc = of_property_read_bool(cnp, "gpio-export,direction_may_change");
  140. + gpio_export_with_name(gpio, dmc, name);
  141. + nb++;
  142. + }
  143. + }
  144. +
  145. + dev_info(&pdev->dev, "%d gpio(s) exported\n", nb);
  146. +
  147. + return 0;
  148. +}
  149. +
  150. +static struct platform_driver gpio_export_driver = {
  151. + .driver = {
  152. + .name = "gpio-export",
  153. + .owner = THIS_MODULE,
  154. + .of_match_table = of_match_ptr(gpio_export_ids),
  155. + },
  156. +};
  157. +
  158. +static int __init of_gpio_export_init(void)
  159. +{
  160. + return platform_driver_probe(&gpio_export_driver, of_gpio_export_probe);
  161. +}
  162. +device_initcall(of_gpio_export_init);
  163. diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
  164. index c2534d6..8697c82 100644
  165. --- a/drivers/gpio/gpiolib.c
  166. +++ b/drivers/gpio/gpiolib.c
  167. @@ -96,7 +96,7 @@ static int gpiod_get_value(const struct gpio_desc *desc);
  168. static void gpiod_set_value(struct gpio_desc *desc, int value);
  169. static int gpiod_cansleep(const struct gpio_desc *desc);
  170. static int gpiod_to_irq(const struct gpio_desc *desc);
  171. -static int gpiod_export(struct gpio_desc *desc, bool direction_may_change);
  172. +static int gpiod_export(struct gpio_desc *desc, bool direction_may_change, const char *name);
  173. static int gpiod_export_link(struct device *dev, const char *name,
  174. struct gpio_desc *desc);
  175. static int gpiod_sysfs_set_active_low(struct gpio_desc *desc, int value);
  176. @@ -674,7 +674,7 @@ static ssize_t export_store(struct class *class,
  177. status = -ENODEV;
  178. goto done;
  179. }
  180. - status = gpiod_export(desc, true);
  181. + status = gpiod_export(desc, true, NULL);
  182. if (status < 0)
  183. gpiod_free(desc);
  184. else
  185. @@ -736,9 +736,10 @@ static struct class gpio_class = {
  186. /**
  187. - * gpio_export - export a GPIO through sysfs
  188. + * gpio_export_with_name - export a GPIO through sysfs
  189. * @gpio: gpio to make available, already requested
  190. * @direction_may_change: true if userspace may change gpio direction
  191. + * @name: gpio name
  192. * Context: arch_initcall or later
  193. *
  194. * When drivers want to make a GPIO accessible to userspace after they
  195. @@ -750,7 +751,7 @@ static struct class gpio_class = {
  196. *
  197. * Returns zero on success, else an error.
  198. */
  199. -static int gpiod_export(struct gpio_desc *desc, bool direction_may_change)
  200. +static int gpiod_export(struct gpio_desc *desc, bool direction_may_change, const char *name)
  201. {
  202. unsigned long flags;
  203. int status;
  204. @@ -783,6 +784,8 @@ static int gpiod_export(struct gpio_desc *desc, bool direction_may_change)
  205. goto fail_unlock;
  206. }
  207. + if (name)
  208. + ioname = name;
  209. if (!desc->chip->direction_input || !desc->chip->direction_output)
  210. direction_may_change = false;
  211. spin_unlock_irqrestore(&gpio_lock, flags);
  212. @@ -829,11 +832,11 @@ fail_unlock:
  213. return status;
  214. }
  215. -int gpio_export(unsigned gpio, bool direction_may_change)
  216. +int gpio_export_with_name(unsigned gpio, bool direction_may_change, const char *name)
  217. {
  218. - return gpiod_export(gpio_to_desc(gpio), direction_may_change);
  219. + return gpiod_export(gpio_to_desc(gpio), direction_may_change, name);
  220. }
  221. -EXPORT_SYMBOL_GPL(gpio_export);
  222. +EXPORT_SYMBOL_GPL(gpio_export_with_name);
  223. static int match_export(struct device *dev, const void *data)
  224. {
  225. @@ -1092,7 +1095,7 @@ static inline void gpiochip_unexport(struct gpio_chip *chip)
  226. }
  227. static inline int gpiod_export(struct gpio_desc *desc,
  228. - bool direction_may_change)
  229. + bool direction_may_change, const char *name)
  230. {
  231. return -ENOSYS;
  232. }
  233. @@ -1521,6 +1524,9 @@ int gpio_request_one(unsigned gpio, unsigned long flags, const char *label)
  234. if (flags & GPIOF_OPEN_SOURCE)
  235. set_bit(FLAG_OPEN_SOURCE, &desc->flags);
  236. + if (flags & GPIOF_ACTIVE_LOW)
  237. + set_bit(FLAG_ACTIVE_LOW, &gpio_desc[gpio].flags);
  238. +
  239. if (flags & GPIOF_DIR_IN)
  240. err = gpiod_direction_input(desc);
  241. else
  242. @@ -1531,7 +1537,7 @@ int gpio_request_one(unsigned gpio, unsigned long flags, const char *label)
  243. goto free_gpio;
  244. if (flags & GPIOF_EXPORT) {
  245. - err = gpiod_export(desc, flags & GPIOF_EXPORT_CHANGEABLE);
  246. + err = gpiod_export(desc, flags & GPIOF_EXPORT_CHANGEABLE, NULL);
  247. if (err)
  248. goto free_gpio;
  249. }
  250. diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h
  251. index bde6469..3290572 100644
  252. --- a/include/asm-generic/gpio.h
  253. +++ b/include/asm-generic/gpio.h
  254. @@ -202,7 +202,8 @@ extern void gpio_free_array(const struct gpio *array, size_t num);
  255. * A sysfs interface can be exported by individual drivers if they want,
  256. * but more typically is configured entirely from userspace.
  257. */
  258. -extern int gpio_export(unsigned gpio, bool direction_may_change);
  259. +extern int gpio_export_with_name(unsigned gpio, bool direction_may_change,
  260. + const char *name);
  261. extern int gpio_export_link(struct device *dev, const char *name,
  262. unsigned gpio);
  263. extern int gpio_sysfs_set_active_low(unsigned gpio, int value);
  264. @@ -284,7 +285,8 @@ struct device;
  265. /* sysfs support is only available with gpiolib, where it's optional */
  266. -static inline int gpio_export(unsigned gpio, bool direction_may_change)
  267. +static inline int gpio_export_with_name(unsigned gpio,
  268. + bool direction_may_change, const char *name)
  269. {
  270. return -ENOSYS;
  271. }
  272. diff --git a/include/linux/gpio.h b/include/linux/gpio.h
  273. index 552e3f4..07bbbcc7 100644
  274. --- a/include/linux/gpio.h
  275. +++ b/include/linux/gpio.h
  276. @@ -27,6 +27,9 @@
  277. #define GPIOF_EXPORT_DIR_FIXED (GPIOF_EXPORT)
  278. #define GPIOF_EXPORT_DIR_CHANGEABLE (GPIOF_EXPORT | GPIOF_EXPORT_CHANGEABLE)
  279. +#define GPIOF_ACTIVE_LOW (1 << 6)
  280. +
  281. +
  282. /**
  283. * struct gpio - a structure describing a GPIO with configuration
  284. * @gpio: the GPIO number
  285. @@ -169,7 +172,8 @@ static inline void gpio_set_value_cansleep(unsigned gpio, int value)
  286. WARN_ON(1);
  287. }
  288. -static inline int gpio_export(unsigned gpio, bool direction_may_change)
  289. +static inline int gpio_export_with_name(unsigned gpio,
  290. + bool direction_may_change, const char *name)
  291. {
  292. /* GPIO can never have been requested or set as {in,out}put */
  293. WARN_ON(1);
  294. @@ -236,4 +240,24 @@ int devm_gpio_request_one(struct device *dev, unsigned gpio,
  295. unsigned long flags, const char *label);
  296. void devm_gpio_free(struct device *dev, unsigned int gpio);
  297. +/**
  298. + * gpio_export - export a GPIO through sysfs
  299. + * @gpio: gpio to make available, already requested
  300. + * @direction_may_change: true if userspace may change gpio direction
  301. + * Context: arch_initcall or later
  302. + *
  303. + * When drivers want to make a GPIO accessible to userspace after they
  304. + * have requested it -- perhaps while debugging, or as part of their
  305. + * public interface -- they may use this routine. If the GPIO can
  306. + * change direction (some can't) and the caller allows it, userspace
  307. + * will see "direction" sysfs attribute which may be used to change
  308. + * the gpio's direction. A "value" attribute will always be provided.
  309. + *
  310. + * Returns zero on success, else an error.
  311. + */
  312. +static inline int gpio_export(unsigned gpio,bool direction_may_change)
  313. +{
  314. + return gpio_export_with_name(gpio, direction_may_change, NULL);
  315. +}
  316. +
  317. #endif /* __LINUX_GPIO_H */
  318. --
  319. 1.7.10.4