[09/11] gpiolib: of: tease apart acpi_find_gpio()
diff mbox series

Message ID 20190911075215.78047-10-dmitry.torokhov@gmail.com
State Not Applicable, archived
Headers show
Series
  • Add support for software nodes to gpiolib
Related show

Commit Message

dmitry.torokhov@gmail.com Sept. 11, 2019, 7:52 a.m. UTC
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(-)

Comments

Andy Shevchenko Sept. 11, 2019, 5:12 p.m. UTC | #1
On Wed, Sep 11, 2019 at 12:52:13AM -0700, Dmitry Torokhov wrote:
> 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().

Title should start with "gpiolib: acpi:"


I review from this one later on.

Patch
diff mbox series

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);
 		}
 	}