123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161 |
- From e058fa1969019c2f6705c53c4130e364a877d4e6 Mon Sep 17 00:00:00 2001
- From: Jonas Gorski <[email protected]>
- Date: Sun, 26 Nov 2017 12:07:31 +0100
- Subject: [PATCH] gpio: fix device tree gpio hogs on dual role gpio/pincontrol
- controllers
- For dual role gpio and pincontrol controller, the device registration
- path is often:
- pinctrl_register(...);
- gpiochip_add_data(...);
- gpiochip_add_pin_range(...);
- If the device tree node has any gpio-hogs, the code will try to apply them
- in the gpiochip_add_data step, but fail as they cannot be requested, as the
- ranges are missing. But we also cannot first add the pinranges, as the
- appropriate data structures are only initialized in gpiochip_add_data.
- To fix this, defer gpio-hogs to the time pin ranges get added instead of
- directly at chip request time, if the gpio-chip has a request method.
- Signed-off-by: Jonas Gorski <[email protected]>
- ---
- drivers/gpio/gpiolib-of.c | 20 +++++++++++++++-----
- drivers/gpio/gpiolib.c | 5 +++--
- drivers/gpio/gpiolib.h | 8 ++++++++
- 3 files changed, 26 insertions(+), 7 deletions(-)
- --- a/drivers/gpio/gpiolib-of.c
- +++ b/drivers/gpio/gpiolib-of.c
- @@ -646,23 +646,30 @@ static struct gpio_desc *of_parse_own_gp
- * of_gpiochip_add_hog - Add all hogs in a hog device node
- * @chip: gpio chip to act on
- * @hog: device node describing the hogs
- + * @start: first gpio to check
- + * @num: number of gpios to check
- *
- * Returns error if it fails otherwise 0 on success.
- */
- -static int of_gpiochip_add_hog(struct gpio_chip *chip, struct device_node *hog)
- +static int of_gpiochip_add_hog(struct gpio_chip *chip, struct device_node *hog,
- + unsigned int start, unsigned int num)
- {
- enum gpiod_flags dflags;
- struct gpio_desc *desc;
- unsigned long lflags;
- const char *name;
- unsigned int i;
- - int ret;
- + int ret, hwgpio;
-
- for (i = 0;; i++) {
- desc = of_parse_own_gpio(hog, chip, i, &name, &lflags, &dflags);
- if (IS_ERR(desc))
- break;
-
- + hwgpio = gpio_chip_hwgpio(desc);
- + if (hwgpio < start || hwgpio >= (start + num))
- + continue;
- +
- ret = gpiod_hog(desc, name, lflags, dflags);
- if (ret < 0)
- return ret;
- @@ -678,12 +685,15 @@ static int of_gpiochip_add_hog(struct gp
- /**
- * of_gpiochip_scan_gpios - Scan gpio-controller for gpio definitions
- * @chip: gpio chip to act on
- + * @start: first gpio to check
- + * @num: number of gpios to check
- *
- - * This is only used by of_gpiochip_add to request/set GPIO initial
- - * configuration.
- + * This is used by of_gpiochip_add, gpiochip_add_pingroup_range and
- + * gpiochip_add_pin_range to request/set GPIO initial configuration.
- * It returns error if it fails otherwise 0 on success.
- */
- -static int of_gpiochip_scan_gpios(struct gpio_chip *chip)
- +int of_gpiochip_scan_gpios(struct gpio_chip *chip, unsigned int start,
- + unsigned int num)
- {
- struct device_node *np;
- int ret;
- @@ -692,7 +702,7 @@ static int of_gpiochip_scan_gpios(struct
- if (!of_property_read_bool(np, "gpio-hog"))
- continue;
-
- - ret = of_gpiochip_add_hog(chip, np);
- + ret = of_gpiochip_add_hog(chip, np, start, num);
- if (ret < 0) {
- of_node_put(np);
- return ret;
- @@ -758,7 +768,7 @@ static int of_gpio_notify(struct notifie
- if (chip == NULL)
- return NOTIFY_OK; /* not for us */
-
- - ret = of_gpiochip_add_hog(chip, rd->dn);
- + ret = of_gpiochip_add_hog(chip, rd->dn, 0, chip->ngpio);
- if (ret < 0) {
- pr_err("%s: failed to add hogs for %pOF\n", __func__,
- rd->dn);
- @@ -1030,9 +1040,11 @@ int of_gpiochip_add(struct gpio_chip *ch
-
- of_node_get(chip->of_node);
-
- - ret = of_gpiochip_scan_gpios(chip);
- - if (ret)
- - of_node_put(chip->of_node);
- + if (!chip->request) {
- + ret = of_gpiochip_scan_gpios(chip, 0, chip->ngpio);
- + if (ret)
- + of_node_put(chip->of_node);
- + }
-
- return ret;
- }
- --- a/drivers/gpio/gpiolib.c
- +++ b/drivers/gpio/gpiolib.c
- @@ -1893,7 +1893,8 @@ int gpiochip_add_pingroup_range(struct g
-
- list_add_tail(&pin_range->node, &gdev->pin_ranges);
-
- - return 0;
- + return of_gpiochip_scan_gpios(gc, gpio_offset,
- + pin_range->range.npins);
- }
- EXPORT_SYMBOL_GPL(gpiochip_add_pingroup_range);
-
- @@ -1950,7 +1951,7 @@ int gpiochip_add_pin_range(struct gpio_c
-
- list_add_tail(&pin_range->node, &gdev->pin_ranges);
-
- - return 0;
- + return of_gpiochip_scan_gpios(gc, gpio_offset, npins);
- }
- EXPORT_SYMBOL_GPL(gpiochip_add_pin_range);
-
- --- a/drivers/gpio/gpiolib-of.h
- +++ b/drivers/gpio/gpiolib-of.h
- @@ -13,6 +13,8 @@ struct gpio_desc *of_find_gpio(struct de
- unsigned long *lookupflags);
- int of_gpiochip_add(struct gpio_chip *gc);
- void of_gpiochip_remove(struct gpio_chip *gc);
- +int of_gpiochip_scan_gpios(struct gpio_chip *chip, unsigned int start,
- + unsigned int num);
- int of_gpio_get_count(struct device *dev, const char *con_id);
- bool of_gpio_need_valid_mask(const struct gpio_chip *gc);
- #else
- @@ -25,6 +27,12 @@ static inline struct gpio_desc *of_find_
- }
- static inline int of_gpiochip_add(struct gpio_chip *gc) { return 0; }
- static inline void of_gpiochip_remove(struct gpio_chip *gc) { }
- +static inline int of_gpiochip_scan_gpios(struct gpio_chip *chip,
- + unsigned int start,
- + unsigned int num)
- +{
- + return 0;
- +}
- static inline int of_gpio_get_count(struct device *dev, const char *con_id)
- {
- return 0;
|