aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpio
diff options
context:
space:
mode:
authorLaxman Dewangan <ldewangan@nvidia.com>2012-02-17 09:56:22 -0500
committerGrant Likely <grant.likely@secretlab.ca>2012-03-05 09:49:44 -0500
commit25553ff0756c59b617af6bdd280c94e943164184 (patch)
tree6ca9ec045b5d2e10523fdf46facac59aa683f4ce /drivers/gpio
parentaca5ce14eb773a75e5d935968b2e390dc5bd29c3 (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.c39
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 */
1622static 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}