diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/watchdog/orion5x_wdt.c | 26 |
1 files changed, 20 insertions, 6 deletions
diff --git a/drivers/watchdog/orion5x_wdt.c b/drivers/watchdog/orion5x_wdt.c index 144776314989..14a339f58b6a 100644 --- a/drivers/watchdog/orion5x_wdt.c +++ b/drivers/watchdog/orion5x_wdt.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/init.h> | 20 | #include <linux/init.h> |
21 | #include <linux/uaccess.h> | 21 | #include <linux/uaccess.h> |
22 | #include <linux/io.h> | 22 | #include <linux/io.h> |
23 | #include <linux/spinlock.h> | ||
23 | 24 | ||
24 | /* | 25 | /* |
25 | * Watchdog timer block registers. | 26 | * Watchdog timer block registers. |
@@ -35,11 +36,14 @@ | |||
35 | static int nowayout = WATCHDOG_NOWAYOUT; | 36 | static int nowayout = WATCHDOG_NOWAYOUT; |
36 | static int heartbeat = WDT_MAX_DURATION; /* (seconds) */ | 37 | static int heartbeat = WDT_MAX_DURATION; /* (seconds) */ |
37 | static unsigned long wdt_status; | 38 | static unsigned long wdt_status; |
39 | static spinlock_t wdt_lock; | ||
38 | 40 | ||
39 | static void wdt_enable(void) | 41 | static void wdt_enable(void) |
40 | { | 42 | { |
41 | u32 reg; | 43 | u32 reg; |
42 | 44 | ||
45 | spin_lock(&wdt_lock); | ||
46 | |||
43 | /* Set watchdog duration */ | 47 | /* Set watchdog duration */ |
44 | writel(ORION5X_TCLK * heartbeat, WDT_VAL); | 48 | writel(ORION5X_TCLK * heartbeat, WDT_VAL); |
45 | 49 | ||
@@ -57,12 +61,16 @@ static void wdt_enable(void) | |||
57 | reg = readl(CPU_RESET_MASK); | 61 | reg = readl(CPU_RESET_MASK); |
58 | reg |= WDT_RESET; | 62 | reg |= WDT_RESET; |
59 | writel(reg, CPU_RESET_MASK); | 63 | writel(reg, CPU_RESET_MASK); |
64 | |||
65 | spin_unlock(&wdt_lock); | ||
60 | } | 66 | } |
61 | 67 | ||
62 | static void wdt_disable(void) | 68 | static void wdt_disable(void) |
63 | { | 69 | { |
64 | u32 reg; | 70 | u32 reg; |
65 | 71 | ||
72 | spin_lock(&wdt_lock); | ||
73 | |||
66 | /* Disable reset on watchdog */ | 74 | /* Disable reset on watchdog */ |
67 | reg = readl(CPU_RESET_MASK); | 75 | reg = readl(CPU_RESET_MASK); |
68 | reg &= ~WDT_RESET; | 76 | reg &= ~WDT_RESET; |
@@ -72,6 +80,16 @@ static void wdt_disable(void) | |||
72 | reg = readl(TIMER_CTRL); | 80 | reg = readl(TIMER_CTRL); |
73 | reg &= ~WDT_EN; | 81 | reg &= ~WDT_EN; |
74 | writel(reg, TIMER_CTRL); | 82 | writel(reg, TIMER_CTRL); |
83 | |||
84 | spin_unlock(&wdt_lock); | ||
85 | } | ||
86 | |||
87 | static int orion5x_wdt_get_timeleft(int *time_left) | ||
88 | { | ||
89 | spin_lock(&wdt_lock); | ||
90 | *time_left = readl(WDT_VAL) / ORION5X_TCLK; | ||
91 | spin_unlock(&wdt_lock); | ||
92 | return 0; | ||
75 | } | 93 | } |
76 | 94 | ||
77 | static int orion5x_wdt_open(struct inode *inode, struct file *file) | 95 | static int orion5x_wdt_open(struct inode *inode, struct file *file) |
@@ -83,12 +101,6 @@ static int orion5x_wdt_open(struct inode *inode, struct file *file) | |||
83 | return nonseekable_open(inode, file); | 101 | return nonseekable_open(inode, file); |
84 | } | 102 | } |
85 | 103 | ||
86 | static int orion5x_wdt_get_timeleft(int *time_left) | ||
87 | { | ||
88 | *time_left = readl(WDT_VAL) / ORION5X_TCLK; | ||
89 | return 0; | ||
90 | } | ||
91 | |||
92 | static ssize_t orion5x_wdt_write(struct file *file, const char *data, | 104 | static ssize_t orion5x_wdt_write(struct file *file, const char *data, |
93 | size_t len, loff_t *ppos) | 105 | size_t len, loff_t *ppos) |
94 | { | 106 | { |
@@ -201,6 +213,8 @@ static int __init orion5x_wdt_init(void) | |||
201 | { | 213 | { |
202 | int ret; | 214 | int ret; |
203 | 215 | ||
216 | spin_lock_init(&wdt_lock); | ||
217 | |||
204 | ret = misc_register(&orion5x_wdt_miscdev); | 218 | ret = misc_register(&orion5x_wdt_miscdev); |
205 | if (ret == 0) | 219 | if (ret == 0) |
206 | printk("Orion5x Watchdog Timer: heartbeat %d sec\n", | 220 | printk("Orion5x Watchdog Timer: heartbeat %d sec\n", |