diff options
author | Ezequiel Garcia <ezequiel.garcia@free-electrons.com> | 2014-02-10 18:00:21 -0500 |
---|---|---|
committer | Jason Cooper <jason@lakedaemon.net> | 2014-02-21 22:42:42 -0500 |
commit | fc8cd2ac0ad8fca1ca4699da53e635b3e9cc35ed (patch) | |
tree | 8bcfbf309e1addc002e5c8d6435a7ae5b1e03c76 | |
parent | bb02c662d641d51ea8c3ae9c828e89fbcfe04ba7 (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.c | 42 |
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) */ | |||
46 | static struct clk *clk; | 45 | static struct clk *clk; |
47 | static unsigned int wdt_tclk; | 46 | static unsigned int wdt_tclk; |
48 | static void __iomem *wdt_reg; | 47 | static void __iomem *wdt_reg; |
49 | static DEFINE_SPINLOCK(wdt_lock); | ||
50 | 48 | ||
51 | static int orion_wdt_ping(struct watchdog_device *wdt_dev) | 49 | static 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 | ||
62 | static int orion_wdt_start(struct watchdog_device *wdt_dev) | 56 | static 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 | ||
88 | static int orion_wdt_stop(struct watchdog_device *wdt_dev) | 72 | static 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 | ||
108 | static unsigned int orion_wdt_get_timeleft(struct watchdog_device *wdt_dev) | 82 | static 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 | ||
119 | static int orion_wdt_set_timeout(struct watchdog_device *wdt_dev, | 87 | static int orion_wdt_set_timeout(struct watchdog_device *wdt_dev, |