]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - drivers/watchdog/renesas_wdt.c
dpaa2-eth: Fix TX FQID values
[linux.git] / drivers / watchdog / renesas_wdt.c
index 565dbc1ec6388fc9cf00ff158c7f72af78779af3..00662a8e039ccd2ac67ab8bd5751ff5863756039 100644 (file)
@@ -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;
 }