Blame view

drivers/gpio/devres.c 10.5 KB
1a0703ede   John Crispin   GPIO: add binding...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  /*
   * drivers/gpio/devres.c - managed gpio resources
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License version 2
   * as published by the Free Software Foundation.
   *
   * You should have received a copy of the GNU General Public License
   * along with this program; if not, write to the Free Software
   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   *
   * This file is based on kernel/irq/devres.c
   *
   * Copyright (c) 2011 John Crispin <blogic@openwrt.org>
   */
  
  #include <linux/module.h>
3c2c628f8   Alexandre Courbot   gpiolib: devres: ...
18
  #include <linux/err.h>
1a0703ede   John Crispin   GPIO: add binding...
19
  #include <linux/gpio.h>
3c2c628f8   Alexandre Courbot   gpiolib: devres: ...
20
  #include <linux/gpio/consumer.h>
1a0703ede   John Crispin   GPIO: add binding...
21
22
  #include <linux/device.h>
  #include <linux/gfp.h>
bae48da23   Alexandre Courbot   gpiolib: add gpio...
23
24
25
26
27
28
29
30
31
32
33
34
35
  static void devm_gpiod_release(struct device *dev, void *res)
  {
  	struct gpio_desc **desc = res;
  
  	gpiod_put(*desc);
  }
  
  static int devm_gpiod_match(struct device *dev, void *res, void *data)
  {
  	struct gpio_desc **this = res, **gpio = data;
  
  	return *this == *gpio;
  }
331758eef   Rojhalat Ibrahim   gpiolib: add devm...
36
37
38
39
40
41
42
43
44
45
46
47
48
  static void devm_gpiod_release_array(struct device *dev, void *res)
  {
  	struct gpio_descs **descs = res;
  
  	gpiod_put_array(*descs);
  }
  
  static int devm_gpiod_match_array(struct device *dev, void *res, void *data)
  {
  	struct gpio_descs **this = res, **gpios = data;
  
  	return *this == *gpios;
  }
bae48da23   Alexandre Courbot   gpiolib: add gpio...
49
50
51
52
  /**
   * devm_gpiod_get - Resource-managed gpiod_get()
   * @dev:	GPIO consumer
   * @con_id:	function within the GPIO consumer
39b2bbe3d   Alexandre Courbot   gpio: add flags a...
53
   * @flags:	optional GPIO initialization flags
bae48da23   Alexandre Courbot   gpiolib: add gpio...
54
55
56
57
58
   *
   * Managed gpiod_get(). GPIO descriptors returned from this function are
   * automatically disposed on driver detach. See gpiod_get() for detailed
   * information about behavior and return values.
   */
b17d1bf16   Uwe Kleine-König   gpio: make flags ...
59
  struct gpio_desc *__must_check devm_gpiod_get(struct device *dev,
39b2bbe3d   Alexandre Courbot   gpio: add flags a...
60
61
  					      const char *con_id,
  					      enum gpiod_flags flags)
bae48da23   Alexandre Courbot   gpiolib: add gpio...
62
  {
39b2bbe3d   Alexandre Courbot   gpio: add flags a...
63
  	return devm_gpiod_get_index(dev, con_id, 0, flags);
bae48da23   Alexandre Courbot   gpiolib: add gpio...
64
  }
b17d1bf16   Uwe Kleine-König   gpio: make flags ...
65
  EXPORT_SYMBOL(devm_gpiod_get);
bae48da23   Alexandre Courbot   gpiolib: add gpio...
66
67
  
  /**
29a1f2333   Thierry Reding   gpio: Add helpers...
68
69
70
   * devm_gpiod_get_optional - Resource-managed gpiod_get_optional()
   * @dev: GPIO consumer
   * @con_id: function within the GPIO consumer
39b2bbe3d   Alexandre Courbot   gpio: add flags a...
71
   * @flags: optional GPIO initialization flags
29a1f2333   Thierry Reding   gpio: Add helpers...
72
73
74
75
76
   *
   * Managed gpiod_get_optional(). GPIO descriptors returned from this function
   * are automatically disposed on driver detach. See gpiod_get_optional() for
   * detailed information about behavior and return values.
   */
