Skip to content

Commit

Permalink
pinctrl: bcm2835: Change init order for gpio hogs
Browse files Browse the repository at this point in the history
pinctrl-bcm2835 is a combined pinctrl/gpio driver. Currently the gpio
side is registered first, but this breaks gpio hogs (which are
configured during gpiochip_add_data). Part of the hog initialisation
is a call to pinctrl_gpio_request, and since the pinctrl driver hasn't
yet been registered this results in an -EPROBE_DEFER from which it can
never recover.

Change the initialisation sequence to register the pinctrl driver
first.

See: https://www.raspberrypi.org/forums/viewtopic.php?f=107&t=260600

Signed-off-by: Phil Elwell <phil@raspberrypi.org>
  • Loading branch information
Phil Elwell committed Jan 7, 2020
1 parent e99b5a3 commit c2bc59c
Showing 1 changed file with 17 additions and 23 deletions.
40 changes: 17 additions & 23 deletions drivers/pinctrl/bcm/pinctrl-bcm2835.c
Original file line number Diff line number Diff line change
Expand Up @@ -1140,16 +1140,33 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev)
raw_spin_lock_init(&pc->irq_lock[i]);
}

match = of_match_node(bcm2835_pinctrl_match, pdev->dev.of_node);
if (match) {
bcm2835_pinctrl_desc.confops =
(const struct pinconf_ops *)match->data;
}

pc->pctl_dev = devm_pinctrl_register(dev, &bcm2835_pinctrl_desc, pc);
if (IS_ERR(pc->pctl_dev))
return PTR_ERR(pc->pctl_dev);

pc->gpio_range = bcm2835_pinctrl_gpio_range;
pc->gpio_range.base = pc->gpio_chip.base;
pc->gpio_range.gc = &pc->gpio_chip;
pinctrl_add_gpio_range(pc->pctl_dev, &pc->gpio_range);

err = devm_gpiochip_add_data(dev, &pc->gpio_chip, pc);
if (err) {
dev_err(dev, "could not add GPIO chip\n");
pinctrl_remove_gpio_range(pc->pctl_dev, &pc->gpio_range);
return err;
}

err = gpiochip_irqchip_add(&pc->gpio_chip, &bcm2835_gpio_irq_chip,
0, handle_level_irq, IRQ_TYPE_NONE);
if (err) {
dev_info(dev, "could not add irqchip\n");
pinctrl_remove_gpio_range(pc->pctl_dev, &pc->gpio_range);
return err;
}

Expand All @@ -1172,29 +1189,6 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev)
bcm2835_gpio_irq_handler);
}

match = of_match_node(bcm2835_pinctrl_match, pdev->dev.of_node);
if (match) {
bcm2835_pinctrl_desc.confops =
(const struct pinconf_ops *)match->data;
}

match = of_match_node(bcm2835_pinctrl_match, pdev->dev.of_node);
if (match) {
bcm2835_pinctrl_desc.confops =
(const struct pinconf_ops *)match->data;
}

pc->pctl_dev = devm_pinctrl_register(dev, &bcm2835_pinctrl_desc, pc);
if (IS_ERR(pc->pctl_dev)) {
gpiochip_remove(&pc->gpio_chip);
return PTR_ERR(pc->pctl_dev);
}

pc->gpio_range = bcm2835_pinctrl_gpio_range;
pc->gpio_range.base = pc->gpio_chip.base;
pc->gpio_range.gc = &pc->gpio_chip;
pinctrl_add_gpio_range(pc->pctl_dev, &pc->gpio_range);

return 0;
}

Expand Down

0 comments on commit c2bc59c

Please sign in to comment.