#define to_omap_wdt_dev(_wdog) container_of(_wdog, struct omap_wdt_dev, wdog)
+static bool early_enable;
+module_param(early_enable, bool, 0);
+MODULE_PARM_DESC(early_enable,
+ "Watchdog is started on module insertion (default=0)");
+
struct omap_wdt_dev {
struct watchdog_device wdog;
void __iomem *base; /* physical */
pm_runtime_get_sync(wdev->dev);
+ /*
+ * Make sure the watchdog is disabled. This is unfortunately required
+ * because writing to various registers with the watchdog running has no
+ * effect.
+ */
+ omap_wdt_disable(wdev);
+
/* initialize prescaler */
while (readl_relaxed(base + OMAP_WATCHDOG_WPS) & 0x01)
cpu_relax();
return 0;
}
+static unsigned int omap_wdt_get_timeleft(struct watchdog_device *wdog)
+{
+ struct omap_wdt_dev *wdev = watchdog_get_drvdata(wdog);
+ void __iomem *base = wdev->base;
+ u32 value;
+
+ value = readl_relaxed(base + OMAP_WATCHDOG_CRR);
+ return GET_WCCR_SECS(value);
+}
+
static const struct watchdog_info omap_wdt_info = {
.options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING,
.identity = "OMAP Watchdog",
.stop = omap_wdt_stop,
.ping = omap_wdt_ping,
.set_timeout = omap_wdt_set_timeout,
+ .get_timeleft = omap_wdt_get_timeleft,
};
static int omap_wdt_probe(struct platform_device *pdev)
struct omap_wd_timer_platform_data *pdata = dev_get_platdata(&pdev->dev);
struct resource *res;
struct omap_wdt_dev *wdev;
- u32 rs;
int ret;
wdev = devm_kzalloc(&pdev->dev, sizeof(*wdev), GFP_KERNEL);
pm_runtime_enable(wdev->dev);
pm_runtime_get_sync(wdev->dev);
- if (pdata && pdata->read_reset_sources)
- rs = pdata->read_reset_sources();
- else
- rs = 0;
- wdev->wdog.bootstatus = (rs & (1 << OMAP_MPU_WD_RST_SRC_ID_SHIFT)) ?
- WDIOF_CARDRESET : 0;
+ if (pdata && pdata->read_reset_sources) {
+ u32 rs = pdata->read_reset_sources();
+ if (rs & (1 << OMAP_MPU_WD_RST_SRC_ID_SHIFT))
+ wdev->wdog.bootstatus = WDIOF_CARDRESET;
+ }
omap_wdt_disable(wdev);
pm_runtime_put_sync(wdev->dev);
+ if (early_enable)
+ omap_wdt_start(&wdev->wdog);
+
return 0;
}