|
@@ -14,6 +14,8 @@
|
|
|
#include <linux/watchdog.h>
|
|
|
#include <linux/platform_device.h>
|
|
|
#include <linux/stmp3xxx_rtc_wdt.h>
|
|
|
+#include <linux/notifier.h>
|
|
|
+#include <linux/reboot.h>
|
|
|
|
|
|
#define WDOG_TICK_RATE 1000 /* 1 kHz clock */
|
|
|
#define STMP3XXX_DEFAULT_TIMEOUT 19
|
|
@@ -69,6 +71,28 @@ static struct watchdog_device stmp3xxx_wdd = {
|
|
|
.status = WATCHDOG_NOWAYOUT_INIT_STATUS,
|
|
|
};
|
|
|
|
|
|
+static int wdt_notify_sys(struct notifier_block *nb, unsigned long code,
|
|
|
+ void *unused)
|
|
|
+{
|
|
|
+ struct device *dev = watchdog_get_drvdata(&stmp3xxx_wdd);
|
|
|
+ struct stmp3xxx_wdt_pdata *pdata = dev_get_platdata(dev);
|
|
|
+
|
|
|
+ switch (code) {
|
|
|
+ case SYS_DOWN: /* keep enabled, system might crash while going down */
|
|
|
+ break;
|
|
|
+ case SYS_HALT: /* allow the system to actually halt */
|
|
|
+ case SYS_POWER_OFF:
|
|
|
+ wdt_stop(&stmp3xxx_wdd);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ return NOTIFY_DONE;
|
|
|
+}
|
|
|
+
|
|
|
+static struct notifier_block wdt_notifier = {
|
|
|
+ .notifier_call = wdt_notify_sys,
|
|
|
+};
|
|
|
+
|
|
|
static int stmp3xxx_wdt_probe(struct platform_device *pdev)
|
|
|
{
|
|
|
int ret;
|
|
@@ -84,6 +108,9 @@ static int stmp3xxx_wdt_probe(struct platform_device *pdev)
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
+ if (register_reboot_notifier(&wdt_notifier))
|
|
|
+ dev_warn(&pdev->dev, "cannot register reboot notifier\n");
|
|
|
+
|
|
|
dev_info(&pdev->dev, "initialized watchdog with heartbeat %ds\n",
|
|
|
stmp3xxx_wdd.timeout);
|
|
|
return 0;
|
|
@@ -91,6 +118,7 @@ static int stmp3xxx_wdt_probe(struct platform_device *pdev)
|
|
|
|
|
|
static int stmp3xxx_wdt_remove(struct platform_device *pdev)
|
|
|
{
|
|
|
+ unregister_reboot_notifier(&wdt_notifier);
|
|
|
watchdog_unregister_device(&stmp3xxx_wdd);
|
|
|
return 0;
|
|
|
}
|