From 872a4090370d196d4a06f8debebeacd282095f32 Mon Sep 17 00:00:00 2001 From: Yingyuan Zhu Date: Wed, 10 Apr 2019 15:26:32 +0800 Subject: [PATCH] watchdog: fix watchdog get lefttime error [1/1] PD#SWPL-6937 Problem: 1.get lefttime error by 'cat sys/class/watchdog/watchdog0/timeleft' cmd. 2.if DTS is configured to feed watchdog by Android, the system will restart automatically after wake up. Solution: 1.modify the code to get time. 2.when the system wakes up, first judge whether the watchdog runs, and then decide whether to start the watchdog. Verify: test pass on u200 Change-Id: If64888ffdd5651e8cfcace5ea0d0da31641bb397 Signed-off-by: Yingyuan Zhu --- drivers/amlogic/watchdog/meson_wdt.c | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/drivers/amlogic/watchdog/meson_wdt.c b/drivers/amlogic/watchdog/meson_wdt.c index 4da2517..bb48362 100644 --- a/drivers/amlogic/watchdog/meson_wdt.c +++ b/drivers/amlogic/watchdog/meson_wdt.c @@ -54,6 +54,7 @@ struct aml_wdt_dev { void __iomem *reg_base; struct notifier_block pm_notifier; struct notifier_block reboot_notifier; + bool is_running; /* 1:enable 0:disable */ }; static void aml_update_bits(void __iomem *reg, unsigned int mask, @@ -108,7 +109,9 @@ static int aml_wdt_start(struct watchdog_device *wdog) if (wdev->boot_queue) cancel_delayed_work(&wdev->boot_queue); #endif + wdev->is_running = true; dev_info(wdev->dev, "start watchdog\n"); + return 0; } @@ -119,6 +122,7 @@ static int aml_wdt_stop(struct watchdog_device *wdog) mutex_lock(&wdev->lock); disable_watchdog(wdev); mutex_unlock(&wdev->lock); + wdev->is_running = false; dev_info(wdev->dev, "stop watchdog\n"); return 0; @@ -153,12 +157,14 @@ static int aml_wdt_set_timeout(struct watchdog_device *wdog, unsigned int aml_wdt_get_timeleft(struct watchdog_device *wdog) { struct aml_wdt_dev *wdev = watchdog_get_drvdata(wdog); - unsigned int timeleft; + unsigned long timeleft, tick; mutex_lock(&wdev->lock); timeleft = read_watchdog_tcnt(wdev); + tick = readl(wdev->reg_base + TCNT) & 0xffff; mutex_unlock(&wdev->lock); - return timeleft/wdev->one_second; + + return (tick - timeleft)/wdev->one_second; } static void boot_moniter_work(struct work_struct *work) @@ -255,14 +261,18 @@ static int aml_wtd_pm_notify(struct notifier_block *nb, unsigned long event, wdev = container_of(nb, struct aml_wdt_dev, pm_notifier); if (event == PM_SUSPEND_PREPARE) { - disable_watchdog(wdev); - dev_info(wdev->dev, - "pm_notify: disable watchdog, event = %lu\n", event); + if (wdev->is_running) { + disable_watchdog(wdev); + dev_info(wdev->dev, + "pm_notify: disable watchdog, event = %lu\n", event); + } } if (event == PM_POST_SUSPEND) { - enable_watchdog(wdev); - dev_info(wdev->dev, - "pm_notify: enable watchdog, event = %lu\n", event); + if (wdev->is_running) { + enable_watchdog(wdev); + dev_info(wdev->dev, + "pm_notify: enable watchdog, event = %lu\n", event); + } } return NOTIFY_OK; } @@ -338,14 +348,13 @@ static int aml_wdt_probe(struct platform_device *pdev) watchdog_set_drvdata(aml_wdt, wdev); platform_set_drvdata(pdev, aml_wdt); + wdev->is_running = false; if (wdev->reset_watchdog_method == 1) { INIT_DELAYED_WORK(&wdev->boot_queue, boot_moniter_work); mod_delayed_work(system_freezable_wq, &wdev->boot_queue, round_jiffies(msecs_to_jiffies(wdev->reset_watchdog_time*1000))); - enable_watchdog(wdev); - set_watchdog_cnt(wdev, - wdev->default_timeout * wdev->one_second); + aml_wdt_start(aml_wdt); dev_info(wdev->dev, "creat work queue for watch dog\n"); } ret = watchdog_register_device(aml_wdt); -- 2.7.4