1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17#include <linux/module.h>
18#include <linux/err.h>
19#include <linux/gpio.h>
20#include <linux/gpio/consumer.h>
21#include <linux/device.h>
22#include <linux/gfp.h>
23
24static void devm_gpiod_release(struct device *dev, void *res)
25{
26 struct gpio_desc **desc = res;
27
28 gpiod_put(*desc);
29}
30
31static int devm_gpiod_match(struct device *dev, void *res, void *data)
32{
33 struct gpio_desc **this = res, **gpio = data;
34
35 return *this == *gpio;
36}
37
38
39
40
41
42
43
44
45
46
47
48struct gpio_desc *__must_check __devm_gpiod_get(struct device *dev,
49 const char *con_id,
50 enum gpiod_flags flags)
51{
52 return devm_gpiod_get_index(dev, con_id, 0, flags);
53}
54EXPORT_SYMBOL(__devm_gpiod_get);
55
56
57
58
59
60
61
62
63
64
65
66struct gpio_desc *__must_check __devm_gpiod_get_optional(struct device *dev,
67 const char *con_id,
68 enum gpiod_flags flags)
69{
70 return devm_gpiod_get_index_optional(dev, con_id, 0, flags);
71}
72EXPORT_SYMBOL(__devm_gpiod_get_optional);
73
74
75
76
77
78
79
80
81
82
83
84
85struct gpio_desc *__must_check __devm_gpiod_get_index(struct device *dev,
86 const char *con_id,
87 unsigned int idx,
88 enum gpiod_flags flags)
89{
90 struct gpio_desc **dr;
91 struct gpio_desc *desc;
92
93 dr = devres_alloc(devm_gpiod_release, sizeof(struct gpiod_desc *),
94 GFP_KERNEL);
95 if (!dr)
96 return ERR_PTR(-ENOMEM);
97
98 desc = gpiod_get_index(dev, con_id, idx, flags);
99 if (IS_ERR(desc)) {
100 devres_free(dr);
101 return desc;
102 }
103
104 *dr = desc;
105 devres_add(dev, dr);
106
107 return desc;
108}
109EXPORT_SYMBOL(__devm_gpiod_get_index);
110
111
112
113
114
115
116
117
118
119
120
121
122
123struct gpio_desc *__must_check __devm_gpiod_get_index_optional(struct device *dev,
124 const char *con_id,
125 unsigned int index,
126 enum gpiod_flags flags)
127{
128 struct gpio_desc *desc;
129
130 desc = devm_gpiod_get_index(dev, con_id, index, flags);
131 if (IS_ERR(desc)) {
132 if (PTR_ERR(desc) == -ENOENT)
133 return NULL;
134 }
135
136 return desc;
137}
138EXPORT_SYMBOL(__devm_gpiod_get_index_optional);
139
140
141
142
143
144
145
146
147
148void devm_gpiod_put(struct device *dev, struct gpio_desc *desc)
149{
150 WARN_ON(devres_release(dev, devm_gpiod_release, devm_gpiod_match,
151 &desc));
152}
153EXPORT_SYMBOL(devm_gpiod_put);
154
155
156
157
158static void devm_gpio_release(struct device *dev, void *res)
159{
160 unsigned *gpio = res;
161
162 gpio_free(*gpio);
163}
164
165static int devm_gpio_match(struct device *dev, void *res, void *data)
166{
167 unsigned *this = res, *gpio = data;
168
169 return *this == *gpio;
170}
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187int devm_gpio_request(struct device *dev, unsigned gpio, const char *label)
188{
189 unsigned *dr;
190 int rc;
191
192 dr = devres_alloc(devm_gpio_release, sizeof(unsigned), GFP_KERNEL);
193 if (!dr)
194 return -ENOMEM;
195
196 rc = gpio_request(gpio, label);
197 if (rc) {
198 devres_free(dr);
199 return rc;
200 }
201
202 *dr = gpio;
203 devres_add(dev, dr);
204
205 return 0;
206}
207EXPORT_SYMBOL(devm_gpio_request);
208
209
210
211
212
213
214
215
216int devm_gpio_request_one(struct device *dev, unsigned gpio,
217 unsigned long flags, const char *label)
218{
219 unsigned *dr;
220 int rc;
221
222 dr = devres_alloc(devm_gpio_release, sizeof(unsigned), GFP_KERNEL);
223 if (!dr)
224 return -ENOMEM;
225
226 rc = gpio_request_one(gpio, flags, label);
227 if (rc) {
228 devres_free(dr);
229 return rc;
230 }
231
232 *dr = gpio;
233 devres_add(dev, dr);
234
235 return 0;
236}
237EXPORT_SYMBOL(devm_gpio_request_one);
238
239
240
241
242
243
244
245
246
247
248
249void devm_gpio_free(struct device *dev, unsigned int gpio)
250{
251
252 WARN_ON(devres_release(dev, devm_gpio_release, devm_gpio_match,
253 &gpio));
254}
255EXPORT_SYMBOL(devm_gpio_free);
256