watchdog: s3c2410_wdt: fix resume sequence
authorChangki Kim <changki.kim@samsung.com>
Thu, 31 Dec 2015 05:45:40 +0000 (14:45 +0900)
committerJaehyoung Choi <jkkkkk.choi@samsung.com>
Wed, 9 May 2018 11:27:47 +0000 (20:27 +0900)
When AUTOMATIC_DISABLE_WDT regster in PMU is set 1 and
APL cores are power down, watchdog registers is set reset value.
So we change resume sequence.

Change-Id: I397e5627a4d0a869ffe756fb19d165886d13952a
Signed-off-by: Changki Kim <changki.kim@samsung.com>
drivers/watchdog/s3c2410_wdt.c

index ccdff8541c57c2fc32ed576edc08ccab391e1b32..cf507b4862042e55c01a4a9d9099cd1cac47e2d4 100644 (file)
@@ -221,7 +221,7 @@ static inline struct s3c2410_wdt *freq_to_wdt(struct notifier_block *nb)
        return container_of(nb, struct s3c2410_wdt, freq_transition);
 }
 
-static int s3c2410wdt_mask_and_disable_reset(struct s3c2410_wdt *wdt, bool mask)
+static int s3c2410wdt_mask_wdt_reset(struct s3c2410_wdt *wdt, bool mask)
 {
        int ret;
        u32 mask_val = 1 << wdt->drv_data->mask_bit;
@@ -235,15 +235,32 @@ static int s3c2410wdt_mask_and_disable_reset(struct s3c2410_wdt *wdt, bool mask)
                val = mask_val;
 
        ret = regmap_update_bits(wdt->pmureg,
-                       wdt->drv_data->disable_reg,
+                       wdt->drv_data->mask_reset_reg,
                        mask_val, val);
+
        if (ret < 0)
-               goto error;
+               dev_err(wdt->dev, "failed to update reg(%d)\n", ret);
+
+       return ret;
+}
+
+static int s3c2410wdt_automatic_disable_wdt(struct s3c2410_wdt *wdt, bool mask)
+{
+       int ret;
+       u32 mask_val = 1 << wdt->drv_data->mask_bit;
+       u32 val = 0;
+
+       /* No need to do anything if no PMU CONFIG needed */
+       if (!(wdt->drv_data->quirks & QUIRK_HAS_PMU_CONFIG))
+               return 0;
+
+       if (mask)
+               val = mask_val;
 
        ret = regmap_update_bits(wdt->pmureg,
-                       wdt->drv_data->mask_reset_reg,
+                       wdt->drv_data->disable_reg,
                        mask_val, val);
- error:
+
        if (ret < 0)
                dev_err(wdt->dev, "failed to update reg(%d)\n", ret);
 
@@ -647,13 +664,17 @@ static int s3c2410wdt_probe(struct platform_device *pdev)
                dev_err(dev, "cannot register watchdog (%d)\n", ret);
                goto err_cpufreq;
        }
+
+       ret = s3c2410wdt_automatic_disable_wdt(wdt, false);
+       if (ret < 0)
+               goto err_unregister;
        /* Prevent watchdog reset while setting */
        s3c2410wdt_stop_intclear(wdt);
-       /* Enable pmu watchdog reset control */
-       ret = s3c2410wdt_mask_and_disable_reset(wdt, false);
+       ret = s3c2410wdt_mask_wdt_reset(wdt, false);
        if (ret < 0)
                goto err_unregister;
 
+
        if (tmr_atboot && started == 0) {
                dev_info(dev, "starting watchdog timer\n");
                s3c2410wdt_start(&wdt->wdt_device);
@@ -696,7 +717,7 @@ static int s3c2410wdt_remove(struct platform_device *dev)
        int ret;
        struct s3c2410_wdt *wdt = platform_get_drvdata(dev);
 
-       ret = s3c2410wdt_mask_and_disable_reset(wdt, true);
+       ret = s3c2410wdt_mask_wdt_reset(wdt, true);
        if (ret < 0)
                return ret;
 
@@ -713,7 +734,7 @@ static void s3c2410wdt_shutdown(struct platform_device *dev)
 {
        struct s3c2410_wdt *wdt = platform_get_drvdata(dev);
 
-       s3c2410wdt_mask_and_disable_reset(wdt, true);
+       s3c2410wdt_mask_wdt_reset(wdt, true);
 
        s3c2410wdt_stop(&wdt->wdt_device);
 }
@@ -731,7 +752,7 @@ static int s3c2410wdt_suspend(struct device *dev)
        /* Note that WTCNT doesn't need to be saved. */
        s3c2410wdt_stop(&wdt->wdt_device);
 
-       ret = s3c2410wdt_mask_and_disable_reset(wdt, true);
+       ret = s3c2410wdt_mask_wdt_reset(wdt, true);
 
        return ret;
 }
@@ -739,21 +760,28 @@ static int s3c2410wdt_suspend(struct device *dev)
 static int s3c2410wdt_resume(struct device *dev)
 {
        int ret;
+       unsigned int val;
        struct s3c2410_wdt *wdt = dev_get_drvdata(dev);
 
+       ret = s3c2410wdt_automatic_disable_wdt(wdt, false);
+       if (ret < 0)
+               return ret;
+
+       s3c2410wdt_stop_intclear(wdt);
        /* Restore watchdog state. */
        writel(wdt->wtdat_save, wdt->reg_base + S3C2410_WTDAT);
        writel(wdt->wtdat_save, wdt->reg_base + S3C2410_WTCNT);/* Reset count */
        writel(wdt->wtcon_save, wdt->reg_base + S3C2410_WTCON);
 
-       s3c2410wdt_stop_intclear(wdt);
-       /* Enable pmu watchdog reset control */
-       ret = s3c2410wdt_mask_and_disable_reset(wdt, false);
+       ret = s3c2410wdt_mask_wdt_reset(wdt, false);
        if (ret < 0)
                return ret;
 
-       dev_info(dev, "watchdog %sabled\n",
-               (wdt->wtcon_save & S3C2410_WTCON_ENABLE) ? "en" : "dis");
+       val = readl(wdt->reg_base + S3C2410_WTCON);
+       dev_info(dev, "watchdog %sabled, con: 0x%08x, dat: 0x%08x, cnt: 0x%08x\n",
+               (val & S3C2410_WTCON_ENABLE) ? "en" : "dis", val,
+               readl(wdt->reg_base + S3C2410_WTDAT),
+               readl(wdt->reg_base + S3C2410_WTCNT));
 
        return 0;
 }