diff options
author | Laxman Dewangan <ldewangan@nvidia.com> | 2012-02-17 09:56:22 -0500 |
---|---|---|
committer | Grant Likely <grant.likely@secretlab.ca> | 2012-03-05 09:49:44 -0500 |
commit | 25553ff0756c59b617af6bdd280c94e943164184 (patch) | |
tree | 6ca9ec045b5d2e10523fdf46facac59aa683f4ce /drivers/gpio | |
parent | aca5ce14eb773a75e5d935968b2e390dc5bd29c3 (diff) |
gpio: gpiolib: Support for open source/emitter gpios
Adding support for the open source gpio on which client
can specify the open source property through GPIO flag
GPIOF_OPEN_SOURCE at the time of gpio request.
The open source pins are normally pulled low and it
cannot be driven to output with value of 0 and so
when client request for setting the pin to LOW, the
gpio will be set to input direction to make pin in tristate
and hence PULL-DOWN on pins will make the state to LOW.
The open source pin can be driven to HIGH by setting output
with value of 1.
Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com>
Reviwed-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Diffstat (limited to 'drivers/gpio')
-rw-r--r-- | drivers/gpio/gpiolib.c | 39 |
1 files changed, 39 insertions, 0 deletions
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 5d25a33d5359..58f40dfc5265 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c | |||
@@ -59,6 +59,7 @@ struct gpio_desc { | |||
59 | #define FLAG_TRIG_RISE 6 /* trigger on rising edge */ | 59 | #define FLAG_TRIG_RISE 6 /* trigger on rising edge */ |
60 | #define FLAG_ACTIVE_LOW 7 /* sysfs value has active low */ | 60 | #define FLAG_ACTIVE_LOW 7 /* sysfs value has active low */ |
61 | #define FLAG_OPEN_DRAIN 8 /* Gpio is open drain type */ | 61 | #define FLAG_OPEN_DRAIN 8 /* Gpio is open drain type */ |
62 | #define FLAG_OPEN_SOURCE 9 /* Gpio is open source type */ | ||
62 | 63 | ||
63 | #define ID_SHIFT 16 /* add new flags before this one */ | 64 | #define ID_SHIFT 16 /* add new flags before this one */ |
64 | 65 | ||
@@ -1266,6 +1267,7 @@ void gpio_free(unsigned gpio) | |||
1266 | clear_bit(FLAG_ACTIVE_LOW, &desc->flags); | 1267 | clear_bit(FLAG_ACTIVE_LOW, &desc->flags); |
1267 | clear_bit(FLAG_REQUESTED, &desc->flags); | 1268 | clear_bit(FLAG_REQUESTED, &desc->flags); |
1268 | clear_bit(FLAG_OPEN_DRAIN, &desc->flags); | 1269 | clear_bit(FLAG_OPEN_DRAIN, &desc->flags); |
1270 | clear_bit(FLAG_OPEN_SOURCE, &desc->flags); | ||
1269 | } else | 1271 | } else |
1270 | WARN_ON(extra_checks); | 1272 | WARN_ON(extra_checks); |
1271 | 1273 | ||
@@ -1290,6 +1292,9 @@ int gpio_request_one(unsigned gpio, unsigned long flags, const char *label) | |||
1290 | if (flags & GPIOF_OPEN_DRAIN) | 1292 | if (flags & GPIOF_OPEN_DRAIN) |
1291 | set_bit(FLAG_OPEN_DRAIN, &gpio_desc[gpio].flags); | 1293 | set_bit(FLAG_OPEN_DRAIN, &gpio_desc[gpio].flags); |
1292 | 1294 | ||
1295 | if (flags & GPIOF_OPEN_SOURCE) | ||
1296 | set_bit(FLAG_OPEN_SOURCE, &gpio_desc[gpio].flags); | ||
1297 | |||
1293 | if (flags & GPIOF_DIR_IN) | 1298 | if (flags & GPIOF_DIR_IN) |
1294 | err = gpio_direction_input(gpio); | 1299 | err = gpio_direction_input(gpio); |
1295 | else | 1300 | else |
@@ -1443,6 +1448,10 @@ int gpio_direction_output(unsigned gpio, int value) | |||
1443 | if (value && test_bit(FLAG_OPEN_DRAIN, &desc->flags)) | 1448 | if (value && test_bit(FLAG_OPEN_DRAIN, &desc->flags)) |
1444 | return gpio_direction_input(gpio); | 1449 | return gpio_direction_input(gpio); |
1445 | 1450 | ||
1451 | /* Open source pin should not be driven to 0 */ | ||
1452 | if (!value && test_bit(FLAG_OPEN_SOURCE, &desc->flags)) | ||
1453 | return gpio_direction_input(gpio); | ||
1454 | |||
1446 | spin_lock_irqsave(&gpio_lock, flags); | 1455 | spin_lock_irqsave(&gpio_lock, flags); |
1447 | 1456 | ||
1448 | if (!gpio_is_valid(gpio)) | 1457 | if (!gpio_is_valid(gpio)) |
@@ -1604,6 +1613,32 @@ static void _gpio_set_open_drain_value(unsigned gpio, | |||
1604 | __func__, gpio, err); | 1613 | __func__, gpio, err); |
1605 | } | 1614 | } |
1606 | 1615 | ||
1616 | /* | ||
1617 | * _gpio_set_open_source() - Set the open source gpio's value. | ||
1618 | * @gpio: Gpio whose state need to be set. | ||
1619 | * @chip: Gpio chip. | ||
1620 | * @value: Non-zero for setting it HIGH otherise it will set to LOW. | ||
1621 | */ | ||
1622 | static void _gpio_set_open_source_value(unsigned gpio, | ||
1623 | struct gpio_chip *chip, int value) | ||
1624 | { | ||
1625 | int err = 0; | ||
1626 | if (value) { | ||
1627 | err = chip->direction_output(chip, gpio - chip->base, 1); | ||
1628 | if (!err) | ||
1629 | set_bit(FLAG_IS_OUT, &gpio_desc[gpio].flags); | ||
1630 | } else { | ||
1631 | err = chip->direction_input(chip, gpio - chip->base); | ||
1632 | if (!err) | ||
1633 | clear_bit(FLAG_IS_OUT, &gpio_desc[gpio].flags); | ||
1634 | } | ||
1635 | trace_gpio_direction(gpio, !value, err); | ||
1636 | if (err < 0) | ||
1637 | pr_err("%s: Error in set_value for open source gpio%d err %d\n", | ||
1638 | __func__, gpio, err); | ||
1639 | } | ||
1640 | |||
1641 | |||
1607 | /** | 1642 | /** |
1608 | * __gpio_set_value() - assign a gpio's value | 1643 | * __gpio_set_value() - assign a gpio's value |
1609 | * @gpio: gpio whose value will be assigned | 1644 | * @gpio: gpio whose value will be assigned |
@@ -1622,6 +1657,8 @@ void __gpio_set_value(unsigned gpio, int value) | |||
1622 | trace_gpio_value(gpio, 0, value); | 1657 | trace_gpio_value(gpio, 0, value); |
1623 | if (test_bit(FLAG_OPEN_DRAIN, &gpio_desc[gpio].flags)) | 1658 | if (test_bit(FLAG_OPEN_DRAIN, &gpio_desc[gpio].flags)) |
1624 | _gpio_set_open_drain_value(gpio, chip, value); | 1659 | _gpio_set_open_drain_value(gpio, chip, value); |
1660 | else if (test_bit(FLAG_OPEN_SOURCE, &gpio_desc[gpio].flags)) | ||
1661 | _gpio_set_open_source_value(gpio, chip, value); | ||
1625 | else | 1662 | else |
1626 | chip->set(chip, gpio - chip->base, value); | 1663 | chip->set(chip, gpio - chip->base, value); |
1627 | } | 1664 | } |
@@ -1692,6 +1729,8 @@ void gpio_set_value_cansleep(unsigned gpio, int value) | |||
1692 | trace_gpio_value(gpio, 0, value); | 1729 | trace_gpio_value(gpio, 0, value); |
1693 | if (test_bit(FLAG_OPEN_DRAIN, &gpio_desc[gpio].flags)) | 1730 | if (test_bit(FLAG_OPEN_DRAIN, &gpio_desc[gpio].flags)) |
1694 | _gpio_set_open_drain_value(gpio, chip, value); | 1731 | _gpio_set_open_drain_value(gpio, chip, value); |
1732 | else if (test_bit(FLAG_OPEN_SOURCE, &gpio_desc[gpio].flags)) | ||
1733 | _gpio_set_open_source_value(gpio, chip, value); | ||
1695 | else | 1734 | else |
1696 | chip->set(chip, gpio - chip->base, value); | 1735 | chip->set(chip, gpio - chip->base, value); |
1697 | } | 1736 | } |