i40e: Implement ndo_features_check()
[deliverable/linux.git] / drivers / watchdog / omap_wdt.c
index 9494c4b254777342cbd6da39ece0c8ca76c9776a..de911c7e477c2875fe3633bce5a72a6b45fb95c0 100644 (file)
@@ -55,6 +55,11 @@ MODULE_PARM_DESC(timer_margin, "initial watchdog timeout (in seconds)");
 
 #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 */
@@ -135,6 +140,13 @@ static int omap_wdt_start(struct watchdog_device *wdog)
 
        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();
@@ -191,6 +203,16 @@ static int omap_wdt_set_timeout(struct watchdog_device *wdog,
        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",
@@ -202,6 +224,7 @@ static const struct watchdog_ops omap_wdt_ops = {
        .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)
@@ -209,7 +232,6 @@ 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);
@@ -242,12 +264,11 @@ static int omap_wdt_probe(struct platform_device *pdev)
        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);
 
@@ -263,6 +284,9 @@ static int omap_wdt_probe(struct platform_device *pdev)
 
        pm_runtime_put_sync(wdev->dev);
 
+       if (early_enable)
+               omap_wdt_start(&wdev->wdog);
+
        return 0;
 }
 
This page took 0.027157 seconds and 5 git commands to generate.