Tease apart acpi_find_gpio() into common function that works on the firmware node, and a fallback handler that works on the ACPI device structure, so that we can later use acpi_find_gpio() in fwnode_gpiod_get_index(). Signed-off-by: Dmitry Torokhov <dmitry.torokhov@xxxxxxxxx> --- drivers/gpio/gpiolib-acpi.c | 77 +++++++++++++++++++++++++------------ drivers/gpio/gpiolib-acpi.h | 17 +++++++- drivers/gpio/gpiolib.c | 8 +++- 3 files changed, 74 insertions(+), 28 deletions(-) diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index 2b6fdc9947f7..8174db1bc02e 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c @@ -728,29 +728,35 @@ static struct gpio_desc *acpi_get_gpiod_by_index(struct acpi_device *adev, return ret ? ERR_PTR(ret) : lookup.desc; } -static bool acpi_can_fallback_to_crs(struct acpi_device *adev, - const char *con_id) +static int acpi_finalize_gpio_lookup(struct acpi_gpio_info *info, + enum gpiod_flags *dflags, + unsigned long *lookupflags) { - /* Never allow fallback if the device has properties */ - if (acpi_dev_has_props(adev) || adev->driver_gpios) - return false; + if (info->gpioint && + (*dflags == GPIOD_OUT_LOW || *dflags == GPIOD_OUT_HIGH)) { + dev_dbg(&info->adev->dev, + "refusing GpioInt() entry when doing GPIOD_OUT_* lookup\n"); + return -ENOENT; + } - return con_id == NULL; + acpi_gpio_update_gpiod_flags(dflags, info); + acpi_gpio_update_gpiod_lookup_flags(lookupflags, info); + + return 0; } -struct gpio_desc *acpi_find_gpio(struct device *dev, - const char *con_id, - unsigned int idx, +struct gpio_desc *acpi_find_gpio(struct fwnode_handle *fwnode, + const char *con_id, unsigned int idx, enum gpiod_flags *dflags, unsigned long *lookupflags) { - struct acpi_device *adev = ACPI_COMPANION(dev); struct acpi_gpio_info info; struct gpio_desc *desc; char propname[32]; int i; + int error; - /* Try first from _DSD */ + /* Try GPIOs from _DSD */ for (i = 0; i < ARRAY_SIZE(gpio_suffixes); i++) { if (con_id) { snprintf(propname, sizeof(propname), "%s-%s", @@ -760,31 +766,52 @@ struct gpio_desc *acpi_find_gpio(struct device *dev, gpio_suffixes[i]); } - desc = acpi_get_gpiod_by_index(adev, propname, idx, &info); + desc = acpi_node_get_gpiod(fwnode, propname, idx, &info); if (!IS_ERR(desc)) break; if (PTR_ERR(desc) == -EPROBE_DEFER) return ERR_CAST(desc); } - /* 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 (!IS_ERR(desc)) { + error = acpi_finalize_gpio_lookup(&info, dflags, lookupflags); + if (error) + return ERR_PTR(error); } - if (info.gpioint && - (*dflags == GPIOD_OUT_LOW || *dflags == GPIOD_OUT_HIGH)) { - dev_dbg(dev, "refusing GpioInt() entry when doing GPIOD_OUT_* lookup\n"); + return desc; +} + +static bool acpi_can_fallback_to_crs(struct acpi_device *adev, + const char *con_id) +{ + /* Never allow fallback if the device has properties */ + if (acpi_dev_has_props(adev) || adev->driver_gpios) + return false; + + return con_id == NULL; +} + +struct gpio_desc *acpi_find_gpio_fallback(struct acpi_device *adev, + const char *con_id, unsigned int idx, + enum gpiod_flags *dflags, + unsigned long *lookupflags) +{ + struct acpi_gpio_info info; + struct gpio_desc *desc; + int error; + + /* Then from plain _CRS GPIOs */ + 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)) { + error = acpi_finalize_gpio_lookup(&info, dflags, lookupflags); + if (error) + return ERR_PTR(error); } - acpi_gpio_update_gpiod_flags(dflags, &info); - acpi_gpio_update_gpiod_lookup_flags(lookupflags, &info); return desc; } diff --git a/drivers/gpio/gpiolib-acpi.h b/drivers/gpio/gpiolib-acpi.h index 1c6d65cf0629..ea97a3822116 100644 --- a/drivers/gpio/gpiolib-acpi.h +++ b/drivers/gpio/gpiolib-acpi.h @@ -9,6 +9,7 @@ #define GPIOLIB_ACPI_H struct acpi_device; +struct fwnode_handle; /** * struct acpi_gpio_info - ACPI GPIO specific information @@ -42,11 +43,16 @@ int acpi_gpio_update_gpiod_flags(enum gpiod_flags *flags, int acpi_gpio_update_gpiod_lookup_flags(unsigned long *lookupflags, struct acpi_gpio_info *info); -struct gpio_desc *acpi_find_gpio(struct device *dev, +struct gpio_desc *acpi_find_gpio(struct fwnode_handle *fwnode, const char *con_id, unsigned int idx, enum gpiod_flags *dflags, unsigned long *lookupflags); +struct gpio_desc *acpi_find_gpio_fallback(struct acpi_device *adev, + const char *con_id, + unsigned int idx, + enum gpiod_flags *dflags, + unsigned long *lookupflags); struct gpio_desc *acpi_node_get_gpiod(struct fwnode_handle *fwnode, const char *propname, int index, struct acpi_gpio_info *info); @@ -75,13 +81,20 @@ acpi_gpio_update_gpiod_lookup_flags(unsigned long *lookupflags, } static inline struct gpio_desc * -acpi_find_gpio(struct device *dev, const char *con_id, +acpi_find_gpio(struct firmware_node *fwnode, const char *con_id, unsigned int idx, enum gpiod_flags *dflags, unsigned long *lookupflags) { return ERR_PTR(-ENOENT); } static inline struct gpio_desc * +acpi_find_gpio_fallback(struct acpi_device *adev, const char *con_id, + unsigned int idx, enum gpiod_flags *dflags, + unsigned long *lookupflags) +{ + return ERR_PTR(-ENOENT); +} +static inline struct gpio_desc * acpi_node_get_gpiod(struct fwnode_handle *fwnode, const char *propname, int index, struct acpi_gpio_info *info) { diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 1248e61f9a23..2d8dd67ab03d 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -4570,7 +4570,13 @@ struct gpio_desc *__must_check gpiod_get_index(struct device *dev, } else if (ACPI_COMPANION(dev)) { dev_dbg(dev, "using ACPI for GPIO lookup\n"); - desc = acpi_find_gpio(dev, con_id, idx, &flags, &lookupflags); + desc = acpi_find_gpio(dev_fwnode(dev), con_id, idx, + &flags, &lookupflags); + if (desc == ERR_PTR(-ENOENT)) + desc = acpi_find_gpio_fallback( + ACPI_COMPANION(dev), + con_id, idx, + &flags, &lookupflags); } } -- 2.23.0.162.g0b9fbb3734-goog