b17d1bf16   Uwe Kleine-König   gpio: make flags ...
77
  struct gpio_desc *__must_check devm_gpiod_get_optional(struct device *dev,
39b2bbe3d   Alexandre Courbot   gpio: add flags a...
78
79
  						       const char *con_id,
  						       enum gpiod_flags flags)
29a1f2333   Thierry Reding   gpio: Add helpers...
80
  {
39b2bbe3d   Alexandre Courbot   gpio: add flags a...
81
  	return devm_gpiod_get_index_optional(dev, con_id, 0, flags);
29a1f2333   Thierry Reding   gpio: Add helpers...
82
  }
b17d1bf16   Uwe Kleine-König   gpio: make flags ...
83
  EXPORT_SYMBOL(devm_gpiod_get_optional);
29a1f2333   Thierry Reding   gpio: Add helpers...
84
85
  
  /**
bae48da23   Alexandre Courbot   gpiolib: add gpio...
86
87
88
89
   * devm_gpiod_get_index - Resource-managed gpiod_get_index()
   * @dev:	GPIO consumer
   * @con_id:	function within the GPIO consumer
   * @idx:	index of the GPIO to obtain in the consumer
39b2bbe3d   Alexandre Courbot   gpio: add flags a...
90
   * @flags:	optional GPIO initialization flags
bae48da23   Alexandre Courbot   gpiolib: add gpio...
91
92
93
94
95
   *
   * Managed gpiod_get_index(). GPIO descriptors returned from this function are
   * automatically disposed on driver detach. See gpiod_get_index() for detailed
   * information about behavior and return values.
   */
b17d1bf16   Uwe Kleine-König   gpio: make flags ...
96
  struct gpio_desc *__must_check devm_gpiod_get_index(struct device *dev,
bae48da23   Alexandre Courbot   gpiolib: add gpio...
97
  						    const char *con_id,
39b2bbe3d   Alexandre Courbot   gpio: add flags a...
98
99
  						    unsigned int idx,
  						    enum gpiod_flags flags)
bae48da23   Alexandre Courbot   gpiolib: add gpio...
100
101
102
  {
  	struct gpio_desc **dr;
  	struct gpio_desc *desc;
0f05a3ae4   Julia Lawall   gpiolib: devres: ...
103
  	dr = devres_alloc(devm_gpiod_release, sizeof(struct gpio_desc *),
bae48da23   Alexandre Courbot   gpiolib: add gpio...
104
105
106
  			  GFP_KERNEL);
  	if (!dr)
  		return ERR_PTR(-ENOMEM);
39b2bbe3d   Alexandre Courbot   gpio: add flags a...
107
  	desc = gpiod_get_index(dev, con_id, idx, flags);
bae48da23   Alexandre Courbot   gpiolib: add gpio...
108
109
110
111
112
113
114
  	if (IS_ERR(desc)) {
  		devres_free(dr);
  		return desc;
  	}
  
  	*dr = desc;
  	devres_add(dev, dr);
5fcdb9dc9   Alexandre Courbot   gpiolib: devres: ...
115
  	return desc;
bae48da23   Alexandre Courbot   gpiolib: add gpio...
116
  }
b17d1bf16   Uwe Kleine-König   gpio: make flags ...
117
  EXPORT_SYMBOL(devm_gpiod_get_index);
