diff options
Diffstat (limited to 'drivers/gpio/gpiolib.c')
-rw-r--r-- | drivers/gpio/gpiolib.c | 85 |
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, | |||
1713 | EXPORT_SYMBOL_GPL(__gpiod_get_index); | 1735 | EXPORT_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 | */ | ||
1751 | struct 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 | } | ||
1790 | EXPORT_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 |