Blame view

drivers/gpio/devres.c 10.9 KB
1a0703ede   John Crispin   GPIO: add binding...
1
2
3
4
5
6
7
8
9
10
11
12
13
  /*
   * 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
   *
baddc7ca4   John Crispin   gpio: update my e...
14
   * Copyright (c) 2011 John Crispin <john@phrozen.org>
1a0703ede   John Crispin   GPIO: add binding...
15
16
17
   */
  
  #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>
200d0177b   Andy Shevchenko   gpio: devres: Use...
23
  #include "gpiolib.h"
bae48da23   Alexandre Courbot   gpiolib: add gpio...
24
25
26
27
28
29
30
31
32
33
34
35
36
  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...
37
38
39
40
41
42
43
44
45
46
47
48
49
  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...
50
51
52
53
  /**
   * devm_gpiod_get - Resource-managed gpiod_get()
   * @dev:	GPIO consumer
   * @con_id:	function within the GPIO consumer
39b2bbe3d   Alexandre Courbot   gpio: add flags a...
54
   * @flags:	optional GPIO initialization flags
bae48da23   Alexandre Courbot   gpiolib: add gpio...
55
56
57
58
59
   *
   * 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 ...
60
  struct gpio_desc *__must_check devm_gpiod_get(struct device *dev,
39b2bbe3d   Alexandre Courbot   gpio: add flags a...
61
62
  					      const char *con_id,
  					      enum gpiod_flags flags)
bae48da23   Alexandre Courbot   gpiolib: add gpio...
63
  {
39b2bbe3d   Alexandre Courbot   gpio: add flags a...
64
  	return devm_gpiod_get_index(dev, con_id, 0, flags);
bae48da23   Alexandre Courbot   gpiolib: add gpio...
65
  }
b17d1bf16   Uwe Kleine-König   gpio: make flags ...
66
  EXPORT_SYMBOL(devm_gpiod_get);
bae48da23   Alexandre Courbot   gpiolib: add gpio...
67
68
  
  /**
29a1f2333   Thierry Reding   gpio: Add helpers...
69
70
71
   * 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...
72
   * @flags: optional GPIO initialization flags
29a1f2333   Thierry Reding   gpio: Add helpers...
73
74
75
76
77
   *
   * 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 ...
78
  struct gpio_desc *__must_check devm_gpiod_get_optional(struct device *dev,
39b2bbe3d   Alexandre Courbot   gpio: add flags a...
79
80
  						       const char *con_id,
  						       enum gpiod_flags flags)
29a1f2333   Thierry Reding   gpio: Add helpers...
81
  {
39b2bbe3d   Alexandre Courbot   gpio: add flags a...
82
  	return devm_gpiod_get_index_optional(dev, con_id, 0, flags);
29a1f2333   Thierry Reding   gpio: Add helpers...
83
  }
b17d1bf16   Uwe Kleine-König   gpio: make flags ...
84
  EXPORT_SYMBOL(devm_gpiod_get_optional);
29a1f2333   Thierry Reding   gpio: Add helpers...
85
86
  
  /**
bae48da23   Alexandre Courbot   gpiolib: add gpio...
87
88
89
90
   * 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...
91
   * @flags:	optional GPIO initialization flags
bae48da23   Alexandre Courbot   gpiolib: add gpio...
92
93
94
95
96
   *
   * 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 ...
97
  struct gpio_desc *__must_check devm_gpiod_get_index(struct device *dev,
bae48da23   Alexandre Courbot   gpiolib: add gpio...
98
  						    const char *con_id,
39b2bbe3d   Alexandre Courbot   gpio: add flags a...
99
100
  						    unsigned int idx,
  						    enum gpiod_flags flags)
bae48da23   Alexandre Courbot   gpiolib: add gpio...
101
102
103
  {
  	struct gpio_desc **dr;
  	struct gpio_desc *desc;
0f05a3ae4   Julia Lawall   gpiolib: devres: ...
104
  	dr = devres_alloc(devm_gpiod_release, sizeof(struct gpio_desc *),
bae48da23   Alexandre Courbot   gpiolib: add gpio...
105
106
107
  			  GFP_KERNEL);
  	if (!dr)
  		return ERR_PTR(-ENOMEM);
39b2bbe3d   Alexandre Courbot   gpio: add flags a...
108
  	desc = gpiod_get_index(dev, con_id, idx, flags);
bae48da23   Alexandre Courbot   gpiolib: add gpio...
109
110
111
112
113
114
115
  	if (IS_ERR(desc)) {
  		devres_free(dr);
  		return desc;
  	}
  
  	*dr = desc;
  	devres_add(dev, dr);
5fcdb9dc9   Alexandre Courbot   gpiolib: devres: ...
116
  	return desc;
bae48da23   Alexandre Courbot   gpiolib: add gpio...
117
  }
b17d1bf16   Uwe Kleine-König   gpio: make flags ...
118
  EXPORT_SYMBOL(devm_gpiod_get_index);
bae48da23   Alexandre Courbot   gpiolib: add gpio...
119
120
  
  /**
537b94daf   Boris Brezillon   gpio: Add the dev...
121
122
   * devm_fwnode_get_index_gpiod_from_child - get a GPIO descriptor from a
   *					    device's child node
40b731831   Mika Westerberg   gpio: Support for...
123
   * @dev:	GPIO consumer
1feb57a24   Olliver Schinagl   gpio: add paramet...
124
   * @con_id:	function within the GPIO consumer
537b94daf   Boris Brezillon   gpio: Add the dev...
125
   * @index:	index of the GPIO to obtain in the consumer
40b731831   Mika Westerberg   gpio: Support for...
126
   * @child:	firmware node (child of @dev)
a264d10ff   Andy Shevchenko   gpiolib: Convert ...
127
   * @flags:	GPIO initialization flags
2b7c809bd   Thierry Reding   gpio: devres: Imp...
128
   * @label:	label to attach to the requested GPIO
40b731831   Mika Westerberg   gpio: Support for...
129
130
131
   *
   * GPIO descriptors returned from this function are automatically disposed on
   * driver detach.
a264d10ff   Andy Shevchenko   gpiolib: Convert ...
132
   *
ff21378a3   Andy Shevchenko   gpiolib: Fix spel...
133
   * On successful request the GPIO pin is configured in accordance with
a264d10ff   Andy Shevchenko   gpiolib: Convert ...
134
   * provided @flags.
40b731831   Mika Westerberg   gpio: Support for...
135
   */