bae48da23   Alexandre Courbot   gpiolib: add gpio...
118
119
  
  /**
40b731831   Mika Westerberg   gpio: Support for...
120
121
   * devm_get_gpiod_from_child - get a GPIO descriptor from a device's child node
   * @dev:	GPIO consumer
1feb57a24   Olliver Schinagl   gpio: add paramet...
122
   * @con_id:	function within the GPIO consumer
40b731831   Mika Westerberg   gpio: Support for...
123
124
125
126
127
128
   * @child:	firmware node (child of @dev)
   *
   * GPIO descriptors returned from this function are automatically disposed on
   * driver detach.
   */
  struct gpio_desc *devm_get_gpiod_from_child(struct device *dev,
1feb57a24   Olliver Schinagl   gpio: add paramet...
129
  					    const char *con_id,
40b731831   Mika Westerberg   gpio: Support for...
130
131
  					    struct fwnode_handle *child)
  {
b6202855d   Linus Walleij   gpio: fix constco...
132
  	static const char * const suffixes[] = { "gpios", "gpio" };
1feb57a24   Olliver Schinagl   gpio: add paramet...
133
  	char prop_name[32]; /* 32 is max size of property name */
40b731831   Mika Westerberg   gpio: Support for...
134
135
  	struct gpio_desc **dr;
  	struct gpio_desc *desc;
1feb57a24   Olliver Schinagl   gpio: add paramet...
136
  	unsigned int i;
40b731831   Mika Westerberg   gpio: Support for...
137
138
139
140
141
  
  	dr = devres_alloc(devm_gpiod_release, sizeof(struct gpio_desc *),
  			  GFP_KERNEL);
  	if (!dr)
  		return ERR_PTR(-ENOMEM);
1feb57a24   Olliver Schinagl   gpio: add paramet...
142
143
144
145
146
147
148
149
150
  	for (i = 0; i < ARRAY_SIZE(suffixes); i++) {
  		if (con_id)
  			snprintf(prop_name, sizeof(prop_name), "%s-%s",
  					    con_id, suffixes[i]);
  		else
  			snprintf(prop_name, sizeof(prop_name), "%s",
  							       suffixes[i]);
  
  		desc = fwnode_get_named_gpiod(child, prop_name);
40c8eabac   Geert Uytterhoeven   gpio: Propagate a...
151
  		if (!IS_ERR(desc) || (PTR_ERR(desc) != -ENOENT))
1feb57a24   Olliver Schinagl   gpio: add paramet...
152
153
  			break;
  	}
40b731831   Mika Westerberg   gpio: Support for...
154
155
156
157
158
159
160
161
162
163
164
165
166
  	if (IS_ERR(desc)) {
  		devres_free(dr);
  		return desc;
  	}
  
  	*dr = desc;
  	devres_add(dev, dr);
  
  	return desc;
  }
  EXPORT_SYMBOL(devm_get_gpiod_from_child);
  
  /**
29a1f2333   Thierry Reding   gpio: Add helpers...
167
168
169
170
   * devm_gpiod_get_index_optional - Resource-managed gpiod_get_index_optional()
   * @dev: GPIO consumer
   * @con_id: function within the GPIO consumer
   * @index: index of the GPIO to obtain in the consumer
39b2bbe3d   Alexandre Courbot   gpio: add flags a...
171
   * @flags: optional GPIO initialization flags
29a1f2333   Thierry Reding   gpio: Add helpers...
172
173
174
175
176
177
   *
   * Managed gpiod_get_index_optional(). GPIO descriptors returned from this
   * function are automatically disposed on driver detach. See
   * gpiod_get_index_optional() for detailed information about behavior and
   * return values.
   */
b17d1bf16   Uwe Kleine-König   gpio: make flags ...
178
  struct gpio_desc *__must_check devm_gpiod_get_index_optional(struct device *dev,
29a1f2333   Thierry Reding   gpio: Add helpers...
179
  							     const char *con_id,
39b2bbe3d   Alexandre Courbot   gpio: add flags a...
180
  							     unsigned int index,
b17d1bf16   Uwe Kleine-König   gpio: make flags ...
181
  							     enum gpiod_flags flags)
29a1f2333   Thierry Reding   gpio: Add helpers...
182
183
  {
  	struct gpio_desc *desc;
39b2bbe3d   Alexandre Courbot   gpio: add flags a...
184
  	desc = devm_gpiod_get_index(dev, con_id, index, flags);
29a1f2333   Thierry Reding   gpio: Add helpers...
185
186
187
188
189
190
191
  	if (IS_ERR(desc)) {
  		if (PTR_ERR(desc) == -ENOENT)
  			return NULL;
  	}
  
  	return desc;
  }
