Commit 71e9b2f0 authored by Guenter Roeck's avatar Guenter Roeck
Browse files

watchdog: bcm2835_wdt: Use watchdog core to install restart handler



Use the infrastructure provided by the watchdog core to install
the restart handler.

Acked-by: default avatarEric Anholt <eric@anholt.net>
Signed-off-by: default avatarGuenter Roeck <linux@roeck-us.net>
parent 55dbe8f3
Loading
Loading
Loading
Loading
+30 −27
Original line number Diff line number Diff line
@@ -14,7 +14,6 @@
 */

#include <linux/delay.h>
#include <linux/reboot.h>
#include <linux/types.h>
#include <linux/module.h>
#include <linux/io.h>
@@ -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,7 +167,7 @@ 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)
@@ -201,6 +205,9 @@ 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");
@@ -208,9 +215,6 @@ static int bcm2835_wdt_probe(struct platform_device *pdev)
		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;

@@ -222,7 +226,6 @@ 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);