diff options
Diffstat (limited to 'drivers/of/of_gpio.c')
-rw-r--r-- | drivers/of/of_gpio.c | 74 |
1 files changed, 56 insertions, 18 deletions
diff --git a/drivers/of/of_gpio.c b/drivers/of/of_gpio.c index e1cafdc848..25496a3cf1 100644 --- a/drivers/of/of_gpio.c +++ b/drivers/of/of_gpio.c @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: GPL-2.0-only + #include <common.h> #include <errno.h> #include <of.h> @@ -28,8 +30,8 @@ static void of_gpio_flags_quirks(struct device_node *np, * be actively ignored. */ if ((*flags & OF_GPIO_ACTIVE_LOW) && !active_low) { - pr_warn("%s GPIO handle specifies active low - ignored\n", - np->full_name); + pr_warn("%pOF GPIO handle specifies active low - ignored\n", + np); *flags &= ~OF_GPIO_ACTIVE_LOW; } if (active_low) @@ -44,6 +46,44 @@ static void of_gpio_flags_quirks(struct device_node *np, } +static struct gpio_chip *of_find_gpiochip_by_xlate( + struct of_phandle_args *gpiospec) +{ + struct gpio_chip *chip; + struct device *dev; + + dev = of_find_device_by_node(gpiospec->np); + if (!dev) { + pr_debug("%s: unable to find device of node %pOF\n", + __func__, gpiospec->np); + return NULL; + } + + chip = gpio_get_chip_by_dev(dev); + if (!chip) { + pr_debug("%s: unable to find gpiochip\n", __func__); + return NULL; + } + + if (!chip->ops->of_xlate || + chip->ops->of_xlate(chip, gpiospec, NULL) < 0) { + pr_err("%s: failed to execute of_xlate\n", __func__); + return NULL; + } + + return chip; +} + +static int of_xlate_and_get_gpiod_flags(struct gpio_chip *chip, + struct of_phandle_args *gpiospec, + enum of_gpio_flags *flags) +{ + if (chip->of_gpio_n_cells != gpiospec->args_count) + return -EINVAL; + + return chip->ops->of_xlate(chip, gpiospec, flags); +} + /** * of_get_named_gpio_flags() - Get a GPIO number and flags to use with GPIO API * @np: device node to get GPIO from @@ -58,38 +98,36 @@ static void of_gpio_flags_quirks(struct device_node *np, int of_get_named_gpio_flags(struct device_node *np, const char *propname, int index, enum of_gpio_flags *flags) { - struct of_phandle_args out_args; - struct device_d *dev; + struct of_phandle_args gpiospec; + struct gpio_chip *chip; int ret; ret = of_parse_phandle_with_args(np, propname, "#gpio-cells", - index, &out_args); + index, &gpiospec); if (ret) { pr_debug("%s: cannot parse %s property: %d\n", __func__, propname, ret); return ret; } - dev = of_find_device_by_node(out_args.np); - if (!dev) { - pr_debug("%s: unable to find device of node %s\n", - __func__, out_args.np->full_name); - return -EPROBE_DEFER; + chip = of_find_gpiochip_by_xlate(&gpiospec); + if (!chip) { + ret = -EPROBE_DEFER; + goto out; } - ret = gpio_get_num(dev, out_args.args[0]); - if (ret == -EPROBE_DEFER) - return ret; + ret = of_xlate_and_get_gpiod_flags(chip, &gpiospec, flags); if (ret < 0) { pr_err("%s: unable to get gpio num of device %s: %d\n", - __func__, dev_name(dev), ret); - return ret; + __func__, dev_name(chip->dev), ret); + goto out; } - if (flags) { - *flags = out_args.args[1]; + if (flags) of_gpio_flags_quirks(np, propname, flags, index); - } + +out: + of_node_put(gpiospec.np); return ret; } |