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 <[email protected]>
---

 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

Reply via email to