|
@@ -201,6 +201,83 @@ void acpi_gpiochip_request_interrupts(struct gpio_chip *chip)
|
|
|
}
|
|
|
EXPORT_SYMBOL(acpi_gpiochip_request_interrupts);
|
|
|
|
|
|
+struct acpi_gpio_lookup {
|
|
|
+ struct acpi_gpio_info info;
|
|
|
+ int index;
|
|
|
+ int gpio;
|
|
|
+ int n;
|
|
|
+};
|
|
|
+
|
|
|
+static int acpi_find_gpio(struct acpi_resource *ares, void *data)
|
|
|
+{
|
|
|
+ struct acpi_gpio_lookup *lookup = data;
|
|
|
+
|
|
|
+ if (ares->type != ACPI_RESOURCE_TYPE_GPIO)
|
|
|
+ return 1;
|
|
|
+
|
|
|
+ if (lookup->n++ == lookup->index && lookup->gpio < 0) {
|
|
|
+ const struct acpi_resource_gpio *agpio = &ares->data.gpio;
|
|
|
+
|
|
|
+ lookup->gpio = acpi_get_gpio(agpio->resource_source.string_ptr,
|
|
|
+ agpio->pin_table[0]);
|
|
|
+ lookup->info.gpioint =
|
|
|
+ agpio->connection_type == ACPI_RESOURCE_GPIO_TYPE_INT;
|
|
|
+ }
|
|
|
+
|
|
|
+ return 1;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * acpi_get_gpio_by_index() - get a GPIO number from device resources
|
|
|
+ * @dev: pointer to a device to get GPIO from
|
|
|
+ * @index: index of GpioIo/GpioInt resource (starting from %0)
|
|
|
+ * @info: info pointer to fill in (optional)
|
|
|
+ *
|
|
|
+ * Function goes through ACPI resources for @dev and based on @index looks
|
|
|
+ * up a GpioIo/GpioInt resource, translates it to the Linux GPIO number,
|
|
|
+ * and returns it. @index matches GpioIo/GpioInt resources only so if there
|
|
|
+ * are total %3 GPIO resources, the index goes from %0 to %2.
|
|
|
+ *
|
|
|
+ * If the GPIO cannot be translated or there is an error, negative errno is
|
|
|
+ * returned.
|
|
|
+ *
|
|
|
+ * Note: if the GPIO resource has multiple entries in the pin list, this
|
|
|
+ * function only returns the first.
|
|
|
+ */
|
|
|
+int acpi_get_gpio_by_index(struct device *dev, int index,
|
|
|
+ struct acpi_gpio_info *info)
|
|
|
+{
|
|
|
+ struct acpi_gpio_lookup lookup;
|
|
|
+ struct list_head resource_list;
|
|
|
+ struct acpi_device *adev;
|
|
|
+ acpi_handle handle;
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ if (!dev)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ handle = ACPI_HANDLE(dev);
|
|
|
+ if (!handle || acpi_bus_get_device(handle, &adev))
|
|
|
+ return -ENODEV;
|
|
|
+
|
|
|
+ memset(&lookup, 0, sizeof(lookup));
|
|
|
+ lookup.index = index;
|
|
|
+ lookup.gpio = -ENODEV;
|
|
|
+
|
|
|
+ INIT_LIST_HEAD(&resource_list);
|
|
|
+ ret = acpi_dev_get_resources(adev, &resource_list, acpi_find_gpio,
|
|
|
+ &lookup);
|
|
|
+ if (ret < 0)
|
|
|
+ return ret;
|
|
|
+
|
|
|
+ acpi_dev_free_resource_list(&resource_list);
|
|
|
+
|
|
|
+ if (lookup.gpio >= 0 && info)
|
|
|
+ *info = lookup.info;
|
|
|
+
|
|
|
+ return lookup.gpio;
|
|
|
+}
|
|
|
+EXPORT_SYMBOL_GPL(acpi_get_gpio_by_index);
|
|
|
|
|
|
/**
|
|
|
* acpi_gpiochip_free_interrupts() - Free GPIO _EVT ACPI event interrupts.
|