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 /drivers/gpio/gpiolib.c | |
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>
Diffstat (limited to 'drivers/gpio/gpiolib.c')
-rw-r--r-- | drivers/gpio/gpiolib.c | 168 |
1 files changed, 168 insertions, 0 deletions
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 | */ |