aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpio/gpiolib.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpio/gpiolib.c')
-rw-r--r--drivers/gpio/gpiolib.c83
1 files changed, 81 insertions, 2 deletions
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index a971e3d043b..a0fa0b25d21 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -58,6 +58,8 @@ struct gpio_desc {
58#define FLAG_TRIG_FALL 5 /* trigger on falling edge */ 58#define FLAG_TRIG_FALL 5 /* trigger on falling edge */
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 */
62#define FLAG_OPEN_SOURCE 9 /* Gpio is open source type */
61 63
62#define ID_SHIFT 16 /* add new flags before this one */ 64#define ID_SHIFT 16 /* add new flags before this one */
63 65
@@ -1257,6 +1259,8 @@ void gpio_free(unsigned gpio)
1257 module_put(desc->chip->owner); 1259 module_put(desc->chip->owner);
1258 clear_bit(FLAG_ACTIVE_LOW, &desc->flags); 1260 clear_bit(FLAG_ACTIVE_LOW, &desc->flags);
1259 clear_bit(FLAG_REQUESTED, &desc->flags); 1261 clear_bit(FLAG_REQUESTED, &desc->flags);
1262 clear_bit(FLAG_OPEN_DRAIN, &desc->flags);
1263 clear_bit(FLAG_OPEN_SOURCE, &desc->flags);
1260 } else 1264 } else
1261 WARN_ON(extra_checks); 1265 WARN_ON(extra_checks);
1262 1266
@@ -1278,6 +1282,12 @@ int gpio_request_one(unsigned gpio, unsigned long flags, const char *label)
1278 if (err) 1282 if (err)
1279 return err; 1283 return err;
1280 1284
1285 if (flags & GPIOF_OPEN_DRAIN)
1286 set_bit(FLAG_OPEN_DRAIN, &gpio_desc[gpio].flags);
1287
1288 if (flags & GPIOF_OPEN_SOURCE)
1289 set_bit(FLAG_OPEN_SOURCE, &gpio_desc[gpio].flags);
1290
1281 if (flags & GPIOF_DIR_IN) 1291 if (flags & GPIOF_DIR_IN)
1282 err = gpio_direction_input(gpio); 1292 err = gpio_direction_input(gpio);
1283 else 1293 else
@@ -1427,6 +1437,14 @@ int gpio_direction_output(unsigned gpio, int value)
1427 struct gpio_desc *desc = &gpio_desc[gpio]; 1437 struct gpio_desc *desc = &gpio_desc[gpio];
1428 int status = -EINVAL; 1438 int status = -EINVAL;
1429 1439
1440 /* Open drain pin should not be driven to 1 */
1441 if (value && test_bit(FLAG_OPEN_DRAIN, &desc->flags))
1442 return gpio_direction_input(gpio);
1443
1444 /* Open source pin should not be driven to 0 */
1445 if (!value && test_bit(FLAG_OPEN_SOURCE, &desc->flags))
1446 return gpio_direction_input(gpio);
1447
1430 spin_lock_irqsave(&gpio_lock, flags); 1448 spin_lock_irqsave(&gpio_lock, flags);
1431 1449
1432 if (!gpio_is_valid(gpio)) 1450 if (!gpio_is_valid(gpio))
@@ -1563,6 +1581,57 @@ int __gpio_get_value(unsigned gpio)
1563} 1581}
1564EXPORT_SYMBOL_GPL(__gpio_get_value); 1582EXPORT_SYMBOL_GPL(__gpio_get_value);
1565 1583
1584/*
1585 * _gpio_set_open_drain_value() - Set the open drain gpio's value.
1586 * @gpio: Gpio whose state need to be set.
1587 * @chip: Gpio chip.
1588 * @value: Non-zero for setting it HIGH otherise it will set to LOW.
1589 */
1590static void _gpio_set_open_drain_value(unsigned gpio,
1591 struct gpio_chip *chip, int value)
1592{
1593 int err = 0;
1594 if (value) {
1595 err = chip->direction_input(chip, gpio - chip->base);
1596 if (!err)
1597 clear_bit(FLAG_IS_OUT, &gpio_desc[gpio].flags);
1598 } else {
1599 err = chip->direction_output(chip, gpio - chip->base, 0);
1600 if (!err)
1601 set_bit(FLAG_IS_OUT, &gpio_desc[gpio].flags);
1602 }
1603 trace_gpio_direction(gpio, value, err);
1604 if (err < 0)
1605 pr_err("%s: Error in set_value for open drain gpio%d err %d\n",
1606 __func__, gpio, err);
1607}
1608
1609/*
1610 * _gpio_set_open_source() - Set the open source gpio's value.
1611 * @gpio: Gpio whose state need to be set.
1612 * @chip: Gpio chip.
1613 * @value: Non-zero for setting it HIGH otherise it will set to LOW.
1614 */
1615static void _gpio_set_open_source_value(unsigned gpio,
1616 struct gpio_chip *chip, int value)
1617{
1618 int err = 0;
1619 if (value) {
1620 err = chip->direction_output(chip, gpio - chip->base, 1);
1621 if (!err)
1622 set_bit(FLAG_IS_OUT, &gpio_desc[gpio].flags);
1623 } else {
1624 err = chip->direction_input(chip, gpio - chip->base);
1625 if (!err)
1626 clear_bit(FLAG_IS_OUT, &gpio_desc[gpio].flags);
1627 }
1628 trace_gpio_direction(gpio, !value, err);
1629 if (err < 0)
1630 pr_err("%s: Error in set_value for open source gpio%d err %d\n",
1631 __func__, gpio, err);
1632}
1633
1634
1566/** 1635/**
1567 * __gpio_set_value() - assign a gpio's value 1636 * __gpio_set_value() - assign a gpio's value
1568 * @gpio: gpio whose value will be assigned 1637 * @gpio: gpio whose value will be assigned
@@ -1579,7 +1648,12 @@ void __gpio_set_value(unsigned gpio, int value)
1579 chip = gpio_to_chip(gpio); 1648 chip = gpio_to_chip(gpio);
1580 WARN_ON(chip->can_sleep); 1649 WARN_ON(chip->can_sleep);
1581 trace_gpio_value(gpio, 0, value); 1650 trace_gpio_value(gpio, 0, value);
1582 chip->set(chip, gpio - chip->base, value); 1651 if (test_bit(FLAG_OPEN_DRAIN, &gpio_desc[gpio].flags))
1652 _gpio_set_open_drain_value(gpio, chip, value);
1653 else if (test_bit(FLAG_OPEN_SOURCE, &gpio_desc[gpio].flags))
1654 _gpio_set_open_source_value(gpio, chip, value);
1655 else
1656 chip->set(chip, gpio - chip->base, value);
1583} 1657}
1584EXPORT_SYMBOL_GPL(__gpio_set_value); 1658EXPORT_SYMBOL_GPL(__gpio_set_value);
1585 1659
@@ -1646,7 +1720,12 @@ void gpio_set_value_cansleep(unsigned gpio, int value)
1646 might_sleep_if(extra_checks); 1720 might_sleep_if(extra_checks);
1647 chip = gpio_to_chip(gpio); 1721 chip = gpio_to_chip(gpio);
1648 trace_gpio_value(gpio, 0, value); 1722 trace_gpio_value(gpio, 0, value);
1649 chip->set(chip, gpio - chip->base, value); 1723 if (test_bit(FLAG_OPEN_DRAIN, &gpio_desc[gpio].flags))
1724 _gpio_set_open_drain_value(gpio, chip, value);
1725 else if (test_bit(FLAG_OPEN_SOURCE, &gpio_desc[gpio].flags))
1726 _gpio_set_open_source_value(gpio, chip, value);
1727 else
1728 chip->set(chip, gpio - chip->base, value);
1650} 1729}
1651EXPORT_SYMBOL_GPL(gpio_set_value_cansleep); 1730EXPORT_SYMBOL_GPL(gpio_set_value_cansleep);
1652 1731