summaryrefslogtreecommitdiff
path: root/drivers/watchdog/bcm2835_wdt.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/watchdog/bcm2835_wdt.c')
-rw-r--r--drivers/watchdog/bcm2835_wdt.c90
1 files changed, 41 insertions, 49 deletions
diff --git a/drivers/watchdog/bcm2835_wdt.c b/drivers/watchdog/bcm2835_wdt.c
index c32c45bd8b09..b339e0e67b4c 100644
--- a/drivers/watchdog/bcm2835_wdt.c
+++ b/drivers/watchdog/bcm2835_wdt.c
@@ -14,7 +14,6 @@
*/
#include <linux/delay.h>
-#include <linux/reboot.h>
#include <linux/types.h>
#include <linux/module.h>
#include <linux/io.h>
@@ -37,9 +36,9 @@
#define PM_RSTC_RESET 0x00000102
/*
- * The Raspberry Pi firmware uses the RSTS register to know which partiton
- * to boot from. The partiton value is spread into bits 0, 2, 4, 6, 8, 10.
- * Partiton 63 is a special partition used by the firmware to indicate halt.
+ * The Raspberry Pi firmware uses the RSTS register to know which partition
+ * to boot from. The partition value is spread into bits 0, 2, 4, 6, 8, 10.
+ * Partition 63 is a special partition used by the firmware to indicate halt.
*/
#define PM_RSTS_RASPBERRYPI_HALT 0x555
@@ -49,7 +48,6 @@
struct bcm2835_wdt {
void __iomem *base;
spinlock_t lock;
- struct notifier_block restart_handler;
};
static unsigned int heartbeat;
@@ -99,11 +97,37 @@ static unsigned int bcm2835_wdt_get_timeleft(struct watchdog_device *wdog)
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 = {
@@ -120,26 +144,6 @@ static struct watchdog_device bcm2835_wdt_wdd = {
.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
@@ -163,13 +167,13 @@ static void bcm2835_power_off(void)
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)
{
+ struct resource *res;
struct device *dev = &pdev->dev;
- struct device_node *np = dev->of_node;
struct bcm2835_wdt *wdt;
int err;
@@ -180,16 +184,15 @@ static int bcm2835_wdt_probe(struct platform_device *pdev)
spin_lock_init(&wdt->lock);
- wdt->base = of_iomap(np, 0);
- if (!wdt->base) {
- dev_err(dev, "Failed to remap watchdog regs");
- return -ENODEV;
- }
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ wdt->base = devm_ioremap_resource(dev, res);
+ if (IS_ERR(wdt->base))
+ return PTR_ERR(wdt->base);
watchdog_set_drvdata(&bcm2835_wdt_wdd, wdt);
watchdog_init_timeout(&bcm2835_wdt_wdd, heartbeat, dev);
watchdog_set_nowayout(&bcm2835_wdt_wdd, nowayout);
- bcm2835_wdt_wdd.parent = &pdev->dev;
+ bcm2835_wdt_wdd.parent = dev;
if (bcm2835_wdt_is_running(wdt)) {
/*
* The currently active timeout value (set by the
@@ -201,16 +204,16 @@ static int bcm2835_wdt_probe(struct platform_device *pdev)
*/
set_bit(WDOG_HW_RUNNING, &bcm2835_wdt_wdd.status);
}
- err = watchdog_register_device(&bcm2835_wdt_wdd);
+
+ watchdog_set_restart_priority(&bcm2835_wdt_wdd, 128);
+
+ watchdog_stop_on_reboot(&bcm2835_wdt_wdd);
+ err = devm_watchdog_register_device(dev, &bcm2835_wdt_wdd);
if (err) {
dev_err(dev, "Failed to register watchdog device");
- iounmap(wdt->base);
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;
@@ -220,22 +223,12 @@ static int bcm2835_wdt_probe(struct platform_device *pdev)
static int bcm2835_wdt_remove(struct platform_device *pdev)
{
- 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);
- iounmap(wdt->base);
return 0;
}
-static void bcm2835_wdt_shutdown(struct platform_device *pdev)
-{
- bcm2835_wdt_stop(&bcm2835_wdt_wdd);
-}
-
static const struct of_device_id bcm2835_wdt_of_match[] = {
{ .compatible = "brcm,bcm2835-pm-wdt", },
{},
@@ -245,7 +238,6 @@ MODULE_DEVICE_TABLE(of, bcm2835_wdt_of_match);
static struct platform_driver bcm2835_wdt_driver = {
.probe = bcm2835_wdt_probe,
.remove = bcm2835_wdt_remove,
- .shutdown = bcm2835_wdt_shutdown,
.driver = {
.name = "bcm2835-wdt",
.of_match_table = bcm2835_wdt_of_match,