*/
#include <linux/delay.h>
-#include <linux/reboot.h>
#include <linux/types.h>
#include <linux/module.h>
#include <linux/io.h>
struct bcm2835_wdt {
void __iomem *base;
spinlock_t lock;
- struct notifier_block restart_handler;
};
static unsigned int heartbeat;
return WDOG_TICKS_TO_SECS(ret & PM_WDOG_TIME_SET);
}
+static void __bcm2835_restart(struct bcm2835_wdt *wdt)
+{
+ u32 val;
+
+ /* use a timeout of 10 ticks (~150us) */
+ writel_relaxed(10 | PM_PASSWORD, wdt->base + PM_WDOG);
+ val = readl_relaxed(wdt->base + PM_RSTC);
+ val &= PM_RSTC_WRCFG_CLR;
+ val |= PM_PASSWORD | PM_RSTC_WRCFG_FULL_RESET;
+ writel_relaxed(val, wdt->base + PM_RSTC);
+
+ /* No sleeping, possibly atomic. */
+ mdelay(1);
+}
+
+static int bcm2835_restart(struct watchdog_device *wdog,
+ unsigned long action, void *data)
+{
+ struct bcm2835_wdt *wdt = watchdog_get_drvdata(wdog);
+
+ __bcm2835_restart(wdt);
+
+ return 0;
+}
+
static const struct watchdog_ops bcm2835_wdt_ops = {
.owner = THIS_MODULE,
.start = bcm2835_wdt_start,
.stop = bcm2835_wdt_stop,
.get_timeleft = bcm2835_wdt_get_timeleft,
+ .restart = bcm2835_restart,
};
static const struct watchdog_info bcm2835_wdt_info = {
.timeout = WDOG_TICKS_TO_SECS(PM_WDOG_TIME_SET),
};
-static int
-bcm2835_restart(struct notifier_block *this, unsigned long mode, void *cmd)
-{
- struct bcm2835_wdt *wdt = container_of(this, struct bcm2835_wdt,
- restart_handler);
- u32 val;
-
- /* use a timeout of 10 ticks (~150us) */
- writel_relaxed(10 | PM_PASSWORD, wdt->base + PM_WDOG);
- val = readl_relaxed(wdt->base + PM_RSTC);
- val &= PM_RSTC_WRCFG_CLR;
- val |= PM_PASSWORD | PM_RSTC_WRCFG_FULL_RESET;
- writel_relaxed(val, wdt->base + PM_RSTC);
-
- /* No sleeping, possibly atomic. */
- mdelay(1);
-
- return 0;
-}
-
/*
* We can't really power off, but if we do the normal reset scheme, and
* indicate to bootcode.bin not to reboot, then most of the chip will be
writel_relaxed(val, wdt->base + PM_RSTS);
/* Continue with normal reset mechanism */
- bcm2835_restart(&wdt->restart_handler, REBOOT_HARD, NULL);
+ __bcm2835_restart(wdt);
}
static int bcm2835_wdt_probe(struct platform_device *pdev)
*/
set_bit(WDOG_HW_RUNNING, &bcm2835_wdt_wdd.status);
}
+
+ watchdog_set_restart_priority(&bcm2835_wdt_wdd, 128);
+
err = watchdog_register_device(&bcm2835_wdt_wdd);
if (err) {
dev_err(dev, "Failed to register watchdog device");
return err;
}
- wdt->restart_handler.notifier_call = bcm2835_restart;
- wdt->restart_handler.priority = 128;
- register_restart_handler(&wdt->restart_handler);
if (pm_power_off == NULL)
pm_power_off = bcm2835_power_off;
{
struct bcm2835_wdt *wdt = platform_get_drvdata(pdev);
- unregister_restart_handler(&wdt->restart_handler);
if (pm_power_off == bcm2835_power_off)
pm_power_off = NULL;
watchdog_unregister_device(&bcm2835_wdt_wdd);