Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 28355f81 authored by Tomeu Vizoso's avatar Tomeu Vizoso Committed by Linus Walleij
Browse files

gpio: defer probe if pinctrl cannot be found



When an OF node has a pin range for its GPIOs, return -EPROBE_DEFER if
the pin controller isn't available.

Otherwise, the GPIO range wouldn't be set at all unless the pin
controller probed always before the GPIO chip.

With this change, the probe of the GPIO chip will be deferred and will
be retried at a later point, hopefully once the pin controller has been
registered and probed already.

Signed-off-by: default avatarTomeu Vizoso <tomeu.vizoso@collabora.com>
Signed-off-by: default avatarLinus Walleij <linus.walleij@linaro.org>
parent 23393d49
Loading
Loading
Loading
Loading
+18 −9
Original line number Diff line number Diff line
@@ -335,7 +335,7 @@ void of_mm_gpiochip_remove(struct of_mm_gpio_chip *mm_gc)
EXPORT_SYMBOL(of_mm_gpiochip_remove);

#ifdef CONFIG_PINCTRL
static void of_gpiochip_add_pin_range(struct gpio_chip *chip)
static int of_gpiochip_add_pin_range(struct gpio_chip *chip)
{
	struct device_node *np = chip->of_node;
	struct of_phandle_args pinspec;
@@ -346,7 +346,7 @@ static void of_gpiochip_add_pin_range(struct gpio_chip *chip)
	struct property *group_names;

	if (!np)
		return;
		return 0;

	group_names = of_find_property(np, group_names_propname, NULL);

@@ -358,7 +358,7 @@ static void of_gpiochip_add_pin_range(struct gpio_chip *chip)

		pctldev = of_pinctrl_get(pinspec.np);
		if (!pctldev)
			break;
			return -EPROBE_DEFER;

		if (pinspec.args[2]) {
			if (group_names) {
@@ -378,7 +378,7 @@ static void of_gpiochip_add_pin_range(struct gpio_chip *chip)
					pinspec.args[1],
					pinspec.args[2]);
			if (ret)
				break;
				return ret;
		} else {
			/* npins == 0: special range */
			if (pinspec.args[1]) {
@@ -408,32 +408,41 @@ static void of_gpiochip_add_pin_range(struct gpio_chip *chip)
			ret = gpiochip_add_pingroup_range(chip, pctldev,
						pinspec.args[0], name);
			if (ret)
				break;
				return ret;
		}
	}

	return 0;
}

#else
static void of_gpiochip_add_pin_range(struct gpio_chip *chip) {}
static int of_gpiochip_add_pin_range(struct gpio_chip *chip) { return 0; }
#endif

void of_gpiochip_add(struct gpio_chip *chip)
int of_gpiochip_add(struct gpio_chip *chip)
{
	int status;

	if ((!chip->of_node) && (chip->dev))
		chip->of_node = chip->dev->of_node;

	if (!chip->of_node)
		return;
		return 0;

	if (!chip->of_xlate) {
		chip->of_gpio_n_cells = 2;
		chip->of_xlate = of_gpio_simple_xlate;
	}

	of_gpiochip_add_pin_range(chip);
	status = of_gpiochip_add_pin_range(chip);
	if (status)
		return status;

	of_node_get(chip->of_node);

	of_gpiochip_scan_hogs(chip);

	return 0;
}

void of_gpiochip_remove(struct gpio_chip *chip)
+4 −1
Original line number Diff line number Diff line
@@ -290,7 +290,10 @@ int gpiochip_add(struct gpio_chip *chip)
	if (!chip->owner && chip->dev && chip->dev->driver)
		chip->owner = chip->dev->driver->owner;

	of_gpiochip_add(chip);
	status = of_gpiochip_add(chip);
	if (status)
		goto err_remove_chip;

	acpi_gpiochip_add(chip);

	status = gpiochip_sysfs_register(chip);
+2 −2
Original line number Diff line number Diff line
@@ -54,7 +54,7 @@ extern int of_mm_gpiochip_add(struct device_node *np,
			      struct of_mm_gpio_chip *mm_gc);
extern void of_mm_gpiochip_remove(struct of_mm_gpio_chip *mm_gc);

extern void of_gpiochip_add(struct gpio_chip *gc);
extern int of_gpiochip_add(struct gpio_chip *gc);
extern void of_gpiochip_remove(struct gpio_chip *gc);
extern int of_gpio_simple_xlate(struct gpio_chip *gc,
				const struct of_phandle_args *gpiospec,
@@ -76,7 +76,7 @@ static inline int of_gpio_simple_xlate(struct gpio_chip *gc,
	return -ENOSYS;
}

static inline void of_gpiochip_add(struct gpio_chip *gc) { }
static inline int of_gpiochip_add(struct gpio_chip *gc) { return 0; }
static inline void of_gpiochip_remove(struct gpio_chip *gc) { }

#endif /* CONFIG_OF_GPIO */