gpio_wdt may need to start the GPIO toggle as soon as possible,
when the watchdog cannot be disabled. Raise the initcall to
arch_initcall.

We need to split the initiation, because of miscdev, as done in
mpc8xxx_wdt.c

Signed-off-by: Jean-Baptiste Theou <[email protected]>
---
 drivers/watchdog/gpio_wdt.c | 78 ++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 74 insertions(+), 4 deletions(-)

diff --git a/drivers/watchdog/gpio_wdt.c b/drivers/watchdog/gpio_wdt.c
index cbc313d..8ecfe7e 100644
--- a/drivers/watchdog/gpio_wdt.c
+++ b/drivers/watchdog/gpio_wdt.c
@@ -14,6 +14,7 @@
 #include <linux/module.h>
 #include <linux/notifier.h>
 #include <linux/of_gpio.h>
+#include <linux/of_platform.h>
 #include <linux/platform_device.h>
 #include <linux/reboot.h>
 #include <linux/watchdog.h>
@@ -223,10 +224,11 @@ static int gpio_wdt_probe(struct platform_device *pdev)
 
        setup_timer(&priv->timer, gpio_wdt_hwping, (unsigned long)&priv->wdd);
 
-       ret = watchdog_register_device(&priv->wdd);
+#ifdef MODULE
+       ret = gpio_wdt_init_late();
        if (ret)
                return ret;
-
+#endif
        priv->notifier.notifier_call = gpio_wdt_notify_sys;
        ret = register_reboot_notifier(&priv->notifier);
        if (ret)
@@ -235,10 +237,13 @@ static int gpio_wdt_probe(struct platform_device *pdev)
        if (priv->always_running)
                gpio_wdt_start_impl(priv);
 
+       platform_set_drvdata(pdev, priv);
        return 0;
 
 error_unregister:
-       watchdog_unregister_device(&priv->wdd);
+#ifdef MODULE
+       ret = gpio_wdt_remove_late(&priv->wdd);
+#endif
        return ret;
 }
 
@@ -267,7 +272,72 @@ static struct platform_driver gpio_wdt_driver = {
        .probe  = gpio_wdt_probe,
        .remove = gpio_wdt_remove,
 };
-module_platform_driver(gpio_wdt_driver);
+
+/*
+ * We do wdt initialization in two steps: arch_initcall probes the wdt
+ * very early to start pinging the watchdog (misc devices are not yet
+ * available), and later module_init() just registers the misc device.
+ */
+static int gpio_wdt_init_late(void)
+{
+       struct platform_device *pdev;
+       struct device_node *wdt_node;
+       struct gpio_wdt_priv *priv;
+       int ret;
+
+       for_each_compatible_node(wdt_node, NULL, "linux,wdt-gpio") {
+               pdev = of_find_device_by_node(wdt_node);
+               priv = platform_get_drvdata(pdev);
+               if (&priv->wdd) {
+                       ret = watchdog_register_device(&priv->wdd);
+                       if (ret)
+                               return ret;
+               } else {
+                       dev_err(&pdev->dev, "Unable to register the 
watchdog\n");
+                       return -1;
+               }
+       }
+       return 0;
+}
+#ifndef MODULE
+module_init(gpio_wdt_init_late);
+#endif
+
+#ifdef MODULE
+int gpio_wdt_remove_late(void)
+{
+       struct platform_device *pdev;
+       struct device_node *wdt_node;
+       struct gpio_wdt_priv *priv;
+       int ret;
+
+       for_each_compatible_node(wdt_node, NULL, "linux,wdt-gpio") {
+               pdev = of_find_device_by_node(wdt_node);
+               priv = platform_get_drvdata(pdev);
+               if (&priv->wdd) {
+                       ret = watchdog_unregister_device(&priv->wdd);
+                       if (ret)
+                               return ret;
+               } else {
+                       dev_err(&pdev->dev, "Unable to register the 
watchdog\n");
+                       return -1;
+               }
+       }
+       return 0;
+}
+#endif
+
+static int __init gpio_wdt_init(void)
+{
+       return platform_driver_register(&gpio_wdt_driver);
+}
+arch_initcall(gpio_wdt_init);
+
+static void __exit gpio_wdt_exit(void)
+{
+       platform_driver_unregister(&gpio_wdt_driver);
+}
+module_exit(gpio_wdt_exit);
 
 MODULE_AUTHOR("Alexander Shiyan <[email protected]>");
 MODULE_DESCRIPTION("GPIO Watchdog");
-- 
2.4.2

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

Reply via email to