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@xxxxxxxxx> --- 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