diff options
author | Rojhalat Ibrahim <imr@rtschenk.de> | 2015-02-11 11:28:02 -0500 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2015-03-05 03:55:42 -0500 |
commit | 331758eef83620eef3f21289f0f44aba094d0503 (patch) | |
tree | 45b24f0b201b6b05333ebcf433a80a41454f6e73 | |
parent | 668585273246f67b0cdafa30dd2da2047a2e1290 (diff) |
gpiolib: add devm_gpiod_get_array and devm_gpiod_put_array functions
Add device managed variants of gpiod_get_array() / gpiod_put_array()
functions for conveniently obtaining and disposing of an entire array
of GPIOs with one function call.
Signed-off-by: Rojhalat Ibrahim <imr@rtschenk.de>
Reviewed-by: Alexandre Courbot <acourbot@nvidia.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
-rw-r--r-- | Documentation/gpio/consumer.txt | 14 | ||||
-rw-r--r-- | drivers/gpio/devres.c | 89 | ||||
-rw-r--r-- | include/linux/gpio/consumer.h | 30 |
3 files changed, 131 insertions, 2 deletions
diff --git a/Documentation/gpio/consumer.txt b/Documentation/gpio/consumer.txt index 2924f2ffcd91..d29a9725c9e5 100644 --- a/Documentation/gpio/consumer.txt +++ b/Documentation/gpio/consumer.txt | |||
@@ -102,11 +102,19 @@ Device-managed variants of these functions are also defined: | |||
102 | const char *con_id, | 102 | const char *con_id, |
103 | enum gpiod_flags flags) | 103 | enum gpiod_flags flags) |
104 | 104 | ||
105 | struct gpio_desc * devm_gpiod_get_index_optional(struct device *dev, | 105 | struct gpio_desc *devm_gpiod_get_index_optional(struct device *dev, |
106 | const char *con_id, | 106 | const char *con_id, |
107 | unsigned int index, | 107 | unsigned int index, |
108 | enum gpiod_flags flags) | 108 | enum gpiod_flags flags) |
109 | 109 | ||
110 | struct gpio_descs *devm_gpiod_get_array(struct device *dev, | ||
111 | const char *con_id, | ||
112 | enum gpiod_flags flags) | ||
113 | |||
114 | struct gpio_descs *devm_gpiod_get_array_optional(struct device *dev, | ||
115 | const char *con_id, | ||
116 | enum gpiod_flags flags) | ||
117 | |||
110 | A GPIO descriptor can be disposed of using the gpiod_put() function: | 118 | A GPIO descriptor can be disposed of using the gpiod_put() function: |
111 | 119 | ||
112 | void gpiod_put(struct gpio_desc *desc) | 120 | void gpiod_put(struct gpio_desc *desc) |
@@ -119,10 +127,12 @@ It is strictly forbidden to use a descriptor after calling these functions. | |||
119 | It is also not allowed to individually release descriptors (using gpiod_put()) | 127 | It is also not allowed to individually release descriptors (using gpiod_put()) |
120 | from an array acquired with gpiod_get_array(). | 128 | from an array acquired with gpiod_get_array(). |
121 | 129 | ||
122 | The device-managed variant is, unsurprisingly: | 130 | The device-managed variants are, unsurprisingly: |
123 | 131 | ||
124 | void devm_gpiod_put(struct device *dev, struct gpio_desc *desc) | 132 | void devm_gpiod_put(struct device *dev, struct gpio_desc *desc) |
125 | 133 | ||
134 | void devm_gpiod_put_array(struct device *dev, struct gpio_descs *descs) | ||
135 | |||
126 | 136 | ||
127 | Using GPIOs | 137 | Using GPIOs |
128 | =========== | 138 | =========== |
diff --git a/drivers/gpio/devres.c b/drivers/gpio/devres.c index 12c2082f968e..ec24da2418b3 100644 --- a/drivers/gpio/devres.c +++ b/drivers/gpio/devres.c | |||
@@ -35,6 +35,20 @@ static int devm_gpiod_match(struct device *dev, void *res, void *data) | |||
35 | return *this == *gpio; | 35 | return *this == *gpio; |
36 | } | 36 | } |
37 | 37 | ||
38 | static void devm_gpiod_release_array(struct device *dev, void *res) | ||
39 | { | ||
40 | struct gpio_descs **descs = res; | ||
41 | |||
42 | gpiod_put_array(*descs); | ||
43 | } | ||
44 | |||
45 | static int devm_gpiod_match_array(struct device *dev, void *res, void *data) | ||
46 | { | ||
47 | struct gpio_descs **this = res, **gpios = data; | ||
48 | |||
49 | return *this == *gpios; | ||
50 | } | ||
51 | |||
38 | /** | 52 | /** |
39 | * devm_gpiod_get - Resource-managed gpiod_get() | 53 | * devm_gpiod_get - Resource-managed gpiod_get() |
40 | * @dev: GPIO consumer | 54 | * @dev: GPIO consumer |
@@ -186,6 +200,66 @@ struct gpio_desc *__must_check __devm_gpiod_get_index_optional(struct device *de | |||
186 | EXPORT_SYMBOL(__devm_gpiod_get_index_optional); | 200 | EXPORT_SYMBOL(__devm_gpiod_get_index_optional); |
187 | 201 | ||
188 | /** | 202 | /** |
203 | * devm_gpiod_get_array - Resource-managed gpiod_get_array() | ||
204 | * @dev: GPIO consumer | ||
205 | * @con_id: function within the GPIO consumer | ||
206 | * @flags: optional GPIO initialization flags | ||
207 | * | ||
208 | * Managed gpiod_get_array(). GPIO descriptors returned from this function are | ||
209 | * automatically disposed on driver detach. See gpiod_get_array() for detailed | ||
210 | * information about behavior and return values. | ||
211 | */ | ||
212 | struct gpio_descs *__must_check devm_gpiod_get_array(struct device *dev, | ||
213 | const char *con_id, | ||
214 | enum gpiod_flags flags) | ||
215 | { | ||
216 | struct gpio_descs **dr; | ||
217 | struct gpio_descs *descs; | ||
218 | |||
219 | dr = devres_alloc(devm_gpiod_release_array, | ||
220 | sizeof(struct gpio_descs *), GFP_KERNEL); | ||
221 | if (!dr) | ||
222 | return ERR_PTR(-ENOMEM); | ||
223 | |||
224 | descs = gpiod_get_array(dev, con_id, flags); | ||
225 | if (IS_ERR(descs)) { | ||
226 | devres_free(dr); | ||
227 | return descs; | ||
228 | } | ||
229 | |||
230 | *dr = descs; | ||
231 | devres_add(dev, dr); | ||
232 | |||
233 | return descs; | ||
234 | } | ||
235 | EXPORT_SYMBOL(devm_gpiod_get_array); | ||
236 | |||
237 | /** | ||
238 | * devm_gpiod_get_array_optional - Resource-managed gpiod_get_array_optional() | ||
239 | * @dev: GPIO consumer | ||
240 | * @con_id: function within the GPIO consumer | ||
241 | * @flags: optional GPIO initialization flags | ||
242 | * | ||
243 | * Managed gpiod_get_array_optional(). GPIO descriptors returned from this | ||
244 | * function are automatically disposed on driver detach. | ||
245 | * See gpiod_get_array_optional() for detailed information about behavior and | ||
246 | * return values. | ||
247 | */ | ||
248 | struct gpio_descs *__must_check | ||
249 | devm_gpiod_get_array_optional(struct device *dev, const char *con_id, | ||
250 | enum gpiod_flags flags) | ||
251 | { | ||
252 | struct gpio_descs *descs; | ||
253 | |||
254 | descs = devm_gpiod_get_array(dev, con_id, flags); | ||
255 | if (IS_ERR(descs) && (PTR_ERR(descs) == -ENOENT)) | ||
256 | return NULL; | ||
257 | |||
258 | return descs; | ||
259 | } | ||
260 | EXPORT_SYMBOL(devm_gpiod_get_array_optional); | ||
261 | |||
262 | /** | ||
189 | * devm_gpiod_put - Resource-managed gpiod_put() | 263 | * devm_gpiod_put - Resource-managed gpiod_put() |
190 | * @desc: GPIO descriptor to dispose of | 264 | * @desc: GPIO descriptor to dispose of |
191 | * | 265 | * |
@@ -200,6 +274,21 @@ void devm_gpiod_put(struct device *dev, struct gpio_desc *desc) | |||
200 | } | 274 | } |
201 | EXPORT_SYMBOL(devm_gpiod_put); | 275 | EXPORT_SYMBOL(devm_gpiod_put); |
202 | 276 | ||
277 | /** | ||
278 | * devm_gpiod_put_array - Resource-managed gpiod_put_array() | ||
279 | * @descs: GPIO descriptor array to dispose of | ||
280 | * | ||
281 | * Dispose of an array of GPIO descriptors obtained with devm_gpiod_get_array(). | ||
282 | * Normally this function will not be called as the GPIOs will be disposed of | ||
283 | * by the resource management code. | ||
284 | */ | ||
285 | void devm_gpiod_put_array(struct device *dev, struct gpio_descs *descs) | ||
286 | { | ||
287 | WARN_ON(devres_release(dev, devm_gpiod_release_array, | ||
288 | devm_gpiod_match_array, &descs)); | ||
289 | } | ||
290 | EXPORT_SYMBOL(devm_gpiod_put_array); | ||
291 | |||
203 | 292 | ||
204 | 293 | ||
205 | 294 | ||
diff --git a/include/linux/gpio/consumer.h b/include/linux/gpio/consumer.h index 33eb52fd0932..3a7c9ffd5ab9 100644 --- a/include/linux/gpio/consumer.h +++ b/include/linux/gpio/consumer.h | |||
@@ -83,7 +83,14 @@ struct gpio_desc *__must_check __devm_gpiod_get_optional(struct device *dev, | |||
83 | struct gpio_desc *__must_check | 83 | struct gpio_desc *__must_check |
84 | __devm_gpiod_get_index_optional(struct device *dev, const char *con_id, | 84 | __devm_gpiod_get_index_optional(struct device *dev, const char *con_id, |
85 | unsigned int index, enum gpiod_flags flags); | 85 | unsigned int index, enum gpiod_flags flags); |
86 | struct gpio_descs *__must_check devm_gpiod_get_array(struct device *dev, | ||
87 | const char *con_id, | ||
88 | enum gpiod_flags flags); | ||
89 | struct gpio_descs *__must_check | ||
90 | devm_gpiod_get_array_optional(struct device *dev, const char *con_id, | ||
91 | enum gpiod_flags flags); | ||
86 | void devm_gpiod_put(struct device *dev, struct gpio_desc *desc); | 92 | void devm_gpiod_put(struct device *dev, struct gpio_desc *desc); |
93 | void devm_gpiod_put_array(struct device *dev, struct gpio_descs *descs); | ||
87 | 94 | ||
88 | int gpiod_get_direction(struct gpio_desc *desc); | 95 | int gpiod_get_direction(struct gpio_desc *desc); |
89 | int gpiod_direction_input(struct gpio_desc *desc); | 96 | int gpiod_direction_input(struct gpio_desc *desc); |
@@ -228,6 +235,20 @@ __devm_gpiod_get_index_optional(struct device *dev, const char *con_id, | |||
228 | return ERR_PTR(-ENOSYS); | 235 | return ERR_PTR(-ENOSYS); |
229 | } | 236 | } |
230 | 237 | ||
238 | static inline struct gpio_descs *__must_check | ||
239 | devm_gpiod_get_array(struct device *dev, const char *con_id, | ||
240 | enum gpiod_flags flags) | ||
241 | { | ||
242 | return ERR_PTR(-ENOSYS); | ||
243 | } | ||
244 | |||
245 | static inline struct gpio_descs *__must_check | ||
246 | devm_gpiod_get_array_optional(struct device *dev, const char *con_id, | ||
247 | enum gpiod_flags flags) | ||
248 | { | ||
249 | return ERR_PTR(-ENOSYS); | ||
250 | } | ||
251 | |||
231 | static inline void devm_gpiod_put(struct device *dev, struct gpio_desc *desc) | 252 | static inline void devm_gpiod_put(struct device *dev, struct gpio_desc *desc) |
232 | { | 253 | { |
233 | might_sleep(); | 254 | might_sleep(); |
@@ -236,6 +257,15 @@ static inline void devm_gpiod_put(struct device *dev, struct gpio_desc *desc) | |||
236 | WARN_ON(1); | 257 | WARN_ON(1); |
237 | } | 258 | } |
238 | 259 | ||
260 | static inline void devm_gpiod_put_array(struct device *dev, | ||
261 | struct gpio_descs *descs) | ||
262 | { | ||
263 | might_sleep(); | ||
264 | |||
265 | /* GPIO can never have been requested */ | ||
266 | WARN_ON(1); | ||
267 | } | ||
268 | |||
239 | 269 | ||
240 | static inline int gpiod_get_direction(const struct gpio_desc *desc) | 270 | static inline int gpiod_get_direction(const struct gpio_desc *desc) |
241 | { | 271 | { |