diff options
Diffstat (limited to 'drivers/gpio/gpiolib-acpi.c')
-rw-r--r-- | drivers/gpio/gpiolib-acpi.c | 111 |
1 files changed, 64 insertions, 47 deletions
diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index 143a9bdbaa53..a38cf16a5828 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c @@ -389,6 +389,8 @@ struct acpi_gpio_lookup { struct acpi_gpio_info info; int index; int pin_index; + bool active_low; + struct acpi_device *adev; struct gpio_desc *desc; int n; }; @@ -425,6 +427,59 @@ static int acpi_find_gpio(struct acpi_resource *ares, void *data) return 1; } +static int acpi_gpio_resource_lookup(struct acpi_gpio_lookup *lookup, + struct acpi_gpio_info *info) +{ + struct list_head res_list; + int ret; + + INIT_LIST_HEAD(&res_list); + + ret = acpi_dev_get_resources(lookup->adev, &res_list, acpi_find_gpio, + lookup); + if (ret < 0) + return ret; + + acpi_dev_free_resource_list(&res_list); + + if (!lookup->desc) + return -ENOENT; + + if (info) { + *info = lookup->info; + if (lookup->active_low) + info->active_low = lookup->active_low; + } + return 0; +} + +static int acpi_gpio_property_lookup(struct acpi_device *adev, + const char *propname, int index, + struct acpi_gpio_lookup *lookup) +{ + struct acpi_reference_args args; + int ret; + + memset(&args, 0, sizeof(args)); + ret = acpi_dev_get_property_reference(adev, propname, index, &args); + if (ret && !acpi_get_driver_gpio_data(adev, propname, index, &args)) + return ret; + + /* + * The property was found and resolved, so need to lookup the GPIO based + * on returned args. + */ + lookup->adev = args.adev; + if (args.nargs >= 2) { + lookup->index = args.args[0]; + lookup->pin_index = args.args[1]; + /* 3rd argument, if present is used to specify active_low. */ + if (args.nargs >= 3) + lookup->active_low = !!args.args[2]; + } + return 0; +} + /** * acpi_get_gpiod_by_index() - get a GPIO descriptor from device resources * @adev: pointer to a ACPI device to get GPIO from @@ -452,8 +507,6 @@ struct gpio_desc *acpi_get_gpiod_by_index(struct acpi_device *adev, struct acpi_gpio_info *info) { struct acpi_gpio_lookup lookup; - struct list_head resource_list; - bool active_low = false; int ret; if (!adev) @@ -463,58 +516,22 @@ struct gpio_desc *acpi_get_gpiod_by_index(struct acpi_device *adev, lookup.index = index; if (propname) { - struct acpi_reference_args args; - dev_dbg(&adev->dev, "GPIO: looking up %s\n", propname); - memset(&args, 0, sizeof(args)); - ret = acpi_dev_get_property_reference(adev, propname, - index, &args); - if (ret) { - bool found = acpi_get_driver_gpio_data(adev, propname, - index, &args); - if (!found) - return ERR_PTR(ret); - } + ret = acpi_gpio_property_lookup(adev, propname, index, &lookup); + if (ret) + return ERR_PTR(ret); - /* - * The property was found and resolved so need to - * lookup the GPIO based on returned args instead. - */ - adev = args.adev; - if (args.nargs >= 2) { - lookup.index = args.args[0]; - lookup.pin_index = args.args[1]; - /* - * 3rd argument, if present is used to - * specify active_low. - */ - if (args.nargs >= 3) - active_low = !!args.args[2]; - } - - dev_dbg(&adev->dev, "GPIO: _DSD returned %s %zd %llu %llu %llu\n", - dev_name(&adev->dev), args.nargs, - args.args[0], args.args[1], args.args[2]); + dev_dbg(&adev->dev, "GPIO: _DSD returned %s %d %d %u\n", + dev_name(&lookup.adev->dev), lookup.index, + lookup.pin_index, lookup.active_low); } else { dev_dbg(&adev->dev, "GPIO: looking up %d in _CRS\n", index); + lookup.adev = adev; } - INIT_LIST_HEAD(&resource_list); - ret = acpi_dev_get_resources(adev, &resource_list, acpi_find_gpio, - &lookup); - if (ret < 0) - return ERR_PTR(ret); - - acpi_dev_free_resource_list(&resource_list); - - if (lookup.desc && info) { - *info = lookup.info; - if (active_low) - info->active_low = active_low; - } - - return lookup.desc ? lookup.desc : ERR_PTR(-ENOENT); + ret = acpi_gpio_resource_lookup(&lookup, info); + return ret ? ERR_PTR(ret) : lookup.desc; } /** |