diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c
index 8b773f7d7724..1d1a18e0ad93 100644
--- a/drivers/gpio/gpiolib-of.c
+++ b/drivers/gpio/gpiolib-of.c
@@ -276,6 +276,28 @@ int of_get_named_gpio_flags(struct device_node *np, const char *list_name,
 }
 EXPORT_SYMBOL(of_get_named_gpio_flags);
 
+static void of_gpio_flags_to_lookup(enum of_gpio_flags of_flags,
+				    unsigned long *flags)
+{
+	if (of_flags & OF_GPIO_ACTIVE_LOW)
+		*flags |= GPIO_ACTIVE_LOW;
+
+	if (of_flags & OF_GPIO_SINGLE_ENDED) {
+		if (of_flags & OF_GPIO_OPEN_DRAIN)
+			*flags |= GPIO_OPEN_DRAIN;
+		else
+			*flags |= GPIO_OPEN_SOURCE;
+	}
+
+	if (of_flags & OF_GPIO_TRANSITORY)
+		*flags |= GPIO_TRANSITORY;
+
+	if (of_flags & OF_GPIO_PULL_UP)
+		*flags |= GPIO_PULL_UP;
+	if (of_flags & OF_GPIO_PULL_DOWN)
+		*flags |= GPIO_PULL_DOWN;
+}
+
 /**
  * gpiod_get_from_of_node() - obtain a GPIO from an OF node
  * @node:	handle of the OF node
@@ -298,10 +320,6 @@ struct gpio_desc *gpiod_get_from_of_node(struct device_node *node,
 	unsigned long lflags = GPIO_LOOKUP_FLAGS_DEFAULT;
 	struct gpio_desc *desc;
 	enum of_gpio_flags flags;
-	bool active_low = false;
-	bool single_ended = false;
-	bool open_drain = false;
-	bool transitory = false;
 	int ret;
 
 	desc = of_get_named_gpiod_flags(node, propname,
@@ -311,29 +329,13 @@ struct gpio_desc *gpiod_get_from_of_node(struct device_node *node,
 		return desc;
 	}
 
-	active_low = flags & OF_GPIO_ACTIVE_LOW;
-	single_ended = flags & OF_GPIO_SINGLE_ENDED;
-	open_drain = flags & OF_GPIO_OPEN_DRAIN;
-	transitory = flags & OF_GPIO_TRANSITORY;
-
 	ret = gpiod_request(desc, label);
 	if (ret == -EBUSY && (flags & GPIOD_FLAGS_BIT_NONEXCLUSIVE))
 		return desc;
 	if (ret)
 		return ERR_PTR(ret);
 
-	if (active_low)
-		lflags |= GPIO_ACTIVE_LOW;
-
-	if (single_ended) {
-		if (open_drain)
-			lflags |= GPIO_OPEN_DRAIN;
-		else
-			lflags |= GPIO_OPEN_SOURCE;
-	}
-
-	if (transitory)
-		lflags |= GPIO_TRANSITORY;
+	of_gpio_flags_to_lookup(flags, &lflags);
 
 	ret = gpiod_configure_flags(desc, propname, lflags, dflags);
 	if (ret < 0) {
@@ -345,6 +347,46 @@ struct gpio_desc *gpiod_get_from_of_node(struct device_node *node,
 }
 EXPORT_SYMBOL(gpiod_get_from_of_node);
 
+static struct gpio_desc *of_find_node_gpio(struct device_node *np,
+					   const char *con_id, unsigned int idx,
+					   enum of_gpio_flags *of_flags)
+{
+	struct gpio_desc *desc;
+	char prop_name[32]; /* 32 is max size of property name */
+	unsigned int i;
+
+	/* Try GPIO property "foo-gpios" and "foo-gpio" */
+	for (i = 0; i < ARRAY_SIZE(gpio_suffixes); i++) {
+		if (con_id)
+			snprintf(prop_name, sizeof(prop_name), "%s-%s", con_id,
+				 gpio_suffixes[i]);
+		else
+			snprintf(prop_name, sizeof(prop_name), "%s",
+				 gpio_suffixes[i]);
+
+		desc = of_get_named_gpiod_flags(np, prop_name, idx, of_flags);
+		if (!IS_ERR(desc) || PTR_ERR(desc) != -ENOENT)
+			break;
+	}
+
+	return desc;
+}
+
+struct gpio_desc *of_find_gpio(struct fwnode_handle *fwnode,
+			       const char *con_id, unsigned int idx,
+			       unsigned long *flags)
+{
+	struct device_node *np = to_of_node(fwnode);
+	struct gpio_desc *desc;
+	enum of_gpio_flags of_flags;
+
+	desc = of_find_node_gpio(np, con_id, idx, &of_flags);
+	if (!IS_ERR(desc))
+		of_gpio_flags_to_lookup(of_flags, flags);
+
+	return desc;
+}
+
 /*
  * The SPI GPIO bindings happened before we managed to establish that GPIO
  * properties should be named "foo-gpios" so we have this special kludge for
@@ -383,7 +425,7 @@ static struct gpio_desc *of_find_spi_gpio(struct device *dev, const char *con_id
 static struct gpio_desc *of_find_spi_cs_gpio(struct device *dev,
 					     const char *con_id,
 					     unsigned int idx,
-					     unsigned long *flags)
+					     enum of_gpio_flags *of_flags)
 {
 	struct device_node *np = dev->of_node;
 
@@ -403,7 +445,7 @@ static struct gpio_desc *of_find_spi_cs_gpio(struct device *dev,
 	 * uses just "gpios" so translate to that when "cs-gpios" is
 	 * requested.
 	 */