b17d1bf16   Uwe Kleine-König   gpio: make flags ...
192
  EXPORT_SYMBOL(devm_gpiod_get_index_optional);
29a1f2333   Thierry Reding   gpio: Add helpers...
193
194
  
  /**
331758eef   Rojhalat Ibrahim   gpiolib: add devm...
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
   * devm_gpiod_get_array - Resource-managed gpiod_get_array()
   * @dev:	GPIO consumer
   * @con_id:	function within the GPIO consumer
   * @flags:	optional GPIO initialization flags
   *
   * Managed gpiod_get_array(). GPIO descriptors returned from this function are
   * automatically disposed on driver detach. See gpiod_get_array() for detailed
   * information about behavior and return values.
   */
  struct gpio_descs *__must_check devm_gpiod_get_array(struct device *dev,
  						     const char *con_id,
  						     enum gpiod_flags flags)
  {
  	struct gpio_descs **dr;
  	struct gpio_descs *descs;
  
  	dr = devres_alloc(devm_gpiod_release_array,
  			  sizeof(struct gpio_descs *), GFP_KERNEL);
  	if (!dr)
  		return ERR_PTR(-ENOMEM);
  
  	descs = gpiod_get_array(dev, con_id, flags);
  	if (IS_ERR(descs)) {
  		devres_free(dr);
  		return descs;
  	}
  
  	*dr = descs;
  	devres_add(dev, dr);
  
  	return descs;
  }
  EXPORT_SYMBOL(devm_gpiod_get_array);
  
  /**
   * devm_gpiod_get_array_optional - Resource-managed gpiod_get_array_optional()
   * @dev:	GPIO consumer
   * @con_id:	function within the GPIO consumer
   * @flags:	optional GPIO initialization flags
   *
   * Managed gpiod_get_array_optional(). GPIO descriptors returned from this
   * function are automatically disposed on driver detach.
   * See gpiod_get_array_optional() for detailed information about behavior and
   * return values.
   */
  struct gpio_descs *__must_check
  devm_gpiod_get_array_optional(struct device *dev, const char *con_id,
  			      enum gpiod_flags flags)
  {
  	struct gpio_descs *descs;
  
  	descs = devm_gpiod_get_array(dev, con_id, flags);
  	if (IS_ERR(descs) && (PTR_ERR(descs) == -ENOENT))
  		return NULL;
  
  	return descs;
  }
  EXPORT_SYMBOL(devm_gpiod_get_array_optional);
  
  /**
bae48da23   Alexandre Courbot   gpiolib: add gpio...
255
256
257
258
259
260
261
262
263
264
265
266
267
   * devm_gpiod_put - Resource-managed gpiod_put()
   * @desc:	GPIO descriptor to dispose of
   *
   * Dispose of a GPIO descriptor obtained with devm_gpiod_get() or
   * devm_gpiod_get_index(). Normally this function will not be called as the GPIO
   * will be disposed of by the resource management code.
   */
  void devm_gpiod_put(struct device *dev, struct gpio_desc *desc)
  {
  	WARN_ON(devres_release(dev, devm_gpiod_release, devm_gpiod_match,
  		&desc));
  }
  EXPORT_SYMBOL(devm_gpiod_put);
331758eef   Rojhalat Ibrahim   gpiolib: add devm...
268
269
270
271
272
273
274
275
276
277
278
279
280
281
  /**
   * devm_gpiod_put_array - Resource-managed gpiod_put_array()
   * @descs:	GPIO descriptor array to dispose of
   *
   * Dispose of an array of GPIO descriptors obtained with devm_gpiod_get_array().
   * Normally this function will not be called as the GPIOs will be disposed of
   * by the resource management code.
   */
  void devm_gpiod_put_array(struct device *dev, struct gpio_descs *descs)
  {
  	WARN_ON(devres_release(dev, devm_gpiod_release_array,
  			       devm_gpiod_match_array, &descs));
  }
  EXPORT_SYMBOL(devm_gpiod_put_array);
