watchdog: orion: Use atomic access for shared registers
authorEzequiel Garcia <ezequiel.garcia@free-electrons.com>
Mon, 10 Feb 2014 23:00:21 +0000 (20:00 -0300)
committerJason Cooper <jason@lakedaemon.net>
Sat, 22 Feb 2014 03:42:42 +0000 (03:42 +0000)
Since the timer control register is shared with the clocksource driver,
use the recently introduced atomic_io_clear_set() to access such register.
Given the watchdog core already provides serialization for all the
watchdog ops, this commit allows to remove the spinlock entirely.

Reviewed-by: Guenter Roeck <linux@roeck-us.net>
Tested-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
Tested-by: Willy Tarreau <w@1wt.eu>
Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
Acked-by: Wim Van Sebroeck <wim@iguana.be>
Tested-By: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
Signed-off-by: Jason Cooper <jason@lakedaemon.net>
drivers/watchdog/orion_wdt.c

index 7f19fa3b543d4025752459be8352cf38c399daaa..b92a9919e068c05d1d386e82a4796a742033fbdd 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/watchdog.h>
 #include <linux/init.h>
 #include <linux/io.h>
-#include <linux/spinlock.h>
 #include <linux/clk.h>
 #include <linux/err.h>
 #include <linux/of.h>
@@ -46,25 +45,16 @@ static unsigned int wdt_max_duration;       /* (seconds) */
 static struct clk *clk;
 static unsigned int wdt_tclk;
 static void __iomem *wdt_reg;
-static DEFINE_SPINLOCK(wdt_lock);
 
 static int orion_wdt_ping(struct watchdog_device *wdt_dev)
 {
-       spin_lock(&wdt_lock);
-
        /* Reload watchdog duration */
        writel(wdt_tclk * wdt_dev->timeout, wdt_reg + WDT_VAL);
-
-       spin_unlock(&wdt_lock);
        return 0;
 }
 
 static int orion_wdt_start(struct watchdog_device *wdt_dev)
 {
-       u32 reg;
-
-       spin_lock(&wdt_lock);
-
        /* Set watchdog duration */
        writel(wdt_tclk * wdt_dev->timeout, wdt_reg + WDT_VAL);
 
@@ -72,48 +62,26 @@ static int orion_wdt_start(struct watchdog_device *wdt_dev)
        writel(~WDT_INT_REQ, BRIDGE_CAUSE);
 
        /* Enable watchdog timer */
-       reg = readl(wdt_reg + TIMER_CTRL);
-       reg |= WDT_EN;
-       writel(reg, wdt_reg + TIMER_CTRL);
+       atomic_io_modify(wdt_reg + TIMER_CTRL, WDT_EN, WDT_EN);
 
        /* Enable reset on watchdog */
-       reg = readl(RSTOUTn_MASK);
-       reg |= WDT_RESET_OUT_EN;
-       writel(reg, RSTOUTn_MASK);
-
-       spin_unlock(&wdt_lock);
+       atomic_io_modify(RSTOUTn_MASK, WDT_RESET_OUT_EN, WDT_RESET_OUT_EN);
        return 0;
 }
 
 static int orion_wdt_stop(struct watchdog_device *wdt_dev)
 {
-       u32 reg;
-
-       spin_lock(&wdt_lock);
-
        /* Disable reset on watchdog */
-       reg = readl(RSTOUTn_MASK);
-       reg &= ~WDT_RESET_OUT_EN;
-       writel(reg, RSTOUTn_MASK);
+       atomic_io_modify(RSTOUTn_MASK, WDT_RESET_OUT_EN, 0);
 
        /* Disable watchdog timer */
-       reg = readl(wdt_reg + TIMER_CTRL);
-       reg &= ~WDT_EN;
-       writel(reg, wdt_reg + TIMER_CTRL);
-
-       spin_unlock(&wdt_lock);
+       atomic_io_modify(wdt_reg + TIMER_CTRL, WDT_EN, 0);
        return 0;
 }
 
 static unsigned int orion_wdt_get_timeleft(struct watchdog_device *wdt_dev)
 {
-       unsigned int time_left;
-
-       spin_lock(&wdt_lock);
-       time_left = readl(wdt_reg + WDT_VAL) / wdt_tclk;
-       spin_unlock(&wdt_lock);
-
-       return time_left;
+       return readl(wdt_reg + WDT_VAL) / wdt_tclk;
 }
 
 static int orion_wdt_set_timeout(struct watchdog_device *wdt_dev,