diff options
author | Lukas Wunner <lukas@wunner.de> | 2017-10-12 06:40:10 -0400 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2017-10-19 16:32:39 -0400 |
commit | eec1d566cdf94b57e8f5ba9fe60eea214929bcfc (patch) | |
tree | f10fab2d393d231f711123fcf66c1b01fc893370 /include/linux/gpio | |
parent | 5307e2ad69ab3b0e0622fdf8b254c1d4565eb924 (diff) |
gpio: Introduce ->get_multiple callback
SPI-attached GPIO controllers typically read out all inputs in one go.
If callers desire the values of multipe inputs, ideally a single readout
should take place to return the desired values. However the current
driver API only offers a ->get callback but no ->get_multiple (unlike
->set_multiple, which is present). Thus, to read multiple inputs, a
full readout needs to be performed for every single value (barring
driver-internal caching), which is inefficient.
In fact, the lack of a ->get_multiple callback has been bemoaned
repeatedly by the gpio subsystem maintainer:
http://www.spinics.net/lists/linux-gpio/msg10571.html
http://www.spinics.net/lists/devicetree/msg121734.html
Introduce the missing callback. Add corresponding consumer functions
such as gpiod_get_array_value(). Amend linehandle_ioctl() to take
advantage of the newly added infrastructure. Update the documentation.
Cc: Rojhalat Ibrahim <imr@rtschenk.de>
Signed-off-by: Lukas Wunner <lukas@wunner.de>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'include/linux/gpio')
-rw-r--r-- | include/linux/gpio/consumer.h | 43 | ||||
-rw-r--r-- | include/linux/gpio/driver.h | 5 |
2 files changed, 48 insertions, 0 deletions
diff --git a/include/linux/gpio/consumer.h b/include/linux/gpio/consumer.h index 8f702fcbe485..d4920ec1f1da 100644 --- a/include/linux/gpio/consumer.h +++ b/include/linux/gpio/consumer.h | |||
@@ -99,10 +99,15 @@ int gpiod_direction_output_raw(struct gpio_desc *desc, int value); | |||
99 | 99 | ||
100 | /* Value get/set from non-sleeping context */ | 100 | /* Value get/set from non-sleeping context */ |
101 | int gpiod_get_value(const struct gpio_desc *desc); | 101 | int gpiod_get_value(const struct gpio_desc *desc); |
102 | int gpiod_get_array_value(unsigned int array_size, | ||
103 | struct gpio_desc **desc_array, int *value_array); | ||
102 | void gpiod_set_value(struct gpio_desc *desc, int value); | 104 | void gpiod_set_value(struct gpio_desc *desc, int value); |
103 | void gpiod_set_array_value(unsigned int array_size, | 105 | void gpiod_set_array_value(unsigned int array_size, |
104 | struct gpio_desc **desc_array, int *value_array); | 106 | struct gpio_desc **desc_array, int *value_array); |
105 | int gpiod_get_raw_value(const struct gpio_desc *desc); | 107 | int gpiod_get_raw_value(const struct gpio_desc *desc); |
108 | int gpiod_get_raw_array_value(unsigned int array_size, | ||
109 | struct gpio_desc **desc_array, | ||
110 | int *value_array); | ||
106 | void gpiod_set_raw_value(struct gpio_desc *desc, int value); | 111 | void gpiod_set_raw_value(struct gpio_desc *desc, int value); |
107 | void gpiod_set_raw_array_value(unsigned int array_size, | 112 | void gpiod_set_raw_array_value(unsigned int array_size, |
108 | struct gpio_desc **desc_array, | 113 | struct gpio_desc **desc_array, |
@@ -110,11 +115,17 @@ void gpiod_set_raw_array_value(unsigned int array_size, | |||
110 | 115 | ||
111 | /* Value get/set from sleeping context */ | 116 | /* Value get/set from sleeping context */ |
112 | int gpiod_get_value_cansleep(const struct gpio_desc *desc); | 117 | int gpiod_get_value_cansleep(const struct gpio_desc *desc); |
118 | int gpiod_get_array_value_cansleep(unsigned int array_size, | ||
119 | struct gpio_desc **desc_array, | ||
120 | int *value_array); | ||
113 | void gpiod_set_value_cansleep(struct gpio_desc *desc, int value); | 121 | void gpiod_set_value_cansleep(struct gpio_desc *desc, int value); |
114 | void gpiod_set_array_value_cansleep(unsigned int array_size, | 122 | void gpiod_set_array_value_cansleep(unsigned int array_size, |
115 | struct gpio_desc **desc_array, | 123 | struct gpio_desc **desc_array, |
116 | int *value_array); | 124 | int *value_array); |
117 | int gpiod_get_raw_value_cansleep(const struct gpio_desc *desc); | 125 | int gpiod_get_raw_value_cansleep(const struct gpio_desc *desc); |
126 | int gpiod_get_raw_array_value_cansleep(unsigned int array_size, | ||
127 | struct gpio_desc **desc_array, | ||
128 | int *value_array); | ||
118 | void gpiod_set_raw_value_cansleep(struct gpio_desc *desc, int value); | 129 | void gpiod_set_raw_value_cansleep(struct gpio_desc *desc, int value); |
119 | void gpiod_set_raw_array_value_cansleep(unsigned int array_size, | 130 | void gpiod_set_raw_array_value_cansleep(unsigned int array_size, |
120 | struct gpio_desc **desc_array, | 131 | struct gpio_desc **desc_array, |
@@ -305,6 +316,14 @@ static inline int gpiod_get_value(const struct gpio_desc *desc) | |||
305 | WARN_ON(1); | 316 | WARN_ON(1); |
306 | return 0; | 317 | return 0; |
307 | } | 318 | } |
319 | static inline int gpiod_get_array_value(unsigned int array_size, | ||
320 | struct gpio_desc **desc_array, | ||
321 | int *value_array) | ||
322 | { | ||
323 | /* GPIO can never have been requested */ | ||
324 | WARN_ON(1); | ||
325 | return 0; | ||
326 | } | ||
308 | static inline void gpiod_set_value(struct gpio_desc *desc, int value) | 327 | static inline void gpiod_set_value(struct gpio_desc *desc, int value) |
309 | { | 328 | { |
310 | /* GPIO can never have been requested */ | 329 | /* GPIO can never have been requested */ |
@@ -323,6 +342,14 @@ static inline int gpiod_get_raw_value(const struct gpio_desc *desc) | |||
323 | WARN_ON(1); | 342 | WARN_ON(1); |
324 | return 0; | 343 | return 0; |
325 | } | 344 | } |
345 | static inline int gpiod_get_raw_array_value(unsigned int array_size, | ||
346 | struct gpio_desc **desc_array, | ||
347 | int *value_array) | ||
348 | { | ||
349 | /* GPIO can never have been requested */ | ||
350 | WARN_ON(1); | ||
351 | return 0; | ||
352 | } | ||
326 | static inline void gpiod_set_raw_value(struct gpio_desc *desc, int value) | 353 | static inline void gpiod_set_raw_value(struct gpio_desc *desc, int value) |
327 | { | 354 | { |
328 | /* GPIO can never have been requested */ | 355 | /* GPIO can never have been requested */ |
@@ -342,6 +369,14 @@ static inline int gpiod_get_value_cansleep(const struct gpio_desc *desc) | |||
342 | WARN_ON(1); | 369 | WARN_ON(1); |
343 | return 0; | 370 | return 0; |
344 | } | 371 | } |
372 | static inline int gpiod_get_array_value_cansleep(unsigned int array_size, | ||
373 | struct gpio_desc **desc_array, | ||
374 | int *value_array) | ||
375 | { | ||
376 | /* GPIO can never have been requested */ | ||
377 | WARN_ON(1); | ||
378 | return 0; | ||
379 | } | ||
345 | static inline void gpiod_set_value_cansleep(struct gpio_desc *desc, int value) | 380 | static inline void gpiod_set_value_cansleep(struct gpio_desc *desc, int value) |
346 | { | 381 | { |
347 | /* GPIO can never have been requested */ | 382 | /* GPIO can never have been requested */ |
@@ -360,6 +395,14 @@ static inline int gpiod_get_raw_value_cansleep(const struct gpio_desc *desc) | |||
360 | WARN_ON(1); | 395 | WARN_ON(1); |
361 | return 0; | 396 | return 0; |
362 | } | 397 | } |
398 | static inline int gpiod_get_raw_array_value_cansleep(unsigned int array_size, | ||
399 | struct gpio_desc **desc_array, | ||
400 | int *value_array) | ||
401 | { | ||
402 | /* GPIO can never have been requested */ | ||
403 | WARN_ON(1); | ||
404 | return 0; | ||
405 | } | ||
363 | static inline void gpiod_set_raw_value_cansleep(struct gpio_desc *desc, | 406 | static inline void gpiod_set_raw_value_cansleep(struct gpio_desc *desc, |
364 | int value) | 407 | int value) |
365 | { | 408 | { |
diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index 6bbda879fb8b..bda95a9b7b8c 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h | |||
@@ -35,6 +35,8 @@ struct module; | |||
35 | * @direction_input: configures signal "offset" as input, or returns error | 35 | * @direction_input: configures signal "offset" as input, or returns error |
36 | * @direction_output: configures signal "offset" as output, or returns error | 36 | * @direction_output: configures signal "offset" as output, or returns error |
37 | * @get: returns value for signal "offset", 0=low, 1=high, or negative error | 37 | * @get: returns value for signal "offset", 0=low, 1=high, or negative error |
38 | * @get_multiple: reads values for multiple signals defined by "mask" and | ||
39 | * stores them in "bits", returns 0 on success or negative error | ||
38 | * @set: assigns output value for signal "offset" | 40 | * @set: assigns output value for signal "offset" |
39 | * @set_multiple: assigns output values for multiple signals defined by "mask" | 41 | * @set_multiple: assigns output values for multiple signals defined by "mask" |
40 | * @set_config: optional hook for all kinds of settings. Uses the same | 42 | * @set_config: optional hook for all kinds of settings. Uses the same |
@@ -125,6 +127,9 @@ struct gpio_chip { | |||
125 | unsigned offset, int value); | 127 | unsigned offset, int value); |
126 | int (*get)(struct gpio_chip *chip, | 128 | int (*get)(struct gpio_chip *chip, |
127 | unsigned offset); | 129 | unsigned offset); |
130 | int (*get_multiple)(struct gpio_chip *chip, | ||
131 | unsigned long *mask, | ||
132 | unsigned long *bits); | ||
128 | void (*set)(struct gpio_chip *chip, | 133 | void (*set)(struct gpio_chip *chip, |
129 | unsigned offset, int value); | 134 | unsigned offset, int value); |
130 | void (*set_multiple)(struct gpio_chip *chip, | 135 | void (*set_multiple)(struct gpio_chip *chip, |