537b94daf   Boris Brezillon   gpio: Add the dev...
136
137
138
139
140
  struct gpio_desc *devm_fwnode_get_index_gpiod_from_child(struct device *dev,
  						const char *con_id, int index,
  						struct fwnode_handle *child,
  						enum gpiod_flags flags,
  						const char *label)
40b731831   Mika Westerberg   gpio: Support for...
141
  {
1feb57a24   Olliver Schinagl   gpio: add paramet...
142
  	char prop_name[32]; /* 32 is max size of property name */
40b731831   Mika Westerberg   gpio: Support for...
143
144
  	struct gpio_desc **dr;
  	struct gpio_desc *desc;
1feb57a24   Olliver Schinagl   gpio: add paramet...
145
  	unsigned int i;
40b731831   Mika Westerberg   gpio: Support for...
146
147
148
149
150
  
  	dr = devres_alloc(devm_gpiod_release, sizeof(struct gpio_desc *),
  			  GFP_KERNEL);
  	if (!dr)
  		return ERR_PTR(-ENOMEM);
200d0177b   Andy Shevchenko   gpio: devres: Use...
151
  	for (i = 0; i < ARRAY_SIZE(gpio_suffixes); i++) {
1feb57a24   Olliver Schinagl   gpio: add paramet...
152
153
  		if (con_id)
  			snprintf(prop_name, sizeof(prop_name), "%s-%s",
200d0177b   Andy Shevchenko   gpio: devres: Use...
154
  					    con_id, gpio_suffixes[i]);
1feb57a24   Olliver Schinagl   gpio: add paramet...
155
156
  		else
  			snprintf(prop_name, sizeof(prop_name), "%s",
200d0177b   Andy Shevchenko   gpio: devres: Use...
157
  					    gpio_suffixes[i]);
1feb57a24   Olliver Schinagl   gpio: add paramet...
158

537b94daf   Boris Brezillon   gpio: Add the dev...
159
160
  		desc = fwnode_get_named_gpiod(child, prop_name, index, flags,
  					      label);
40c8eabac   Geert Uytterhoeven   gpio: Propagate a...
161
  		if (!IS_ERR(desc) || (PTR_ERR(desc) != -ENOENT))
1feb57a24   Olliver Schinagl   gpio: add paramet...
162
163
  			break;
  	}
40b731831   Mika Westerberg   gpio: Support for...
164
165
166
167
168
169
170
171
172
173
  	if (IS_ERR(desc)) {
  		devres_free(dr);
  		return desc;
  	}
  
  	*dr = desc;
  	devres_add(dev, dr);
  
  	return desc;
  }
