aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEzequiel Garcia <ezequiel.garcia@free-electrons.com>2014-02-10 18:00:21 -0500
committerJason Cooper <jason@lakedaemon.net>2014-02-21 22:42:42 -0500
commitfc8cd2ac0ad8fca1ca4699da53e635b3e9cc35ed (patch)
tree8bcfbf309e1addc002e5c8d6435a7ae5b1e03c76
parentbb02c662d641d51ea8c3ae9c828e89fbcfe04ba7 (diff)
watchdog: orion: Use atomic access for shared registers
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>
-rw-r--r--drivers/watchdog/orion_wdt.c42
1 files changed, 5 insertions, 37 deletions
diff --git a/drivers/watchdog/orion_wdt.c b/drivers/watchdog/orion_wdt.c
index 7f19fa3b543d..b92a9919e068 100644
--- a/drivers/watchdog/orion_wdt.c
+++ b/drivers/watchdog/orion_wdt.c
@@ -20,7 +20,6 @@
20#include <linux/watchdog.h> 20#include <linux/watchdog.h>
21#include <linux/init.h> 21#include <linux/init.h>
22#include <linux/io.h> 22#include <linux/io.h>
23#include <linux/spinlock.h>
24#include <linux/clk.h> 23#include <linux/clk.h>
25#include <linux/err.h> 24#include <linux/err.h>
26#include <linux/of.h> 25#include <linux/of.h>
@@ -46,25 +45,16 @@ static unsigned int wdt_max_duration; /* (seconds) */
46static struct clk *clk; 45static struct clk *clk;
47static unsigned int wdt_tclk; 46static unsigned int wdt_tclk;
48static void __iomem *wdt_reg; 47static void __iomem *wdt_reg;
49static DEFINE_SPINLOCK(wdt_lock);
50 48
51static int orion_wdt_ping(struct watchdog_device *wdt_dev) 49static int orion_wdt_ping(struct watchdog_device *wdt_dev)
52{ 50{
53 spin_lock(&wdt_lock);
54
55 /* Reload watchdog duration */ 51 /* Reload watchdog duration */
56 writel(wdt_tclk * wdt_dev->timeout, wdt_reg + WDT_VAL); 52 writel(wdt_tclk * wdt_dev->timeout, wdt_reg + WDT_VAL);
57
58 spin_unlock(&wdt_lock);
59 return 0; 53 return 0;
60} 54}
61 55
62static int orion_wdt_start(struct watchdog_device *wdt_dev) 56static int orion_wdt_start(struct watchdog_device *wdt_dev)
63{ 57{
64 u32 reg;
65
66 spin_lock(&wdt_lock);
67
68 /* Set watchdog duration */ 58 /* Set watchdog duration */
69 writel(wdt_tclk * wdt_dev->timeout, wdt_reg + WDT_VAL); 59 writel(wdt_tclk * wdt_dev->timeout, wdt_reg + WDT_VAL);
70 60
@@ -72,48 +62,26 @@ static int orion_wdt_start(struct watchdog_device *wdt_dev)
72 writel(~WDT_INT_REQ, BRIDGE_CAUSE); 62 writel(~WDT_INT_REQ, BRIDGE_CAUSE);
73 63
74 /* Enable watchdog timer */ 64 /* Enable watchdog timer */
75 reg = readl(wdt_reg + TIMER_CTRL); 65 atomic_io_modify(wdt_reg + TIMER_CTRL, WDT_EN, WDT_EN);
76 reg |= WDT_EN;
77 writel(reg, wdt_reg + TIMER_CTRL);
78 66
79 /* Enable reset on watchdog */ 67 /* Enable reset on watchdog */
80 reg = readl(RSTOUTn_MASK); 68 atomic_io_modify(RSTOUTn_MASK, WDT_RESET_OUT_EN, WDT_RESET_OUT_EN);
81 reg |= WDT_RESET_OUT_EN;
82 writel(reg, RSTOUTn_MASK);
83
84 spin_unlock(&wdt_lock);
85 return 0; 69 return 0;
86} 70}
87 71
88static int orion_wdt_stop(struct watchdog_device *wdt_dev) 72static int orion_wdt_stop(struct watchdog_device *wdt_dev)
89{ 73{
90 u32 reg;
91
92 spin_lock(&wdt_lock);
93
94 /* Disable reset on watchdog */ 74 /* Disable reset on watchdog */
95 reg = readl(RSTOUTn_MASK); 75 atomic_io_modify(RSTOUTn_MASK, WDT_RESET_OUT_EN, 0);
96 reg &= ~WDT_RESET_OUT_EN;
97 writel(reg, RSTOUTn_MASK);
98 76
99 /* Disable watchdog timer */ 77 /* Disable watchdog timer */
100 reg = readl(wdt_reg + TIMER_CTRL); 78 atomic_io_modify(wdt_reg + TIMER_CTRL, WDT_EN, 0);
101 reg &= ~WDT_EN;
102 writel(reg, wdt_reg + TIMER_CTRL);
103
104 spin_unlock(&wdt_lock);
105 return 0; 79 return 0;
106} 80}
107 81
108static unsigned int orion_wdt_get_timeleft(struct watchdog_device *wdt_dev) 82static unsigned int orion_wdt_get_timeleft(struct watchdog_device *wdt_dev)
109{ 83{
110 unsigned int time_left; 84 return readl(wdt_reg + WDT_VAL) / wdt_tclk;
111
112 spin_lock(&wdt_lock);
113 time_left = readl(wdt_reg + WDT_VAL) / wdt_tclk;
114 spin_unlock(&wdt_lock);
115
116 return time_left;
117} 85}
118 86
119static int orion_wdt_set_timeout(struct watchdog_device *wdt_dev, 87static int orion_wdt_set_timeout(struct watchdog_device *wdt_dev,