diff options
Diffstat (limited to 'drivers/watchdog/renesas_wdt.c')
-rw-r--r-- | drivers/watchdog/renesas_wdt.c | 35 |
1 files changed, 25 insertions, 10 deletions
diff --git a/drivers/watchdog/renesas_wdt.c b/drivers/watchdog/renesas_wdt.c index 565dbc1ec638..00662a8e039c 100644 --- a/drivers/watchdog/renesas_wdt.c +++ b/drivers/watchdog/renesas_wdt.c @@ -7,6 +7,7 @@ */ #include <linux/bitops.h> #include <linux/clk.h> +#include <linux/delay.h> #include <linux/io.h> #include <linux/kernel.h> #include <linux/module.h> @@ -70,6 +71,15 @@ static int rwdt_init_timeout(struct watchdog_device *wdev) return 0; } +static void rwdt_wait_cycles(struct rwdt_priv *priv, unsigned int cycles) +{ + unsigned int delay; + + delay = DIV_ROUND_UP(cycles * 1000000, priv->clk_rate); + + usleep_range(delay, 2 * delay); +} + static int rwdt_start(struct watchdog_device *wdev) { struct rwdt_priv *priv = watchdog_get_drvdata(wdev); @@ -80,6 +90,8 @@ static int rwdt_start(struct watchdog_device *wdev) /* Stop the timer before we modify any register */ val = readb_relaxed(priv->base + RWTCSRA) & ~RWTCSRA_TME; rwdt_write(priv, val, RWTCSRA); + /* Delay 2 cycles before setting watchdog counter */ + rwdt_wait_cycles(priv, 2); rwdt_init_timeout(wdev); rwdt_write(priv, priv->cks, RWTCSRA); @@ -98,6 +110,8 @@ static int rwdt_stop(struct watchdog_device *wdev) struct rwdt_priv *priv = watchdog_get_drvdata(wdev); rwdt_write(priv, priv->cks, RWTCSRA); + /* Delay 3 cycles before disabling module clock */ + rwdt_wait_cycles(priv, 3); pm_runtime_put(wdev->parent); return 0; @@ -175,15 +189,16 @@ static inline bool rwdt_blacklisted(struct device *dev) { return false; } static int rwdt_probe(struct platform_device *pdev) { + struct device *dev = &pdev->dev; struct rwdt_priv *priv; struct clk *clk; unsigned long clks_per_sec; int ret, i; - if (rwdt_blacklisted(&pdev->dev)) + if (rwdt_blacklisted(dev)) return -ENODEV; - priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; @@ -191,16 +206,16 @@ static int rwdt_probe(struct platform_device *pdev) if (IS_ERR(priv->base)) return PTR_ERR(priv->base); - clk = devm_clk_get(&pdev->dev, NULL); + clk = devm_clk_get(dev, NULL); if (IS_ERR(clk)) return PTR_ERR(clk); - pm_runtime_enable(&pdev->dev); - pm_runtime_get_sync(&pdev->dev); + pm_runtime_enable(dev); + pm_runtime_get_sync(dev); priv->clk_rate = clk_get_rate(clk); priv->wdev.bootstatus = (readb_relaxed(priv->base + RWTCSRA) & RWTCSRA_WOVF) ? WDIOF_CARDRESET : 0; - pm_runtime_put(&pdev->dev); + pm_runtime_put(dev); if (!priv->clk_rate) { ret = -ENOENT; @@ -216,14 +231,14 @@ static int rwdt_probe(struct platform_device *pdev) } if (i < 0) { - dev_err(&pdev->dev, "Can't find suitable clock divider\n"); + dev_err(dev, "Can't find suitable clock divider\n"); ret = -ERANGE; goto out_pm_disable; } priv->wdev.info = &rwdt_ident; priv->wdev.ops = &rwdt_ops; - priv->wdev.parent = &pdev->dev; + priv->wdev.parent = dev; priv->wdev.min_timeout = 1; priv->wdev.max_timeout = DIV_BY_CLKS_PER_SEC(priv, 65536); priv->wdev.timeout = min(priv->wdev.max_timeout, RWDT_DEFAULT_TIMEOUT); @@ -235,7 +250,7 @@ static int rwdt_probe(struct platform_device *pdev) watchdog_stop_on_unregister(&priv->wdev); /* This overrides the default timeout only if DT configuration was found */ - watchdog_init_timeout(&priv->wdev, 0, &pdev->dev); + watchdog_init_timeout(&priv->wdev, 0, dev); ret = watchdog_register_device(&priv->wdev); if (ret < 0) @@ -244,7 +259,7 @@ static int rwdt_probe(struct platform_device *pdev) return 0; out_pm_disable: - pm_runtime_disable(&pdev->dev); + pm_runtime_disable(dev); return ret; } |