[PATCH 09/11] gpiolib: of: tease apart acpi_find_gpio()

Dmitry Torokhov
2019-09-11T07:52:34Z

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@gmail.com>
---

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