diff options
author | Thierry Reding <treding@nvidia.com> | 2014-04-25 11:10:06 -0400 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2014-05-09 07:48:30 -0400 |
commit | 29a1f2333e07bbbecb920cc78fd035fe8f53207a (patch) | |
tree | b2cb50d4c41ff4d1337cca888da3840f6f0d4d84 | |
parent | 91329132c909bbeb27699556b98b7f745ddb2ed9 (diff) |
gpio: Add helpers for optional GPIOs
Introduce gpiod_get_optional() and gpiod_get_index_optional() helpers
that make it easier for drivers to handle optional GPIOs.
Currently in order to handle optional GPIOs, a driver needs to special
case error handling for -ENOENT, such as this:
gpio = gpiod_get(dev, "foo");
if (IS_ERR(gpio)) {
if (PTR_ERR(gpio) != -ENOENT)
return PTR_ERR(gpio);
gpio = NULL;
}
if (gpio) {
/* set up GPIO */
}
With these new helpers the above is reduced to:
gpio = gpiod_get_optional(dev, "foo");
if (IS_ERR(gpio))
return PTR_ERR(gpio);
if (gpio) {
/* set up GPIO */
}
While at it, device-managed variants of these functions are also
provided.
Signed-off-by: Thierry Reding <treding@nvidia.com>
Reviewed-by: Alexandre Courbot <acourbot@nvidia.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
-rw-r--r-- | Documentation/driver-model/devres.txt | 2 | ||||
-rw-r--r-- | drivers/gpio/devres.c | 43 | ||||
-rw-r--r-- | drivers/gpio/gpiolib.c | 43 | ||||
-rw-r--r-- | include/linux/gpio/consumer.h | 40 |
4 files changed, 128 insertions, 0 deletions
diff --git a/Documentation/driver-model/devres.txt b/Documentation/driver-model/devres.txt index 8ff1167cfedf..10b8c5d2c797 100644 --- a/Documentation/driver-model/devres.txt +++ b/Documentation/driver-model/devres.txt | |||
@@ -312,4 +312,6 @@ SPI | |||
312 | GPIO | 312 | GPIO |
313 | devm_gpiod_get() | 313 | devm_gpiod_get() |
314 | devm_gpiod_get_index() | 314 | devm_gpiod_get_index() |
315 | devm_gpiod_get_optional() | ||
316 | devm_gpiod_get_index_optional() | ||
315 | devm_gpiod_put() | 317 | devm_gpiod_put() |
diff --git a/drivers/gpio/devres.c b/drivers/gpio/devres.c index 307464fd015f..65978cf85f79 100644 --- a/drivers/gpio/devres.c +++ b/drivers/gpio/devres.c | |||
@@ -52,6 +52,22 @@ struct gpio_desc *__must_check devm_gpiod_get(struct device *dev, | |||
52 | EXPORT_SYMBOL(devm_gpiod_get); | 52 | EXPORT_SYMBOL(devm_gpiod_get); |
53 | 53 | ||
54 | /** | 54 | /** |
55 | * devm_gpiod_get_optional - Resource-managed gpiod_get_optional() | ||
56 | * @dev: GPIO consumer | ||
57 | * @con_id: function within the GPIO consumer | ||
58 | * | ||
59 | * Managed gpiod_get_optional(). GPIO descriptors returned from this function | ||
60 | * are automatically disposed on driver detach. See gpiod_get_optional() for | ||
61 | * detailed information about behavior and return values. | ||
62 | */ | ||
63 | struct gpio_desc *__must_check devm_gpiod_get_optional(struct device *dev, | ||
64 | const char *con_id) | ||
65 | { | ||
66 | return devm_gpiod_get_index_optional(dev, con_id, 0); | ||
67 | } | ||
68 | EXPORT_SYMBOL(devm_gpiod_get_optional); | ||
69 | |||
70 | /** | ||
55 | * devm_gpiod_get_index - Resource-managed gpiod_get_index() | 71 | * devm_gpiod_get_index - Resource-managed gpiod_get_index() |
56 | * @dev: GPIO consumer | 72 | * @dev: GPIO consumer |
57 | * @con_id: function within the GPIO consumer | 73 | * @con_id: function within the GPIO consumer |
@@ -87,6 +103,33 @@ struct gpio_desc *__must_check devm_gpiod_get_index(struct device *dev, | |||
87 | EXPORT_SYMBOL(devm_gpiod_get_index); | 103 | EXPORT_SYMBOL(devm_gpiod_get_index); |
88 | 104 | ||
89 | /** | 105 | /** |
106 | * devm_gpiod_get_index_optional - Resource-managed gpiod_get_index_optional() | ||
107 | * @dev: GPIO consumer | ||
108 | * @con_id: function within the GPIO consumer | ||
109 | * @index: index of the GPIO to obtain in the consumer | ||
110 | * | ||
111 | * Managed gpiod_get_index_optional(). GPIO descriptors returned from this | ||
112 | * function are automatically disposed on driver detach. See | ||
113 | * gpiod_get_index_optional() for detailed information about behavior and | ||
114 | * return values. | ||
115 | */ | ||
116 | struct gpio_desc *__must_check devm_gpiod_get_index_optional(struct device *dev, | ||
117 | const char *con_id, | ||
118 | unsigned int index) | ||
119 | { | ||
120 | struct gpio_desc *desc; | ||
121 | |||
122 | desc = devm_gpiod_get_index(dev, con_id, index); | ||
123 | if (IS_ERR(desc)) { | ||
124 | if (PTR_ERR(desc) == -ENOENT) | ||
125 | return NULL; | ||
126 | } | ||
127 | |||
128 | return desc; | ||
129 | } | ||
130 | EXPORT_SYMBOL(devm_gpiod_get_index_optional); | ||
131 | |||
132 | /** | ||
90 | * devm_gpiod_put - Resource-managed gpiod_put() | 133 | * devm_gpiod_put - Resource-managed gpiod_put() |
91 | * @desc: GPIO descriptor to dispose of | 134 | * @desc: GPIO descriptor to dispose of |
92 | * | 135 | * |
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 4ad110e793c5..d9c9cb4665db 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c | |||
@@ -2738,6 +2738,22 @@ struct gpio_desc *__must_check gpiod_get(struct device *dev, const char *con_id) | |||
2738 | EXPORT_SYMBOL_GPL(gpiod_get); | 2738 | EXPORT_SYMBOL_GPL(gpiod_get); |
2739 | 2739 | ||
2740 | /** | 2740 | /** |
2741 | * gpiod_get_optional - obtain an optional GPIO for a given GPIO function | ||
2742 | * @dev: GPIO consumer, can be NULL for system-global GPIOs | ||
2743 | * @con_id: function within the GPIO consumer | ||
2744 | * | ||
2745 | * This is equivalent to gpiod_get(), except that when no GPIO was assigned to | ||
2746 | * the requested function it will return NULL. This is convenient for drivers | ||
2747 | * that need to handle optional GPIOs. | ||
2748 | */ | ||
2749 | struct gpio_desc *__must_check gpiod_get_optional(struct device *dev, | ||
2750 | const char *con_id) | ||
2751 | { | ||
2752 | return gpiod_get_index_optional(dev, con_id, 0); | ||
2753 | } | ||
2754 | EXPORT_SYMBOL_GPL(gpiod_get_optional); | ||
2755 | |||
2756 | /** | ||
2741 | * gpiod_get_index - obtain a GPIO from a multi-index GPIO function | 2757 | * gpiod_get_index - obtain a GPIO from a multi-index GPIO function |
2742 | * @dev: GPIO consumer, can be NULL for system-global GPIOs | 2758 | * @dev: GPIO consumer, can be NULL for system-global GPIOs |
2743 | * @con_id: function within the GPIO consumer | 2759 | * @con_id: function within the GPIO consumer |
@@ -2800,6 +2816,33 @@ struct gpio_desc *__must_check gpiod_get_index(struct device *dev, | |||
2800 | EXPORT_SYMBOL_GPL(gpiod_get_index); | 2816 | EXPORT_SYMBOL_GPL(gpiod_get_index); |
2801 | 2817 | ||
2802 | /** | 2818 | /** |
2819 | * gpiod_get_index_optional - obtain an optional GPIO from a multi-index GPIO | ||
2820 | * function | ||
2821 | * @dev: GPIO consumer, can be NULL for system-global GPIOs | ||
2822 | * @con_id: function within the GPIO consumer | ||
2823 | * @index: index of the GPIO to obtain in the consumer | ||
2824 | * | ||
2825 | * This is equivalent to gpiod_get_index(), except that when no GPIO with the | ||
2826 | * specified index was assigned to the requested function it will return NULL. | ||
2827 | * This is convenient for drivers that need to handle optional GPIOs. | ||
2828 | */ | ||
2829 | struct gpio_desc *__must_check gpiod_get_index_optional(struct device *dev, | ||
2830 | const char *con_id, | ||
2831 | unsigned int index) | ||
2832 | { | ||
2833 | struct gpio_desc *desc; | ||
2834 | |||
2835 | desc = gpiod_get_index(dev, con_id, index); | ||
2836 | if (IS_ERR(desc)) { | ||
2837 | if (PTR_ERR(desc) == -ENOENT) | ||
2838 | return NULL; | ||
2839 | } | ||
2840 | |||
2841 | return desc; | ||
2842 | } | ||
2843 | EXPORT_SYMBOL_GPL(gpiod_get_index_optional); | ||
2844 | |||
2845 | /** | ||
2803 | * gpiod_put - dispose of a GPIO descriptor | 2846 | * gpiod_put - dispose of a GPIO descriptor |
2804 | * @desc: GPIO descriptor to dispose of | 2847 | * @desc: GPIO descriptor to dispose of |
2805 | * | 2848 | * |
diff --git a/include/linux/gpio/consumer.h b/include/linux/gpio/consumer.h index bed128e8f4b1..6a37ef0dc59c 100644 --- a/include/linux/gpio/consumer.h +++ b/include/linux/gpio/consumer.h | |||
@@ -23,6 +23,12 @@ struct gpio_desc *__must_check gpiod_get(struct device *dev, | |||
23 | struct gpio_desc *__must_check gpiod_get_index(struct device *dev, | 23 | struct gpio_desc *__must_check gpiod_get_index(struct device *dev, |
24 | const char *con_id, | 24 | const char *con_id, |
25 | unsigned int idx); | 25 | unsigned int idx); |
26 | struct gpio_desc *__must_check gpiod_get_optional(struct device *dev, | ||
27 | const char *con_id); | ||
28 | struct gpio_desc *__must_check gpiod_get_index_optional(struct device *dev, | ||
29 | const char *con_id, | ||
30 | unsigned int index); | ||
31 | |||
26 | void gpiod_put(struct gpio_desc *desc); | 32 | void gpiod_put(struct gpio_desc *desc); |
27 | 33 | ||
28 | struct gpio_desc *__must_check devm_gpiod_get(struct device *dev, | 34 | struct gpio_desc *__must_check devm_gpiod_get(struct device *dev, |
@@ -30,6 +36,12 @@ struct gpio_desc *__must_check devm_gpiod_get(struct device *dev, | |||
30 | struct gpio_desc *__must_check devm_gpiod_get_index(struct device *dev, | 36 | struct gpio_desc *__must_check devm_gpiod_get_index(struct device *dev, |
31 | const char *con_id, | 37 | const char *con_id, |
32 | unsigned int idx); | 38 | unsigned int idx); |
39 | struct gpio_desc *__must_check devm_gpiod_get_optional(struct device *dev, | ||
40 | const char *con_id); | ||
41 | struct gpio_desc *__must_check | ||
42 | devm_gpiod_get_index_optional(struct device *dev, const char *con_id, | ||
43 | unsigned int index); | ||
44 | |||
33 | void devm_gpiod_put(struct device *dev, struct gpio_desc *desc); | 45 | void devm_gpiod_put(struct device *dev, struct gpio_desc *desc); |
34 | 46 | ||
35 | int gpiod_get_direction(const struct gpio_desc *desc); | 47 | int gpiod_get_direction(const struct gpio_desc *desc); |
@@ -73,6 +85,20 @@ static inline struct gpio_desc *__must_check gpiod_get_index(struct device *dev, | |||
73 | { | 85 | { |
74 | return ERR_PTR(-ENOSYS); | 86 | return ERR_PTR(-ENOSYS); |
75 | } | 87 | } |
88 | |||
89 | static inline struct gpio_desc *__must_check | ||
90 | gpiod_get_optional(struct device *dev, const char *con_id) | ||
91 | { | ||
92 | return ERR_PTR(-ENOSYS); | ||
93 | } | ||
94 | |||
95 | static inline struct gpio_desc *__must_check | ||
96 | gpiod_get_index_optional(struct device *dev, const char *con_id, | ||
97 | unsigned int index) | ||
98 | { | ||
99 | return ERR_PTR(-ENOSYS); | ||
100 | } | ||
101 | |||
76 | static inline void gpiod_put(struct gpio_desc *desc) | 102 | static inline void gpiod_put(struct gpio_desc *desc) |
77 | { | 103 | { |
78 | might_sleep(); | 104 | might_sleep(); |
@@ -93,6 +119,20 @@ struct gpio_desc *__must_check devm_gpiod_get_index(struct device *dev, | |||
93 | { | 119 | { |
94 | return ERR_PTR(-ENOSYS); | 120 | return ERR_PTR(-ENOSYS); |
95 | } | 121 | } |
122 | |||
123 | static inline struct gpio_desc *__must_check | ||
124 | devm_gpiod_get_optional(struct device *dev, const char *con_id) | ||
125 | { | ||
126 | return ERR_PTR(-ENOSYS); | ||
127 | } | ||
128 | |||
129 | static inline struct gpio_desc *__must_check | ||
130 | devm_gpiod_get_index_optional(struct device *dev, const char *con_id, | ||
131 | unsigned int index) | ||
132 | { | ||
133 | return ERR_PTR(-ENOSYS); | ||
134 | } | ||
135 | |||
96 | static inline void devm_gpiod_put(struct device *dev, struct gpio_desc *desc) | 136 | static inline void devm_gpiod_put(struct device *dev, struct gpio_desc *desc) |
97 | { | 137 | { |
98 | might_sleep(); | 138 | might_sleep(); |