pinctrl: bcm2835: Change init order for gpio hogs
authorPhil Elwell <phil@raspberrypi.org>
Mon, 6 Jan 2020 14:05:42 +0000 (14:05 +0000)
committerpopcornmix <popcornmix@gmail.com>
Wed, 1 Jul 2020 15:33:13 +0000 (16:33 +0100)
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>
drivers/pinctrl/bcm/pinctrl-bcm2835.c

index c8db202..cf30821 100644 (file)
@@ -1140,9 +1140,25 @@ 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;
        }
 
@@ -1150,6 +1166,7 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev)
                                   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;
        }
 
@@ -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;
 }