537b94daf   Boris Brezillon   gpio: Add the dev...
174
  EXPORT_SYMBOL(devm_fwnode_get_index_gpiod_from_child);
40b731831   Mika Westerberg   gpio: Support for...
175
176
  
  /**
29a1f2333   Thierry Reding   gpio: Add helpers...
177
178
179
180
   * 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...
181
   * @flags: optional GPIO initialization flags
29a1f2333   Thierry Reding   gpio: Add helpers...
182
183
184
185
186
187
   *
   * 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 ...
188
  struct gpio_desc *__must_check devm_gpiod_get_index_optional(struct device *dev,
29a1f2333   Thierry Reding   gpio: Add helpers...
189
  							     const char *con_id,
39b2bbe3d   Alexandre Courbot   gpio: add flags a...
190
  							     unsigned int index,
b17d1bf16   Uwe Kleine-König   gpio: make flags ...
191
  							     enum gpiod_flags flags)
29a1f2333   Thierry Reding   gpio: Add helpers...
192
193
  {
  	struct gpio_desc *desc;
39b2bbe3d   Alexandre Courbot   gpio: add flags a...
194
  	desc = devm_gpiod_get_index(dev, con_id, index, flags);
29a1f2333   Thierry Reding   gpio: Add helpers...
195
196
197
198
199
200
201
  	if (IS_ERR(desc)) {
  		if (PTR_ERR(desc) == -ENOENT)
  			return NULL;
  	}
  
  	return desc;
  }
b17d1bf16   Uwe Kleine-König   gpio: make flags ...
202
  EXPORT_SYMBOL(devm_gpiod_get_index_optional);
29a1f2333   Thierry Reding   gpio: Add helpers...
203
204
  
  /**
331758eef   Rojhalat Ibrahim   gpiolib: add devm...
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
255
256
257
258
259
260
261
262
263
264
   * 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...
265
   * devm_gpiod_put - Resource-managed gpiod_put()
2b7c809bd   Thierry Reding   gpio: devres: Imp...
266
   * @dev:	GPIO consumer
bae48da23   Alexandre Courbot   gpiolib: add gpio...
267
268
269
270
271
272
273
274
275
276
277
278
   * @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...
279
280
  /**
   * devm_gpiod_put_array - Resource-managed gpiod_put_array()
2b7c809bd   Thierry Reding   gpio: devres: Imp...
281
   * @dev:	GPIO consumer
331758eef   Rojhalat Ibrahim   gpiolib: add devm...
282
283
284
285
286
287
288
289
290
291
292
293
   * @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...
294

1a0703ede   John Crispin   GPIO: add binding...
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
  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...
310
311
312
313
   *      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...
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
   *
   *      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...
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
   *	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...
374
  EXPORT_SYMBOL(devm_gpio_request_one);
09d71ff19   Mark Brown   gpiolib: Implemen...
375
376
  
  /**
713b7ef83   Wolfram Sang   gpio: devres: mak...
377
378
379
   *      devm_gpio_free - free a GPIO
   *      @dev: device to free GPIO for
   *      @gpio: GPIO to free
1a0703ede   John Crispin   GPIO: add binding...
380
381
382
383
384
385
386
387
   *
   *      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 ...
388
  	WARN_ON(devres_release(dev, devm_gpio_release, devm_gpio_match,
1a0703ede   John Crispin   GPIO: add binding...
389
  		&gpio));
1a0703ede   John Crispin   GPIO: add binding...
390
391
  }
  EXPORT_SYMBOL(devm_gpio_free);