diff options
-rw-r--r-- | drivers/char/watchdog/at32ap700x_wdt.c | 9 |
1 files changed, 9 insertions, 0 deletions
diff --git a/drivers/char/watchdog/at32ap700x_wdt.c b/drivers/char/watchdog/at32ap700x_wdt.c index fcd55c600b87..75e852e954e7 100644 --- a/drivers/char/watchdog/at32ap700x_wdt.c +++ b/drivers/char/watchdog/at32ap700x_wdt.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/watchdog.h> | 18 | #include <linux/watchdog.h> |
19 | #include <linux/uaccess.h> | 19 | #include <linux/uaccess.h> |
20 | #include <linux/io.h> | 20 | #include <linux/io.h> |
21 | #include <linux/spinlock.h> | ||
21 | 22 | ||
22 | #define TIMEOUT_MIN 1 | 23 | #define TIMEOUT_MIN 1 |
23 | #define TIMEOUT_MAX 2 | 24 | #define TIMEOUT_MAX 2 |
@@ -53,6 +54,7 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" | |||
53 | 54 | ||
54 | struct wdt_at32ap700x { | 55 | struct wdt_at32ap700x { |
55 | void __iomem *regs; | 56 | void __iomem *regs; |
57 | spinlock_t io_lock; | ||
56 | int timeout; | 58 | int timeout; |
57 | int users; | 59 | int users; |
58 | struct miscdevice miscdev; | 60 | struct miscdevice miscdev; |
@@ -66,9 +68,11 @@ static char expect_release; | |||
66 | */ | 68 | */ |
67 | static inline void at32_wdt_stop(void) | 69 | static inline void at32_wdt_stop(void) |
68 | { | 70 | { |
71 | spin_lock(&wdt->io_lock); | ||
69 | unsigned long psel = wdt_readl(wdt, CTRL) & WDT_BF(CTRL_PSEL, 0x0f); | 72 | unsigned long psel = wdt_readl(wdt, CTRL) & WDT_BF(CTRL_PSEL, 0x0f); |
70 | wdt_writel(wdt, CTRL, psel | WDT_BF(CTRL_KEY, 0x55)); | 73 | wdt_writel(wdt, CTRL, psel | WDT_BF(CTRL_KEY, 0x55)); |
71 | wdt_writel(wdt, CTRL, psel | WDT_BF(CTRL_KEY, 0xaa)); | 74 | wdt_writel(wdt, CTRL, psel | WDT_BF(CTRL_KEY, 0xaa)); |
75 | spin_unlock(&wdt->io_lock); | ||
72 | } | 76 | } |
73 | 77 | ||
74 | /* | 78 | /* |
@@ -79,12 +83,14 @@ static inline void at32_wdt_start(void) | |||
79 | /* 0xf is 2^16 divider = 2 sec, 0xe is 2^15 divider = 1 sec */ | 83 | /* 0xf is 2^16 divider = 2 sec, 0xe is 2^15 divider = 1 sec */ |
80 | unsigned long psel = (wdt->timeout > 1) ? 0xf : 0xe; | 84 | unsigned long psel = (wdt->timeout > 1) ? 0xf : 0xe; |
81 | 85 | ||
86 | spin_lock(&wdt->io_lock); | ||
82 | wdt_writel(wdt, CTRL, WDT_BIT(CTRL_EN) | 87 | wdt_writel(wdt, CTRL, WDT_BIT(CTRL_EN) |
83 | | WDT_BF(CTRL_PSEL, psel) | 88 | | WDT_BF(CTRL_PSEL, psel) |
84 | | WDT_BF(CTRL_KEY, 0x55)); | 89 | | WDT_BF(CTRL_KEY, 0x55)); |
85 | wdt_writel(wdt, CTRL, WDT_BIT(CTRL_EN) | 90 | wdt_writel(wdt, CTRL, WDT_BIT(CTRL_EN) |
86 | | WDT_BF(CTRL_PSEL, psel) | 91 | | WDT_BF(CTRL_PSEL, psel) |
87 | | WDT_BF(CTRL_KEY, 0xaa)); | 92 | | WDT_BF(CTRL_KEY, 0xaa)); |
93 | spin_unlock(&wdt->io_lock); | ||
88 | } | 94 | } |
89 | 95 | ||
90 | /* | 96 | /* |
@@ -92,7 +98,9 @@ static inline void at32_wdt_start(void) | |||
92 | */ | 98 | */ |
93 | static inline void at32_wdt_pat(void) | 99 | static inline void at32_wdt_pat(void) |
94 | { | 100 | { |
101 | spin_lock(&wdt->io_lock); | ||
95 | wdt_writel(wdt, CLR, 0x42); | 102 | wdt_writel(wdt, CLR, 0x42); |
103 | spin_unlock(&wdt->io_lock); | ||
96 | } | 104 | } |
97 | 105 | ||
98 | /* | 106 | /* |
@@ -272,6 +280,7 @@ static int __init at32_wdt_probe(struct platform_device *pdev) | |||
272 | dev_dbg(&pdev->dev, "could not map I/O memory\n"); | 280 | dev_dbg(&pdev->dev, "could not map I/O memory\n"); |
273 | goto err_free; | 281 | goto err_free; |
274 | } | 282 | } |
283 | spin_lock_init(&wdt->io_lock); | ||
275 | wdt->users = 0; | 284 | wdt->users = 0; |
276 | wdt->miscdev.minor = WATCHDOG_MINOR; | 285 | wdt->miscdev.minor = WATCHDOG_MINOR; |
277 | wdt->miscdev.name = "watchdog"; | 286 | wdt->miscdev.name = "watchdog"; |