-	return of_find_gpio(dev, NULL, idx, flags);
+	return of_find_node_gpio(dev->of_node, NULL, idx, of_flags);
 }
 
 /*
@@ -451,41 +493,18 @@ static struct gpio_desc *of_find_arizona_gpio(struct device *dev,
 	return of_get_named_gpiod_flags(dev->of_node, con_id, 0, of_flags);
 }
 
-struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id,
-			       unsigned int idx, unsigned long *flags)
+struct gpio_desc *of_find_gpio_fallback(struct device *dev,
+					const char *con_id, unsigned int idx,
+					unsigned long *flags)
 {
-	char prop_name[32]; /* 32 is max size of property name */
-	enum of_gpio_flags of_flags;
 	struct gpio_desc *desc;
-	unsigned int i;
-
-	/* Try GPIO property "foo-gpios" and "foo-gpio" */
-	for (i = 0; i < ARRAY_SIZE(gpio_suffixes); i++) {
-		if (con_id)
-			snprintf(prop_name, sizeof(prop_name), "%s-%s", con_id,
-				 gpio_suffixes[i]);
-		else
-			snprintf(prop_name, sizeof(prop_name), "%s",
-				 gpio_suffixes[i]);
-
-		desc = of_get_named_gpiod_flags(dev->of_node, prop_name, idx,
-						&of_flags);
-
-		if (!IS_ERR(desc) || PTR_ERR(desc) != -ENOENT)
-			break;
-	}
+	enum of_gpio_flags of_flags;
 
-	if (IS_ERR(desc) && PTR_ERR(desc) == -ENOENT) {
-		/* Special handling for SPI GPIOs if used */
-		desc = of_find_spi_gpio(dev, con_id, &of_flags);
-	}
+	/* Special handling for SPI GPIOs if used */
+	desc = of_find_spi_gpio(dev, con_id, &of_flags);
 
