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, |
