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.c85
1 files changed, 81 insertions, 4 deletions
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index e8e98ca25ec7..58659dbe702a 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -1505,14 +1505,36 @@ static struct gpio_desc *acpi_find_gpio(struct device *dev, const char *con_id,
1505 unsigned int idx, 1505 unsigned int idx,
1506 enum gpio_lookup_flags *flags) 1506 enum gpio_lookup_flags *flags)
1507{ 1507{
1508 static const char * const suffixes[] = { "gpios", "gpio" };
1509 struct acpi_device *adev = ACPI_COMPANION(dev);
1508 struct acpi_gpio_info info; 1510 struct acpi_gpio_info info;
1509 struct gpio_desc *desc; 1511 struct gpio_desc *desc;
1512 char propname[32];
1513 int i;
1510 1514
1511 desc = acpi_get_gpiod_by_index(dev, idx, &info); 1515 /* Try first from _DSD */
1512 if (IS_ERR(desc)) 1516 for (i = 0; i < ARRAY_SIZE(suffixes); i++) {
1513 return desc; 1517 if (con_id && strcmp(con_id, "gpios")) {
1518 snprintf(propname, sizeof(propname), "%s-%s",
1519 con_id, suffixes[i]);
1520 } else {
1521 snprintf(propname, sizeof(propname), "%s",
1522 suffixes[i]);
1523 }
1524
1525 desc = acpi_get_gpiod_by_index(adev, propname, idx, &info);
1526 if (!IS_ERR(desc) || (PTR_ERR(desc) == -EPROBE_DEFER))
1527 break;
1528 }
1514 1529
1515 if (info.gpioint && info.active_low) 1530 /* Then from plain _CRS GPIOs */
1531 if (IS_ERR(desc)) {
1532 desc = acpi_get_gpiod_by_index(adev, NULL, idx, &info);
1533 if (IS_ERR(desc))
1534 return desc;
1535 }
1536
1537 if (info.active_low)
1516 *flags |= GPIO_ACTIVE_LOW; 1538 *flags |= GPIO_ACTIVE_LOW;
1517 1539
1518 return desc; 1540 return desc;
@@ -1713,6 +1735,61 @@ struct gpio_desc *__must_check __gpiod_get_index(struct device *dev,
1713EXPORT_SYMBOL_GPL(__gpiod_get_index); 1735EXPORT_SYMBOL_GPL(__gpiod_get_index);
1714 1736
1715/** 1737/**
1738 * fwnode_get_named_gpiod - obtain a GPIO from firmware node
1739 * @fwnode: handle of the firmware node
1740 * @propname: name of the firmware property representing the GPIO
1741 *
1742 * This function can be used for drivers that get their configuration
1743 * from firmware.
1744 *
1745 * Function properly finds the corresponding GPIO using whatever is the
1746 * underlying firmware interface and then makes sure that the GPIO
1747 * descriptor is requested before it is returned to the caller.
1748 *
1749 * In case of error an ERR_PTR() is returned.
1750 */
1751struct gpio_desc *fwnode_get_named_gpiod(struct fwnode_handle *fwnode,
1752 const char *propname)
1753{
1754 struct gpio_desc *desc = ERR_PTR(-ENODEV);
1755 bool active_low = false;
1756 int ret;
1757
1758 if (!fwnode)
1759 return ERR_PTR(-EINVAL);
1760
1761 if (is_of_node(fwnode)) {
1762 enum of_gpio_flags flags;
1763
1764 desc = of_get_named_gpiod_flags(of_node(fwnode), propname, 0,
1765 &flags);
1766 if (!IS_ERR(desc))
1767 active_low = flags & OF_GPIO_ACTIVE_LOW;
1768 } else if (is_acpi_node(fwnode)) {
1769 struct acpi_gpio_info info;
1770
1771 desc = acpi_get_gpiod_by_index(acpi_node(fwnode), propname, 0,
1772 &info);
1773 if (!IS_ERR(desc))
1774 active_low = info.active_low;
1775 }
1776
1777 if (IS_ERR(desc))
1778 return desc;
1779
1780 ret = gpiod_request(desc, NULL);
1781 if (ret)
1782 return ERR_PTR(ret);
1783
1784 /* Only value flag can be set from both DT and ACPI is active_low */
1785 if (active_low)
1786 set_bit(FLAG_ACTIVE_LOW, &desc->flags);
1787
1788 return desc;
1789}
1790EXPORT_SYMBOL_GPL(fwnode_get_named_gpiod);
1791
1792/**
1716 * gpiod_get_index_optional - obtain an optional GPIO from a multi-index GPIO 1793 * gpiod_get_index_optional - obtain an optional GPIO from a multi-index GPIO
1717 * function 1794 * function
1718 * @dev: GPIO consumer, can be NULL for system-global GPIOs 1795 * @dev: GPIO consumer, can be NULL for system-global GPIOs