1
2
3
4
5
6
7
8
9#include <linux/module.h>
10#include <linux/err.h>
11#include <linux/gpio.h>
12#include <linux/gpio/consumer.h>
13#include <linux/device.h>
14#include <linux/gfp.h>
15
16#include "gpiolib.h"
17
18static void devm_gpiod_release(struct device *dev, void *res)
19{
20 struct gpio_desc **desc = res;
21
22 gpiod_put(*desc);
23}
24
25static int devm_gpiod_match(struct device *dev, void *res, void *data)
26{
27 struct gpio_desc **this = res, **gpio = data;
28
29 return *this == *gpio;
30}
31
32static void devm_gpiod_release_array(struct device *dev, void *res)
33{
34 struct gpio_descs **descs = res;
35
36 gpiod_put_array(*descs);
37}
38
39static int devm_gpiod_match_array(struct device *dev, void *res, void *data)
40{
41 struct gpio_descs **this = res, **gpios = data;
42
43 return *this == *gpios;
44}
45
46
47
48
49
50
51
52
53
54
55
56struct gpio_desc *__must_check devm_gpiod_get(struct device *dev,
57 const char *con_id,
58 enum gpiod_flags flags)
59{
60 return devm_gpiod_get_index(dev, con_id, 0, flags);
61}
62EXPORT_SYMBOL_GPL(devm_gpiod_get);
63
64
65
66
67
68
69
70
71
72
73
74struct gpio_desc *__must_check devm_gpiod_get_optional(struct device *dev,
75 const char *con_id,
76 enum gpiod_flags flags)
77{
78 return devm_gpiod_get_index_optional(dev, con_id, 0, flags);
79}
80EXPORT_SYMBOL_GPL(devm_gpiod_get_optional);
81
82
83
84
85
86
87
88
89
90
91
92
93struct gpio_desc *__must_check devm_gpiod_get_index(struct device *dev,
94 const char *con_id,
95 unsigned int idx,
96 enum gpiod_flags flags)
97{
98 struct gpio_desc **dr;
99 struct gpio_desc *desc;
100
101 desc = gpiod_get_index(dev, con_id, idx, flags);
102 if (IS_ERR(desc))
103 return desc;
104
105
106
107
108
109 if (flags & GPIOD_FLAGS_BIT_NONEXCLUSIVE) {
110 struct devres *dres;
111
112 dres = devres_find(dev, devm_gpiod_release,
113 devm_gpiod_match, &desc);
114 if (dres)
115 return desc;
116 }
117
118 dr = devres_alloc(devm_gpiod_release, sizeof(struct gpio_desc *),
119 GFP_KERNEL);
120 if (!dr) {
121 gpiod_put(desc);
122 return ERR_PTR(-ENOMEM);
123 }
124
125 *dr = desc;
126 devres_add(dev, dr);
127
128 return desc;
129}
130EXPORT_SYMBOL_GPL(devm_gpiod_get_index);
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147struct gpio_desc *devm_gpiod_get_from_of_node(struct device *dev,
148 const struct device_node *node,
149 const char *propname, int index,
150 enum gpiod_flags dflags,
151 const char *label)
152{
153 struct gpio_desc **dr;
154 struct gpio_desc *desc;
155
156 desc = gpiod_get_from_of_node(node, propname, index, dflags, label);
157 if (IS_ERR(desc))
158 return desc;
159
160
161
162
163
164 if (dflags & GPIOD_FLAGS_BIT_NONEXCLUSIVE) {
165 struct devres *dres;
166
167 dres = devres_find(dev, devm_gpiod_release,
168 devm_gpiod_match, &desc);
169 if (dres)
170 return desc;
171 }
172
173 dr = devres_alloc(devm_gpiod_release, sizeof(struct gpio_desc *),
174 GFP_KERNEL);
175 if (!dr) {
176 gpiod_put(desc);
177 return ERR_PTR(-ENOMEM);
178 }
179
180 *dr = desc;
181 devres_add(dev, dr);
182
183 return desc;
184}
185EXPORT_SYMBOL_GPL(devm_gpiod_get_from_of_node);
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202struct gpio_desc *devm_fwnode_gpiod_get_index(struct device *dev,
203 struct fwnode_handle *fwnode,
204 const char *con_id, int index,
205 enum gpiod_flags flags,
206 const char *label)
207{
208 struct gpio_desc **dr;
209 struct gpio_desc *desc;
210
211 dr = devres_alloc(devm_gpiod_release, sizeof(struct gpio_desc *),
212 GFP_KERNEL);
213 if (!dr)
214 return ERR_PTR(-ENOMEM);
215
216 desc = fwnode_gpiod_get_index(fwnode, con_id, index, flags, label);
217 if (IS_ERR(desc)) {
218 devres_free(dr);
219 return desc;
220 }
221
222 *dr = desc;
223 devres_add(dev, dr);
224
225 return desc;
226}
227EXPORT_SYMBOL_GPL(devm_fwnode_gpiod_get_index);
228
229
230
231
232
233
234
235
236
237
238
239
240
241struct gpio_desc *__must_check devm_gpiod_get_index_optional(struct device *dev,
242 const char *con_id,
243 unsigned int index,
244 enum gpiod_flags flags)
245{
246 struct gpio_desc *desc;
247
248 desc = devm_gpiod_get_index(dev, con_id, index, flags);
249 if (gpiod_not_found(desc))
250 return NULL;
251
252 return desc;
253}
254EXPORT_SYMBOL_GPL(devm_gpiod_get_index_optional);
255
256
257
258
259
260
261
262
263
264
265
266struct gpio_descs *__must_check devm_gpiod_get_array(struct device *dev,
267 const char *con_id,
268 enum gpiod_flags flags)
269{
270 struct gpio_descs **dr;
271 struct gpio_descs *descs;
272
273 dr = devres_alloc(devm_gpiod_release_array,
274 sizeof(struct gpio_descs *), GFP_KERNEL);
275 if (!dr)
276 return ERR_PTR(-ENOMEM);
277
278 descs = gpiod_get_array(dev, con_id, flags);
279 if (IS_ERR(descs)) {
280 devres_free(dr);
281 return descs;
282 }
283
284 *dr = descs;
285 devres_add(dev, dr);
286
287 return descs;
288}
289EXPORT_SYMBOL_GPL(devm_gpiod_get_array);
290
291
292
293
294
295
296
297
298
299
300
301
302struct gpio_descs *__must_check
303devm_gpiod_get_array_optional(struct device *dev, const char *con_id,
304 enum gpiod_flags flags)
305{
306 struct gpio_descs *descs;
307
308 descs = devm_gpiod_get_array(dev, con_id, flags);
309 if (gpiod_not_found(descs))
310 return NULL;
311
312 return descs;
313}
314EXPORT_SYMBOL_GPL(devm_gpiod_get_array_optional);
315
316
317
318
319
320
321
322
323
324
325void devm_gpiod_put(struct device *dev, struct gpio_desc *desc)
326{
327 WARN_ON(devres_release(dev, devm_gpiod_release, devm_gpiod_match,
328 &desc));
329}
330EXPORT_SYMBOL_GPL(devm_gpiod_put);
331
332
333
334
335
336
337
338
339
340
341
342void devm_gpiod_unhinge(struct device *dev, struct gpio_desc *desc)
343{
344 int ret;
345
346 if (IS_ERR_OR_NULL(desc))
347 return;
348 ret = devres_destroy(dev, devm_gpiod_release,
349 devm_gpiod_match, &desc);
350
351
352
353
354
355 if (ret == -ENOENT)
356 return;
357
358 WARN_ON(ret);
359}
360EXPORT_SYMBOL_GPL(devm_gpiod_unhinge);
361
362
363
364
365
366
367
368
369
370
371void devm_gpiod_put_array(struct device *dev, struct gpio_descs *descs)
372{
373 WARN_ON(devres_release(dev, devm_gpiod_release_array,
374 devm_gpiod_match_array, &descs));
375}
376EXPORT_SYMBOL_GPL(devm_gpiod_put_array);
377
378
379
380
381static void devm_gpio_release(struct device *dev, void *res)
382{
383 unsigned *gpio = res;
384
385 gpio_free(*gpio);
386}
387
388static int devm_gpio_match(struct device *dev, void *res, void *data)
389{
390 unsigned *this = res, *gpio = data;
391
392 return *this == *gpio;
393}
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410int devm_gpio_request(struct device *dev, unsigned gpio, const char *label)
411{
412 unsigned *dr;
413 int rc;
414
415 dr = devres_alloc(devm_gpio_release, sizeof(unsigned), GFP_KERNEL);
416 if (!dr)
417 return -ENOMEM;
418
419 rc = gpio_request(gpio, label);
420 if (rc) {
421 devres_free(dr);
422 return rc;
423 }
424
425 *dr = gpio;
426 devres_add(dev, dr);
427
428 return 0;
429}
430EXPORT_SYMBOL_GPL(devm_gpio_request);
431
432
433
434
435
436
437
438
439int devm_gpio_request_one(struct device *dev, unsigned gpio,
440 unsigned long flags, const char *label)
441{
442 unsigned *dr;
443 int rc;
444
445 dr = devres_alloc(devm_gpio_release, sizeof(unsigned), GFP_KERNEL);
446 if (!dr)
447 return -ENOMEM;
448
449 rc = gpio_request_one(gpio, flags, label);
450 if (rc) {
451 devres_free(dr);
452 return rc;
453 }
454
455 *dr = gpio;
456 devres_add(dev, dr);
457
458 return 0;
459}
460EXPORT_SYMBOL_GPL(devm_gpio_request_one);
461
462
463
464
465
466
467
468
469
470
471
472void devm_gpio_free(struct device *dev, unsigned int gpio)
473{
474
475 WARN_ON(devres_release(dev, devm_gpio_release, devm_gpio_match,
476 &gpio));
477}
478EXPORT_SYMBOL_GPL(devm_gpio_free);
479
480static void devm_gpio_chip_release(void *data)
481{
482 struct gpio_chip *gc = data;
483
484 gpiochip_remove(gc);
485}
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504int devm_gpiochip_add_data_with_key(struct device *dev, struct gpio_chip *gc, void *data,
505 struct lock_class_key *lock_key,
506 struct lock_class_key *request_key)
507{
508 int ret;
509
510 ret = gpiochip_add_data_with_key(gc, data, lock_key, request_key);
511 if (ret < 0)
512 return ret;
513
514 return devm_add_action_or_reset(dev, devm_gpio_chip_release, gc);
515}
516EXPORT_SYMBOL_GPL(devm_gpiochip_add_data_with_key);
517