net: phy: dp83848: add dp83822 PHY support
[cascardo/linux.git] / drivers / gpio / gpiolib-acpi.c
index af51461..58ece20 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/gpio.h>
 #include <linux/gpio/consumer.h>
 #include <linux/gpio/driver.h>
+#include <linux/gpio/machine.h>
 #include <linux/export.h>
 #include <linux/acpi.h>
 #include <linux/interrupt.h>
@@ -395,7 +396,7 @@ struct acpi_gpio_lookup {
        int n;
 };
 
-static int acpi_find_gpio(struct acpi_resource *ares, void *data)
+static int acpi_populate_gpio_lookup(struct acpi_resource *ares, void *data)
 {
        struct acpi_gpio_lookup *lookup = data;
 
@@ -440,7 +441,8 @@ static int acpi_gpio_resource_lookup(struct acpi_gpio_lookup *lookup,
 
        INIT_LIST_HEAD(&res_list);
 
-       ret = acpi_dev_get_resources(lookup->adev, &res_list, acpi_find_gpio,
+       ret = acpi_dev_get_resources(lookup->adev, &res_list,
+                                    acpi_populate_gpio_lookup,
                                     lookup);
        if (ret < 0)
                return ret;
@@ -513,7 +515,7 @@ static int acpi_gpio_property_lookup(struct fwnode_handle *fwnode,
  * Note: if the GPIO resource has multiple entries in the pin list, this
  * function only returns the first.
  */
-struct gpio_desc *acpi_get_gpiod_by_index(struct acpi_device *adev,
+static struct gpio_desc *acpi_get_gpiod_by_index(struct acpi_device *adev,
                                          const char *propname, int index,
                                          struct acpi_gpio_info *info)
 {
@@ -546,6 +548,55 @@ struct gpio_desc *acpi_get_gpiod_by_index(struct acpi_device *adev,
        return ret ? ERR_PTR(ret) : lookup.desc;
 }
 
+struct gpio_desc *acpi_find_gpio(struct device *dev,
+                                const char *con_id,
+                                unsigned int idx,
+                                enum gpiod_flags flags,
+                                enum gpio_lookup_flags *lookupflags)
+{
+       struct acpi_device *adev = ACPI_COMPANION(dev);
+       struct acpi_gpio_info info;
+       struct gpio_desc *desc;
+       char propname[32];
+       int i;
+
+       /* Try first from _DSD */
+       for (i = 0; i < ARRAY_SIZE(gpio_suffixes); i++) {
+               if (con_id && strcmp(con_id, "gpios")) {
+                       snprintf(propname, sizeof(propname), "%s-%s",
+                                con_id, gpio_suffixes[i]);
+               } else {
+                       snprintf(propname, sizeof(propname), "%s",
+                                gpio_suffixes[i]);
+               }
+
+               desc = acpi_get_gpiod_by_index(adev, propname, idx, &info);
+               if (!IS_ERR(desc) || (PTR_ERR(desc) == -EPROBE_DEFER))
+                       break;
+       }
+
+       /* Then from plain _CRS GPIOs */
+       if (IS_ERR(desc)) {
+               if (!acpi_can_fallback_to_crs(adev, con_id))
+                       return ERR_PTR(-ENOENT);
+
+               desc = acpi_get_gpiod_by_index(adev, NULL, idx, &info);
+               if (IS_ERR(desc))
+                       return desc;
+
+               if ((flags == GPIOD_OUT_LOW || flags == GPIOD_OUT_HIGH) &&
+                   info.gpioint) {
+                       dev_dbg(dev, "refusing GpioInt() entry when doing GPIOD_OUT_* lookup\n");
+                       return ERR_PTR(-ENOENT);
+               }
+       }
+
+       if (info.polarity == GPIO_ACTIVE_LOW)
+               *lookupflags |= GPIO_ACTIVE_LOW;
+
+       return desc;
+}
+
 /**
  * acpi_node_get_gpiod() - get a GPIO descriptor from ACPI resources
  * @fwnode: pointer to an ACPI firmware node to get the GPIO information from