Instead of deferring if pinctrl_request_gpio() returns
-EPROBE_DEFER, queue the GPIO number and request it later,
when the pinctrl part of the driver probes.

This is because we will otherwise have a circular dependency
between the GPIO and pinctrl parts of the driver: the new
auto-reservation of IRQ pins from the DT code will attempt
to request a GPIO line as soon as the gpiochip is added,
but this calls pinctrl_request_gpio() which count on the
pinctrl backend being present, and the pinctrl backend will
not probe until all the GPIO blocks have probed. So we
get locked up in a circular loop unless we do something
like this.

Signed-off-by: Linus Walleij <[email protected]>
---
 drivers/pinctrl/pinctrl-nomadik.c | 48 ++++++++++++++++++++++++++++++++++++++-
 1 file changed, 47 insertions(+), 1 deletion(-)

diff --git a/drivers/pinctrl/pinctrl-nomadik.c 
b/drivers/pinctrl/pinctrl-nomadik.c
index 4a1cfdc..ee87e73 100644
--- a/drivers/pinctrl/pinctrl-nomadik.c
+++ b/drivers/pinctrl/pinctrl-nomadik.c
@@ -1010,6 +1010,31 @@ static int nmk_gpio_init_irq(struct nmk_gpio_chip 
*nmk_chip)
 
 /* I/O Functions */
 
+struct nmk_gpio_req {
+        struct list_head node;
+       int gpio;
+};
+
+static LIST_HEAD(nmk_queued_gpio_requests);
+
+static void nmk_pinctrl_process_queued_gpio_requests(void)
+{
+       struct list_head *node, *tmp;
+
+        list_for_each_safe(node, tmp, &nmk_queued_gpio_requests) {
+                struct nmk_gpio_req *req =
+                       list_entry(node, struct nmk_gpio_req, node);
+               int ret;
+               ret = pinctrl_request_gpio(req->gpio);
+               if (ret)
+                       pr_err("failed to request queued GPIO %d\n", req->gpio);
+               else
+                       pr_info("requested queued GPIO %d\n", req->gpio);
+                list_del(node);
+                kfree(req);
+        }
+}
+
 static int nmk_gpio_request(struct gpio_chip *chip, unsigned offset)
 {
        /*
@@ -1017,8 +1042,28 @@ static int nmk_gpio_request(struct gpio_chip *chip, 
unsigned offset)
         * parameter does not matter for this controller.
         */
        int gpio = chip->base + offset;
+       int ret;
+
+       ret = pinctrl_request_gpio(gpio);
+       if (ret == -EPROBE_DEFER) {
+               /*
+                * This may happen during system startup: we request a GPIO
+                * for being used for IRQ when registering the GPIO controller
+                * for example, but the pin controller is not yet online.
+                * Store the request on a list to be done when the
+                * pin controller comes online. In our driver the GPIO
+                * blocks must always probe before the pin controller.
+                */
+               struct nmk_gpio_req *req = kzalloc(sizeof(struct nmk_gpio_req), 
GFP_KERNEL);
 
-       return pinctrl_request_gpio(gpio);
+               if (!req)
+                       return -ENOMEM;
+               req->gpio = gpio;
+               list_add_tail(&req->node, &nmk_queued_gpio_requests);
+               pr_info("queueing pinctrl_request_gpio(%d)\n", req->gpio);
+               ret = 0;
+       }
+       return ret;
 }
 
 static void nmk_gpio_free(struct gpio_chip *chip, unsigned offset)
@@ -2224,6 +2269,7 @@ static int nmk_pinctrl_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, npct);
        dev_info(&pdev->dev, "initialized Nomadik pin control driver\n");
+       nmk_pinctrl_process_queued_gpio_requests();
 
        return 0;
 }
-- 
1.8.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-gpio" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to