From: Changki Kim Date: Thu, 31 Dec 2015 05:45:40 +0000 (+0900) Subject: watchdog: s3c2410_wdt: fix resume sequence X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=f5d1c0e70d670448b91dd9102ed0a38475ad7558;p=GitHub%2Fmoto-9609%2Fandroid_kernel_motorola_exynos9610.git watchdog: s3c2410_wdt: fix resume sequence 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 --- diff --git a/drivers/watchdog/s3c2410_wdt.c b/drivers/watchdog/s3c2410_wdt.c index ccdff8541c57..cf507b486204 100644 --- a/drivers/watchdog/s3c2410_wdt.c +++ b/drivers/watchdog/s3c2410_wdt.c @@ -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; }