-	if (IS_ERR(desc) && PTR_ERR(desc) == -ENOENT) {
-		/* This quirk looks up flags and all */
-		desc = of_find_spi_cs_gpio(dev, con_id, idx, flags);
-		if (!IS_ERR(desc))
-			return desc;
-	}
+	if (IS_ERR(desc) && PTR_ERR(desc) == -ENOENT)
+		desc = of_find_spi_cs_gpio(dev, con_id, idx, &of_flags);
 
 	if (IS_ERR(desc) && PTR_ERR(desc) == -ENOENT) {
 		/* Special handling for regulator GPIOs if used */
@@ -495,26 +514,8 @@ struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id,
 	if (IS_ERR(desc) && PTR_ERR(desc) == -ENOENT)
 		desc = of_find_arizona_gpio(dev, con_id, &of_flags);
 
-	if (IS_ERR(desc))
-		return desc;
-
-	if (of_flags & OF_GPIO_ACTIVE_LOW)
-		*flags |= GPIO_ACTIVE_LOW;
-
-	if (of_flags & OF_GPIO_SINGLE_ENDED) {
-		if (of_flags & OF_GPIO_OPEN_DRAIN)
-			*flags |= GPIO_OPEN_DRAIN;
-		else
-			*flags |= GPIO_OPEN_SOURCE;
-	}
-
-	if (of_flags & OF_GPIO_TRANSITORY)
-		*flags |= GPIO_TRANSITORY;
-
-	if (of_flags & OF_GPIO_PULL_UP)
-		*flags |= GPIO_PULL_UP;
-	if (of_flags & OF_GPIO_PULL_DOWN)
-		*flags |= GPIO_PULL_DOWN;
+	if (!IS_ERR(desc))
+		of_gpio_flags_to_lookup(of_flags, flags);
 
 	return desc;
 }
diff --git a/drivers/gpio/gpiolib-of.h b/drivers/gpio/gpiolib-of.h
index 454d1658ee2d..580539cd995f 100644
--- a/drivers/gpio/gpiolib-of.h
+++ b/drivers/gpio/gpiolib-of.h
@@ -3,14 +3,17 @@
 #ifndef GPIOLIB_OF_H
 #define GPIOLIB_OF_H
 
+struct fwnode_handle;
 struct gpio_chip;
 enum of_gpio_flags;
 
 #ifdef CONFIG_OF_GPIO
-struct gpio_desc *of_find_gpio(struct device *dev,
-			       const char *con_id,
-			       unsigned int idx,
-			       unsigned long *lookupflags);
+struct gpio_desc *of_find_gpio(struct fwnode_handle *fwnode,
+			       const char *con_id, unsigned int idx,
+			       unsigned long *flags);
+struct gpio_desc *of_find_gpio_fallback(struct device *dev,
+					const char *con_id, unsigned int idx,
+					unsigned long *flags);
 struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np,
 		   const char *list_name, int index, enum of_gpio_flags *flags);
 int of_gpiochip_add(struct gpio_chip *gc);
@@ -18,10 +21,17 @@ void of_gpiochip_remove(struct gpio_chip *gc);
 int of_gpio_get_count(struct device *dev, const char *con_id);
 bool of_gpio_need_valid_mask(const struct gpio_chip *gc);
 #else
-static inline struct gpio_desc *of_find_gpio(struct device *dev,
-					     const char *con_id,
-					     unsigned int idx,
-					     unsigned long *lookupflags)
+static inline
+struct gpio_desc *of_find_gpio(struct fwnode_handle *fwnode,
+			       const char *con_id, unsigned int idx,
+			       unsigned long *flags)
+{
+	return ERR_PTR(-ENOENT);
+}
+static inline
+struct gpio_desc *of_find_gpio_fallback(struct device *dev,
+					const char *con_id, unsigned int idx,
+					unsigned long *flags)
 {
 	return ERR_PTR(-ENOENT);
 }
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 54db2c42e9a0..1248e61f9a23 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -4562,7 +4562,12 @@ struct gpio_desc *__must_check gpiod_get_index(struct device *dev,
 		/* Using device tree? */
 		if (IS_ENABLED(CONFIG_OF) && dev->of_node) {
 			dev_dbg(dev, "using device tree for GPIO lookup\n");
-			desc = of_find_gpio(dev, con_id, idx, &lookupflags);
+			desc = of_find_gpio(dev_fwnode(dev),
+					    con_id, idx, &lookupflags);
+			if (desc == ERR_PTR(-ENOENT))
+				desc = of_find_gpio_fallback(dev, con_id, idx,
+							     &lookupflags);
+
 		} else if (ACPI_COMPANION(dev)) {
 			dev_dbg(dev, "using ACPI for GPIO lookup\n");
 			desc = acpi_find_gpio(dev, con_id, idx, &flags, &lookupflags);
