aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpio/gpiolib-acpi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpio/gpiolib-acpi.c')
-rw-r--r--drivers/gpio/gpiolib-acpi.c43
1 files changed, 41 insertions, 2 deletions
diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c
index 8aa6ca473748..5a4d061e787e 100644
--- a/drivers/gpio/gpiolib-acpi.c
+++ b/drivers/gpio/gpiolib-acpi.c
@@ -287,6 +287,41 @@ void acpi_gpiochip_free_interrupts(struct gpio_chip *chip)
}
}
+int acpi_dev_add_driver_gpios(struct acpi_device *adev,
+ const struct acpi_gpio_mapping *gpios)
+{
+ if (adev && gpios) {
+ adev->driver_gpios = gpios;
+ return 0;
+ }
+ return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(acpi_dev_add_driver_gpios);
+
+static bool acpi_get_driver_gpio_data(struct acpi_device *adev,
+ const char *name, int index,
+ struct acpi_reference_args *args)
+{
+ const struct acpi_gpio_mapping *gm;
+
+ if (!adev->driver_gpios)
+ return false;
+
+ for (gm = adev->driver_gpios; gm->name; gm++)
+ if (!strcmp(name, gm->name) && gm->data && index < gm->size) {
+ const struct acpi_gpio_params *par = gm->data + index;
+
+ args->adev = adev;
+ args->args[0] = par->crs_entry_index;
+ args->args[1] = par->line_index;
+ args->args[2] = par->active_low;
+ args->nargs = 3;
+ return true;
+ }
+
+ return false;
+}
+
struct acpi_gpio_lookup {
struct acpi_gpio_info info;
int index;
@@ -372,8 +407,12 @@ struct gpio_desc *acpi_get_gpiod_by_index(struct acpi_device *adev,
memset(&args, 0, sizeof(args));
ret = acpi_dev_get_property_reference(adev, propname, NULL,
index, &args);
- if (ret)
- return ERR_PTR(ret);
+ if (ret) {
+ bool found = acpi_get_driver_gpio_data(adev, propname,
+ index, &args);
+ if (!found)
+ return ERR_PTR(ret);
+ }
/*
* The property was found and resolved so need to