bae48da23   Alexandre Courbot   gpiolib: add gpio...
282

1a0703ede   John Crispin   GPIO: add binding...
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
  static void devm_gpio_release(struct device *dev, void *res)
  {
  	unsigned *gpio = res;
  
  	gpio_free(*gpio);
  }
  
  static int devm_gpio_match(struct device *dev, void *res, void *data)
  {
  	unsigned *this = res, *gpio = data;
  
  	return *this == *gpio;
  }
  
  /**
713b7ef83   Wolfram Sang   gpio: devres: mak...
298
299
300
301
   *      devm_gpio_request - request a GPIO for a managed device
   *      @dev: device to request the GPIO for
   *      @gpio: GPIO to allocate
   *      @label: the name of the requested GPIO
1a0703ede   John Crispin   GPIO: add binding...
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
   *
   *      Except for the extra @dev argument, this function takes the
   *      same arguments and performs the same function as
   *      gpio_request().  GPIOs requested with this function will be
   *      automatically freed on driver detach.
   *
   *      If an GPIO allocated with this function needs to be freed
   *      separately, devm_gpio_free() must be used.
   */
  
  int devm_gpio_request(struct device *dev, unsigned gpio, const char *label)
  {
  	unsigned *dr;
  	int rc;
  
  	dr = devres_alloc(devm_gpio_release, sizeof(unsigned), GFP_KERNEL);
  	if (!dr)
  		return -ENOMEM;
  
  	rc = gpio_request(gpio, label);
  	if (rc) {
  		devres_free(dr);
  		return rc;
  	}
  
  	*dr = gpio;
  	devres_add(dev, dr);
  
  	return 0;
  }
  EXPORT_SYMBOL(devm_gpio_request);
  
  /**
09d71ff19   Mark Brown   gpiolib: Implemen...
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
   *	devm_gpio_request_one - request a single GPIO with initial setup
   *	@dev:   device to request for
   *	@gpio:	the GPIO number
   *	@flags:	GPIO configuration as specified by GPIOF_*
   *	@label:	a literal description string of this GPIO
   */
  int devm_gpio_request_one(struct device *dev, unsigned gpio,
  			  unsigned long flags, const char *label)
  {
  	unsigned *dr;
  	int rc;
  
  	dr = devres_alloc(devm_gpio_release, sizeof(unsigned), GFP_KERNEL);
  	if (!dr)
  		return -ENOMEM;
  
  	rc = gpio_request_one(gpio, flags, label);
  	if (rc) {
  		devres_free(dr);
  		return rc;
  	}
  
  	*dr = gpio;
  	devres_add(dev, dr);
  
  	return 0;
  }
3996bfc78   Stephen Warren   gpio: export devm...
362
  EXPORT_SYMBOL(devm_gpio_request_one);
09d71ff19   Mark Brown   gpiolib: Implemen...
363
364
  
  /**
713b7ef83   Wolfram Sang   gpio: devres: mak...
365
366
367
   *      devm_gpio_free - free a GPIO
   *      @dev: device to free GPIO for
   *      @gpio: GPIO to free
1a0703ede   John Crispin   GPIO: add binding...
368
369
370
371
372
373
374
375
   *
   *      Except for the extra @dev argument, this function takes the
   *      same arguments and performs the same function as gpio_free().
   *      This function instead of gpio_free() should be used to manually
   *      free GPIOs allocated with devm_gpio_request().
   */
  void devm_gpio_free(struct device *dev, unsigned int gpio)
  {
a85990b3b   Mark Brown   gpiolib: Convert ...
376
  	WARN_ON(devres_release(dev, devm_gpio_release, devm_gpio_match,
1a0703ede   John Crispin   GPIO: add binding...
377
  		&gpio));
1a0703ede   John Crispin   GPIO: add binding...
378
379
  }
  EXPORT_SYMBOL(devm_gpio_free);