Source
x
/*
* Watchdog driver for CSR Atlas7
*
* Copyright (c) 2015 Cambridge Silicon Radio Limited, a CSR plc group company.
*
* Licensed under GPLv2.
*/
static unsigned int timeout = ATLAS7_WDT_DEFAULT_TIMEOUT;
static bool nowayout = WATCHDOG_NOWAYOUT;
module_param(timeout, uint, 0);
module_param(nowayout, bool, 0);
MODULE_PARM_DESC(timeout, "Default watchdog timeout (in seconds)");
MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
__MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
struct atlas7_wdog {
struct device *dev;
void __iomem *base;
unsigned long tick_rate;
struct clk *clk;
};
static unsigned int atlas7_wdt_gettimeleft(struct watchdog_device *wdd)
{
struct atlas7_wdog *wdt = watchdog_get_drvdata(wdd);
u32 counter, match, delta;
counter = readl(wdt->base + ATLAS7_WDT_CNT);
match = readl(wdt->base + ATLAS7_WDT_CNT_MATCH);
delta = match - counter;
return delta / wdt->tick_rate;
}
static int atlas7_wdt_ping(struct watchdog_device *wdd)
{
struct atlas7_wdog *wdt = watchdog_get_drvdata(wdd);
u32 counter, match, delta;
counter = readl(wdt->base + ATLAS7_WDT_CNT);
delta = wdd->timeout * wdt->tick_rate;
match = counter + delta;
writel(match, wdt->base + ATLAS7_WDT_CNT_MATCH);
return 0;
}
static int atlas7_wdt_enable(struct watchdog_device *wdd)
{
struct atlas7_wdog *wdt = watchdog_get_drvdata(wdd);
atlas7_wdt_ping(wdd);
writel(readl(wdt->base + ATLAS7_WDT_CNT_CTRL) | ATLAS7_WDT_CNT_EN,
wdt->base + ATLAS7_WDT_CNT_CTRL);
writel(1, wdt->base + ATLAS7_WDT_EN);
return 0;
}
static int atlas7_wdt_disable(struct watchdog_device *wdd)
{
struct atlas7_wdog *wdt = watchdog_get_drvdata(wdd);
writel(0, wdt->base + ATLAS7_WDT_EN);
writel(readl(wdt->base + ATLAS7_WDT_CNT_CTRL) & ~ATLAS7_WDT_CNT_EN,
wdt->base + ATLAS7_WDT_CNT_CTRL);
return 0;
}