Commit 3e45f1d1155894e6f4291f5536b224874d52d8e2
Committed by
Linus Torvalds
1 parent
62fecb70cf
Exists in
master
and in
20 other branches
gpio: introduce gpio_request_one() and friends
gpio_request() without initial configuration of the GPIO is normally useless, introduce gpio_request_one() together with GPIOF_ flags for input/output direction and initial output level. gpio_{request,free}_array() for multiple GPIOs. Signed-off-by: Eric Miao <eric.y.miao@gmail.com> Cc: David Brownell <dbrownell@users.sourceforge.net> Cc: Ben Nizette <bn@niasdigital.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Showing 3 changed files with 148 additions and 0 deletions Side-by-side Diff
Documentation/gpio.txt
... | ... | @@ -253,6 +253,70 @@ |
253 | 253 | Also note that it's your responsibility to have stopped using a GPIO |
254 | 254 | before you free it. |
255 | 255 | |
256 | +Considering in most cases GPIOs are actually configured right after they | |
257 | +are claimed, three additional calls are defined: | |
258 | + | |
259 | + /* request a single GPIO, with initial configuration specified by | |
260 | + * 'flags', identical to gpio_request() wrt other arguments and | |
261 | + * return value | |
262 | + */ | |
263 | + int gpio_request_one(unsigned gpio, unsigned long flags, const char *label); | |
264 | + | |
265 | + /* request multiple GPIOs in a single call | |
266 | + */ | |
267 | + int gpio_request_array(struct gpio *array, size_t num); | |
268 | + | |
269 | + /* release multiple GPIOs in a single call | |
270 | + */ | |
271 | + void gpio_free_array(struct gpio *array, size_t num); | |
272 | + | |
273 | +where 'flags' is currently defined to specify the following properties: | |
274 | + | |
275 | + * GPIOF_DIR_IN - to configure direction as input | |
276 | + * GPIOF_DIR_OUT - to configure direction as output | |
277 | + | |
278 | + * GPIOF_INIT_LOW - as output, set initial level to LOW | |
279 | + * GPIOF_INIT_HIGH - as output, set initial level to HIGH | |
280 | + | |
281 | +since GPIOF_INIT_* are only valid when configured as output, so group valid | |
282 | +combinations as: | |
283 | + | |
284 | + * GPIOF_IN - configure as input | |
285 | + * GPIOF_OUT_INIT_LOW - configured as output, initial level LOW | |
286 | + * GPIOF_OUT_INIT_HIGH - configured as output, initial level HIGH | |
287 | + | |
288 | +In the future, these flags can be extended to support more properties such | |
289 | +as open-drain status. | |
290 | + | |
291 | +Further more, to ease the claim/release of multiple GPIOs, 'struct gpio' is | |
292 | +introduced to encapsulate all three fields as: | |
293 | + | |
294 | + struct gpio { | |
295 | + unsigned gpio; | |
296 | + unsigned long flags; | |
297 | + const char *label; | |
298 | + }; | |
299 | + | |
300 | +A typical example of usage: | |
301 | + | |
302 | + static struct gpio leds_gpios[] = { | |
303 | + { 32, GPIOF_OUT_INIT_HIGH, "Power LED" }, /* default to ON */ | |
304 | + { 33, GPIOF_OUT_INIT_LOW, "Green LED" }, /* default to OFF */ | |
305 | + { 34, GPIOF_OUT_INIT_LOW, "Red LED" }, /* default to OFF */ | |
306 | + { 35, GPIOF_OUT_INIT_LOW, "Blue LED" }, /* default to OFF */ | |
307 | + { ... }, | |
308 | + }; | |
309 | + | |
310 | + err = gpio_request_one(31, GPIOF_IN, "Reset Button"); | |
311 | + if (err) | |
312 | + ... | |
313 | + | |
314 | + err = gpio_request_array(leds_gpios, ARRAY_SIZE(leds_gpios)); | |
315 | + if (err) | |
316 | + ... | |
317 | + | |
318 | + gpio_free_array(leds_gpios, ARRAY_SIZE(leds_gpios)); | |
319 | + | |
256 | 320 | |
257 | 321 | GPIOs mapped to IRQs |
258 | 322 | -------------------- |
drivers/gpio/gpiolib.c
... | ... | @@ -1237,6 +1237,64 @@ |
1237 | 1237 | } |
1238 | 1238 | EXPORT_SYMBOL_GPL(gpio_free); |
1239 | 1239 | |
1240 | +/** | |
1241 | + * gpio_request_one - request a single GPIO with initial configuration | |
1242 | + * @gpio: the GPIO number | |
1243 | + * @flags: GPIO configuration as specified by GPIOF_* | |
1244 | + * @label: a literal description string of this GPIO | |
1245 | + */ | |
1246 | +int gpio_request_one(unsigned gpio, unsigned long flags, const char *label) | |
1247 | +{ | |
1248 | + int err; | |
1249 | + | |
1250 | + err = gpio_request(gpio, label); | |
1251 | + if (err) | |
1252 | + return err; | |
1253 | + | |
1254 | + if (flags & GPIOF_DIR_IN) | |
1255 | + err = gpio_direction_input(gpio); | |
1256 | + else | |
1257 | + err = gpio_direction_output(gpio, | |
1258 | + (flags & GPIOF_INIT_HIGH) ? 1 : 0); | |
1259 | + | |
1260 | + return err; | |
1261 | +} | |
1262 | +EXPORT_SYMBOL_GPL(gpio_request_one); | |
1263 | + | |
1264 | +/** | |
1265 | + * gpio_request_array - request multiple GPIOs in a single call | |
1266 | + * @array: array of the 'struct gpio' | |
1267 | + * @num: how many GPIOs in the array | |
1268 | + */ | |
1269 | +int gpio_request_array(struct gpio *array, size_t num) | |
1270 | +{ | |
1271 | + int i, err; | |
1272 | + | |
1273 | + for (i = 0; i < num; i++, array++) { | |
1274 | + err = gpio_request_one(array->gpio, array->flags, array->label); | |
1275 | + if (err) | |
1276 | + goto err_free; | |
1277 | + } | |
1278 | + return 0; | |
1279 | + | |
1280 | +err_free: | |
1281 | + while (i--) | |
1282 | + gpio_free((--array)->gpio); | |
1283 | + return err; | |
1284 | +} | |
1285 | +EXPORT_SYMBOL_GPL(gpio_request_array); | |
1286 | + | |
1287 | +/** | |
1288 | + * gpio_free_array - release multiple GPIOs in a single call | |
1289 | + * @array: array of the 'struct gpio' | |
1290 | + * @num: how many GPIOs in the array | |
1291 | + */ | |
1292 | +void gpio_free_array(struct gpio *array, size_t num) | |
1293 | +{ | |
1294 | + while (num--) | |
1295 | + gpio_free((array++)->gpio); | |
1296 | +} | |
1297 | +EXPORT_SYMBOL_GPL(gpio_free_array); | |
1240 | 1298 | |
1241 | 1299 | /** |
1242 | 1300 | * gpiochip_is_requested - return string iff signal was requested |
include/asm-generic/gpio.h
... | ... | @@ -136,6 +136,32 @@ |
136 | 136 | |
137 | 137 | extern int __gpio_to_irq(unsigned gpio); |
138 | 138 | |
139 | +#define GPIOF_DIR_OUT (0 << 0) | |
140 | +#define GPIOF_DIR_IN (1 << 0) | |
141 | + | |
142 | +#define GPIOF_INIT_LOW (0 << 1) | |
143 | +#define GPIOF_INIT_HIGH (1 << 1) | |
144 | + | |
145 | +#define GPIOF_IN (GPIOF_DIR_IN) | |
146 | +#define GPIOF_OUT_INIT_LOW (GPIOF_DIR_OUT | GPIOF_INIT_LOW) | |
147 | +#define GPIOF_OUT_INIT_HIGH (GPIOF_DIR_OUT | GPIOF_INIT_HIGH) | |
148 | + | |
149 | +/** | |
150 | + * struct gpio - a structure describing a GPIO with configuration | |
151 | + * @gpio: the GPIO number | |
152 | + * @flags: GPIO configuration as specified by GPIOF_* | |
153 | + * @label: a literal description string of this GPIO | |
154 | + */ | |
155 | +struct gpio { | |
156 | + unsigned gpio; | |
157 | + unsigned long flags; | |
158 | + const char *label; | |
159 | +}; | |
160 | + | |
161 | +extern int gpio_request_one(unsigned gpio, unsigned long flags, const char *label); | |
162 | +extern int gpio_request_array(struct gpio *array, size_t num); | |
163 | +extern void gpio_free_array(struct gpio *array, size_t num); | |
164 | + | |
139 | 165 | #ifdef CONFIG_GPIO_SYSFS |
140 | 166 | |
141 | 167 | /* |