diff options
author | Rojhalat Ibrahim <imr@rtschenk.de> | 2014-11-04 11:12:06 -0500 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2014-11-27 09:01:18 -0500 |
commit | 5f42424354f5b0ca5413b4fb8528d150692c85b7 (patch) | |
tree | 23ba183fa9976595adda4bceb006842a15eb3e19 | |
parent | b5b7b487431b01619f2947d91dadd7c7a233692e (diff) |
gpiolib: allow simultaneous setting of multiple GPIO outputs
Introduce new functions gpiod_set_array & gpiod_set_raw_array to the consumer
interface which allow setting multiple outputs with just one function call.
Also add an optional set_multiple function to the driver interface. Without an
implementation of that function in the chip driver outputs are set
sequentially.
Implementing the set_multiple function in a chip driver allows for:
- Improved performance for certain use cases. The original motivation for this
was the task of configuring an FPGA. In that specific case, where 9 GPIO
lines have to be set many times, configuration time goes down from 48 s to
20 s when using the new function.
- Simultaneous glitch-free setting of multiple pins on any kind of parallel
bus attached to GPIOs provided they all reside on the same chip and bank.
Limitations:
Performance is only improved for normal high-low outputs. Open drain and
open source outputs are always set separately from each other. Those kinds
of outputs could probably be accelerated in a similar way if we could
forgo the error checking when setting GPIO directions.
Change log:
v6: - rebase on current linux-gpio devel branch
v5: - check can_sleep property per chip
- remove superfluous checks
- supplement documentation
v4: - add gpiod_set_array function for setting logical values
- change interface of the set_multiple driver function to use
unsigned long as type for the bit fields
- use generic bitops (which also use unsigned long for bit fields)
- do not use ARCH_NR_GPIOS any more
v3: - add documentation
- change commit message
v2: - use descriptor interface
- allow arbitrary groups of GPIOs spanning multiple chips
Signed-off-by: Rojhalat Ibrahim <imr@rtschenk.de>
Reviewed-by: Alexandre Courbot <acourbot@nvidia.com>
Reviewed-by: Mark Brown <broonie@linaro.org>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
-rw-r--r-- | Documentation/gpio/consumer.txt | 27 | ||||
-rw-r--r-- | drivers/gpio/gpiolib.c | 168 | ||||
-rw-r--r-- | include/linux/gpio/consumer.h | 38 | ||||
-rw-r--r-- | include/linux/gpio/driver.h | 4 |
4 files changed, 237 insertions, 0 deletions
diff --git a/Documentation/gpio/consumer.txt b/Documentation/gpio/consumer.txt index 6ce544191ca6..c67f806401a5 100644 --- a/Documentation/gpio/consumer.txt +++ b/Documentation/gpio/consumer.txt | |||
@@ -199,6 +199,33 @@ The active-low state of a GPIO can also be queried using the following call: | |||
199 | Note that these functions should only be used with great moderation ; a driver | 199 | Note that these functions should only be used with great moderation ; a driver |
200 | should not have to care about the physical line level. | 200 | should not have to care about the physical line level. |
201 | 201 | ||
202 | |||
203 | Set multiple GPIO outputs with a single function call | ||
204 | ----------------------------------------------------- | ||
205 | The following functions set the output values of an array of GPIOs: | ||
206 | |||
207 | void gpiod_set_array(unsigned int array_size, | ||
208 | struct gpio_desc **desc_array, | ||
209 | int *value_array) | ||
210 | void gpiod_set_raw_array(unsigned int array_size, | ||
211 | struct gpio_desc **desc_array, | ||
212 | int *value_array) | ||
213 | void gpiod_set_array_cansleep(unsigned int array_size, | ||
214 | struct gpio_desc **desc_array, | ||
215 | int *value_array) | ||
216 | void gpiod_set_raw_array_cansleep(unsigned int array_size, | ||
217 | struct gpio_desc **desc_array, | ||
218 | int *value_array) | ||
219 | |||
220 | The array can be an arbitrary set of GPIOs. The functions will try to set | ||
221 | GPIOs belonging to the same bank or chip simultaneously if supported by the | ||
222 | corresponding chip driver. In that case a significantly improved performance | ||
223 | can be expected. If simultaneous setting is not possible the GPIOs will be set | ||
224 | sequentially. | ||
225 | Note that for optimal performance GPIOs belonging to the same chip should be | ||
226 | contiguous within the array of descriptors. | ||
227 | |||
228 | |||
202 | GPIOs mapped to IRQs | 229 | GPIOs mapped to IRQs |
203 | -------------------- | 230 | -------------------- |
204 | GPIO lines can quite often be used as IRQs. You can get the IRQ number | 231 | GPIO lines can quite often be used as IRQs. You can get the IRQ number |
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 50e18a4b3a9f..eb739a51e774 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c | |||
@@ -1254,6 +1254,88 @@ static void _gpiod_set_raw_value(struct gpio_desc *desc, bool value) | |||
1254 | chip->set(chip, gpio_chip_hwgpio(desc), value); | 1254 | chip->set(chip, gpio_chip_hwgpio(desc), value); |
1255 | } | 1255 | } |
1256 | 1256 | ||
1257 | /* | ||
1258 | * set multiple outputs on the same chip; | ||
1259 | * use the chip's set_multiple function if available; | ||
1260 | * otherwise set the outputs sequentially; | ||
1261 | * @mask: bit mask array; one bit per output; BITS_PER_LONG bits per word | ||
1262 | * defines which outputs are to be changed | ||
1263 | * @bits: bit value array; one bit per output; BITS_PER_LONG bits per word | ||
1264 | * defines the values the outputs specified by mask are to be set to | ||
1265 | */ | ||
1266 | static void gpio_chip_set_multiple(struct gpio_chip *chip, | ||
1267 | unsigned long *mask, unsigned long *bits) | ||
1268 | { | ||
1269 | if (chip->set_multiple) { | ||
1270 | chip->set_multiple(chip, mask, bits); | ||
1271 | } else { | ||
1272 | int i; | ||
1273 | for (i = 0; i < chip->ngpio; i++) { | ||
1274 | if (mask[BIT_WORD(i)] == 0) { | ||
1275 | /* no more set bits in this mask word; | ||
1276 | * skip ahead to the next word */ | ||
1277 | i = (BIT_WORD(i) + 1) * BITS_PER_LONG - 1; | ||
1278 | continue; | ||
1279 | } | ||
1280 | /* set outputs if the corresponding mask bit is set */ | ||
1281 | if (__test_and_clear_bit(i, mask)) { | ||
1282 | chip->set(chip, i, test_bit(i, bits)); | ||
1283 | } | ||
1284 | } | ||
1285 | } | ||
1286 | } | ||
1287 | |||
1288 | static void gpiod_set_array_priv(bool raw, bool can_sleep, | ||
1289 | unsigned int array_size, | ||
1290 | struct gpio_desc **desc_array, | ||
1291 | int *value_array) | ||
1292 | { | ||
1293 | int i = 0; | ||
1294 | |||
1295 | while (i < array_size) { | ||
1296 | struct gpio_chip *chip = desc_array[i]->chip; | ||
1297 | unsigned long mask[BITS_TO_LONGS(chip->ngpio)]; | ||
1298 | unsigned long bits[BITS_TO_LONGS(chip->ngpio)]; | ||
1299 | int count = 0; | ||
1300 | |||
1301 | if (!can_sleep) { | ||
1302 | WARN_ON(chip->can_sleep); | ||
1303 | } | ||
1304 | memset(mask, 0, sizeof(mask)); | ||
1305 | do { | ||
1306 | struct gpio_desc *desc = desc_array[i]; | ||
1307 | int hwgpio = gpio_chip_hwgpio(desc); | ||
1308 | int value = value_array[i]; | ||
1309 | |||
1310 | if (!raw && test_bit(FLAG_ACTIVE_LOW, &desc->flags)) | ||
1311 | value = !value; | ||
1312 | trace_gpio_value(desc_to_gpio(desc), 0, value); | ||
1313 | /* | ||
1314 | * collect all normal outputs belonging to the same chip | ||
1315 | * open drain and open source outputs are set individually | ||
1316 | */ | ||
1317 | if (test_bit(FLAG_OPEN_DRAIN, &desc->flags)) { | ||
1318 | _gpio_set_open_drain_value(desc,value); | ||
1319 | } else if (test_bit(FLAG_OPEN_SOURCE, &desc->flags)) { | ||
1320 | _gpio_set_open_source_value(desc, value); | ||
1321 | } else { | ||
1322 | __set_bit(hwgpio, mask); | ||
1323 | if (value) { | ||
1324 | __set_bit(hwgpio, bits); | ||
1325 | } else { | ||
1326 | __clear_bit(hwgpio, bits); | ||
1327 | } | ||
1328 | count++; | ||
1329 | } | ||
1330 | i++; | ||
1331 | } while ((i < array_size) && (desc_array[i]->chip == chip)); | ||
1332 | /* push collected bits to outputs */ | ||
1333 | if (count != 0) { | ||
1334 | gpio_chip_set_multiple(chip, mask, bits); | ||
1335 | } | ||
1336 | } | ||
1337 | } | ||
1338 | |||
1257 | /** | 1339 | /** |
1258 | * gpiod_set_raw_value() - assign a gpio's raw value | 1340 | * gpiod_set_raw_value() - assign a gpio's raw value |
1259 | * @desc: gpio whose value will be assigned | 1341 | * @desc: gpio whose value will be assigned |
@@ -1299,6 +1381,48 @@ void gpiod_set_value(struct gpio_desc *desc, int value) | |||
1299 | EXPORT_SYMBOL_GPL(gpiod_set_value); | 1381 | EXPORT_SYMBOL_GPL(gpiod_set_value); |
1300 | 1382 | ||
1301 | /** | 1383 | /** |
1384 | * gpiod_set_raw_array() - assign values to an array of GPIOs | ||
1385 | * @array_size: number of elements in the descriptor / value arrays | ||
1386 | * @desc_array: array of GPIO descriptors whose values will be assigned | ||
1387 | * @value_array: array of values to assign | ||
1388 | * | ||
1389 | * Set the raw values of the GPIOs, i.e. the values of the physical lines | ||
1390 | * without regard for their ACTIVE_LOW status. | ||
1391 | * | ||
1392 | * This function should be called from contexts where we cannot sleep, and will | ||
1393 | * complain if the GPIO chip functions potentially sleep. | ||
1394 | */ | ||
1395 | void gpiod_set_raw_array(unsigned int array_size, | ||
1396 | struct gpio_desc **desc_array, int *value_array) | ||
1397 | { | ||
1398 | if (!desc_array) | ||
1399 | return; | ||
1400 | gpiod_set_array_priv(true, false, array_size, desc_array, value_array); | ||
1401 | } | ||
1402 | EXPORT_SYMBOL_GPL(gpiod_set_raw_array); | ||
1403 | |||
1404 | /** | ||
1405 | * gpiod_set_array() - assign values to an array of GPIOs | ||
1406 | * @array_size: number of elements in the descriptor / value arrays | ||
1407 | * @desc_array: array of GPIO descriptors whose values will be assigned | ||
1408 | * @value_array: array of values to assign | ||
1409 | * | ||
1410 | * Set the logical values of the GPIOs, i.e. taking their ACTIVE_LOW status | ||
1411 | * into account. | ||
1412 | * | ||
1413 | * This function should be called from contexts where we cannot sleep, and will | ||
1414 | * complain if the GPIO chip functions potentially sleep. | ||
1415 | */ | ||
1416 | void gpiod_set_array(unsigned int array_size, | ||
1417 | struct gpio_desc **desc_array, int *value_array) | ||
1418 | { | ||
1419 | if (!desc_array) | ||
1420 | return; | ||
1421 | gpiod_set_array_priv(false, false, array_size, desc_array, value_array); | ||
1422 | } | ||
1423 | EXPORT_SYMBOL_GPL(gpiod_set_array); | ||
1424 | |||
1425 | /** | ||
1302 | * gpiod_cansleep() - report whether gpio value access may sleep | 1426 | * gpiod_cansleep() - report whether gpio value access may sleep |
1303 | * @desc: gpio to check | 1427 | * @desc: gpio to check |
1304 | * | 1428 | * |
@@ -1458,6 +1582,50 @@ void gpiod_set_value_cansleep(struct gpio_desc *desc, int value) | |||
1458 | EXPORT_SYMBOL_GPL(gpiod_set_value_cansleep); | 1582 | EXPORT_SYMBOL_GPL(gpiod_set_value_cansleep); |
1459 | 1583 | ||
1460 | /** | 1584 | /** |
1585 | * gpiod_set_raw_array_cansleep() - assign values to an array of GPIOs | ||
1586 | * @array_size: number of elements in the descriptor / value arrays | ||
1587 | * @desc_array: array of GPIO descriptors whose values will be assigned | ||
1588 | * @value_array: array of values to assign | ||
1589 | * | ||
1590 | * Set the raw values of the GPIOs, i.e. the values of the physical lines | ||
1591 | * without regard for their ACTIVE_LOW status. | ||
1592 | * | ||
1593 | * This function is to be called from contexts that can sleep. | ||
1594 | */ | ||
1595 | void gpiod_set_raw_array_cansleep(unsigned int array_size, | ||
1596 | struct gpio_desc **desc_array, | ||
1597 | int *value_array) | ||
1598 | { | ||
1599 | might_sleep_if(extra_checks); | ||
1600 | if (!desc_array) | ||
1601 | return; | ||
1602 | gpiod_set_array_priv(true, true, array_size, desc_array, value_array); | ||
1603 | } | ||
1604 | EXPORT_SYMBOL_GPL(gpiod_set_raw_array_cansleep); | ||
1605 | |||
1606 | /** | ||
1607 | * gpiod_set_array_cansleep() - assign values to an array of GPIOs | ||
1608 | * @array_size: number of elements in the descriptor / value arrays | ||
1609 | * @desc_array: array of GPIO descriptors whose values will be assigned | ||
1610 | * @value_array: array of values to assign | ||
1611 | * | ||
1612 | * Set the logical values of the GPIOs, i.e. taking their ACTIVE_LOW status | ||
1613 | * into account. | ||
1614 | * | ||
1615 | * This function is to be called from contexts that can sleep. | ||
1616 | */ | ||
1617 | void gpiod_set_array_cansleep(unsigned int array_size, | ||
1618 | struct gpio_desc **desc_array, | ||
1619 | int *value_array) | ||
1620 | { | ||
1621 | might_sleep_if(extra_checks); | ||
1622 | if (!desc_array) | ||
1623 | return; | ||
1624 | gpiod_set_array_priv(false, true, array_size, desc_array, value_array); | ||
1625 | } | ||
1626 | EXPORT_SYMBOL_GPL(gpiod_set_array_cansleep); | ||
1627 | |||
1628 | /** | ||
1461 | * gpiod_add_lookup_table() - register GPIO device consumers | 1629 | * gpiod_add_lookup_table() - register GPIO device consumers |
1462 | * @table: table of consumers to register | 1630 | * @table: table of consumers to register |
1463 | */ | 1631 | */ |
diff --git a/include/linux/gpio/consumer.h b/include/linux/gpio/consumer.h index 12f146fa6604..83c0a61c605d 100644 --- a/include/linux/gpio/consumer.h +++ b/include/linux/gpio/consumer.h | |||
@@ -74,14 +74,24 @@ int gpiod_direction_output_raw(struct gpio_desc *desc, int value); | |||
74 | /* Value get/set from non-sleeping context */ | 74 | /* Value get/set from non-sleeping context */ |
75 | int gpiod_get_value(const struct gpio_desc *desc); | 75 | int gpiod_get_value(const struct gpio_desc *desc); |
76 | void gpiod_set_value(struct gpio_desc *desc, int value); | 76 | void gpiod_set_value(struct gpio_desc *desc, int value); |
77 | void gpiod_set_array(unsigned int array_size, | ||
78 | struct gpio_desc **desc_array, int *value_array); | ||
77 | int gpiod_get_raw_value(const struct gpio_desc *desc); | 79 | int gpiod_get_raw_value(const struct gpio_desc *desc); |
78 | void gpiod_set_raw_value(struct gpio_desc *desc, int value); | 80 | void gpiod_set_raw_value(struct gpio_desc *desc, int value); |
81 | void gpiod_set_raw_array(unsigned int array_size, | ||
82 | struct gpio_desc **desc_array, int *value_array); | ||
79 | 83 | ||
80 | /* Value get/set from sleeping context */ | 84 | /* Value get/set from sleeping context */ |
81 | int gpiod_get_value_cansleep(const struct gpio_desc *desc); | 85 | int gpiod_get_value_cansleep(const struct gpio_desc *desc); |
82 | void gpiod_set_value_cansleep(struct gpio_desc *desc, int value); | 86 | void gpiod_set_value_cansleep(struct gpio_desc *desc, int value); |
87 | void gpiod_set_array_cansleep(unsigned int array_size, | ||
88 | struct gpio_desc **desc_array, | ||
89 | int *value_array); | ||
83 | int gpiod_get_raw_value_cansleep(const struct gpio_desc *desc); | 90 | int gpiod_get_raw_value_cansleep(const struct gpio_desc *desc); |
84 | void gpiod_set_raw_value_cansleep(struct gpio_desc *desc, int value); | 91 | void gpiod_set_raw_value_cansleep(struct gpio_desc *desc, int value); |
92 | void gpiod_set_raw_array_cansleep(unsigned int array_size, | ||
93 | struct gpio_desc **desc_array, | ||
94 | int *value_array); | ||
85 | 95 | ||
86 | int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce); | 96 | int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce); |
87 | 97 | ||
@@ -210,6 +220,13 @@ static inline void gpiod_set_value(struct gpio_desc *desc, int value) | |||
210 | /* GPIO can never have been requested */ | 220 | /* GPIO can never have been requested */ |
211 | WARN_ON(1); | 221 | WARN_ON(1); |
212 | } | 222 | } |
223 | static inline void gpiod_set_array(unsigned int array_size, | ||
224 | struct gpio_desc **desc_array, | ||
225 | int *value_array) | ||
226 | { | ||
227 | /* GPIO can never have been requested */ | ||
228 | WARN_ON(1); | ||
229 | } | ||
213 | static inline int gpiod_get_raw_value(const struct gpio_desc *desc) | 230 | static inline int gpiod_get_raw_value(const struct gpio_desc *desc) |
214 | { | 231 | { |
215 | /* GPIO can never have been requested */ | 232 | /* GPIO can never have been requested */ |
@@ -221,6 +238,13 @@ static inline void gpiod_set_raw_value(struct gpio_desc *desc, int value) | |||
221 | /* GPIO can never have been requested */ | 238 | /* GPIO can never have been requested */ |
222 | WARN_ON(1); | 239 | WARN_ON(1); |
223 | } | 240 | } |
241 | static inline void gpiod_set_raw_array(unsigned int array_size, | ||
242 | struct gpio_desc **desc_array, | ||
243 | int *value_array) | ||
244 | { | ||
245 | /* GPIO can never have been requested */ | ||
246 | WARN_ON(1); | ||
247 | } | ||
224 | 248 | ||
225 | static inline int gpiod_get_value_cansleep(const struct gpio_desc *desc) | 249 | static inline int gpiod_get_value_cansleep(const struct gpio_desc *desc) |
226 | { | 250 | { |
@@ -233,6 +257,13 @@ static inline void gpiod_set_value_cansleep(struct gpio_desc *desc, int value) | |||
233 | /* GPIO can never have been requested */ | 257 | /* GPIO can never have been requested */ |
234 | WARN_ON(1); | 258 | WARN_ON(1); |
235 | } | 259 | } |
260 | static inline void gpiod_set_array_cansleep(unsigned int array_size, | ||
261 | struct gpio_desc **desc_array, | ||
262 | int *value_array) | ||
263 | { | ||
264 | /* GPIO can never have been requested */ | ||
265 | WARN_ON(1); | ||
266 | } | ||
236 | static inline int gpiod_get_raw_value_cansleep(const struct gpio_desc *desc) | 267 | static inline int gpiod_get_raw_value_cansleep(const struct gpio_desc *desc) |
237 | { | 268 | { |
238 | /* GPIO can never have been requested */ | 269 | /* GPIO can never have been requested */ |
@@ -245,6 +276,13 @@ static inline void gpiod_set_raw_value_cansleep(struct gpio_desc *desc, | |||
245 | /* GPIO can never have been requested */ | 276 | /* GPIO can never have been requested */ |
246 | WARN_ON(1); | 277 | WARN_ON(1); |
247 | } | 278 | } |
279 | static inline void gpiod_set_raw_array_cansleep(unsigned int array_size, | ||
280 | struct gpio_desc **desc_array, | ||
281 | int *value_array) | ||
282 | { | ||
283 | /* GPIO can never have been requested */ | ||
284 | WARN_ON(1); | ||
285 | } | ||
248 | 286 | ||
249 | static inline int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce) | 287 | static inline int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce) |
250 | { | 288 | { |
diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index ff200a75501e..c497c62889d1 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h | |||
@@ -32,6 +32,7 @@ struct seq_file; | |||
32 | * @get: returns value for signal "offset"; for output signals this | 32 | * @get: returns value for signal "offset"; for output signals this |
33 | * returns either the value actually sensed, or zero | 33 | * returns either the value actually sensed, or zero |
34 | * @set: assigns output value for signal "offset" | 34 | * @set: assigns output value for signal "offset" |
35 | * @set_multiple: assigns output values for multiple signals defined by "mask" | ||
35 | * @set_debounce: optional hook for setting debounce time for specified gpio in | 36 | * @set_debounce: optional hook for setting debounce time for specified gpio in |
36 | * interrupt triggered gpio chips | 37 | * interrupt triggered gpio chips |
37 | * @to_irq: optional hook supporting non-static gpio_to_irq() mappings; | 38 | * @to_irq: optional hook supporting non-static gpio_to_irq() mappings; |
@@ -89,6 +90,9 @@ struct gpio_chip { | |||
89 | unsigned offset); | 90 | unsigned offset); |
90 | void (*set)(struct gpio_chip *chip, | 91 | void (*set)(struct gpio_chip *chip, |
91 | unsigned offset, int value); | 92 | unsigned offset, int value); |
93 | void (*set_multiple)(struct gpio_chip *chip, | ||
94 | unsigned long *mask, | ||
95 | unsigned long *bits); | ||
92 | int (*set_debounce)(struct gpio_chip *chip, | 96 | int (*set_debounce)(struct gpio_chip *chip, |
93 | unsigned offset, | 97 | unsigned offset, |
94 | unsigned debounce); | 98 | unsigned debounce); |