[PATCH 08/11] gpiolib: of: tease apart of_find_gpio()

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

Tease apart of_find_gpio() into common function that works on the
firmware node, and a fallback handler that works on the device
structure, so that we can later use of_find_gpio() in
fwnode_gpiod_get_index().

Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---

drivers/gpio/gpiolib-of.c | 149 +++++++++++++++++++-------------------
drivers/gpio/gpiolib-of.h | 26 +++++--
drivers/gpio/gpiolib.c | 7 +-
3 files changed, 99 insertions(+), 83 deletions(-)

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);
--
2.23.0.162.g0b9fbb3734-goog