diff options
-rw-r--r-- | drivers/watchdog/Kconfig | 1 | ||||
-rw-r--r-- | drivers/watchdog/omap_wdt.c | 260 |
2 files changed, 112 insertions, 149 deletions
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index b19465c15091..aecce5c8cf11 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig | |||
@@ -232,6 +232,7 @@ config EP93XX_WATCHDOG | |||
232 | config OMAP_WATCHDOG | 232 | config OMAP_WATCHDOG |
233 | tristate "OMAP Watchdog" | 233 | tristate "OMAP Watchdog" |
234 | depends on ARCH_OMAP16XX || ARCH_OMAP2PLUS | 234 | depends on ARCH_OMAP16XX || ARCH_OMAP2PLUS |
235 | select WATCHDOG_CORE | ||
235 | help | 236 | help |
236 | Support for TI OMAP1610/OMAP1710/OMAP2420/OMAP3430/OMAP4430 watchdog. Say 'Y' | 237 | Support for TI OMAP1610/OMAP1710/OMAP2420/OMAP3430/OMAP4430 watchdog. Say 'Y' |
237 | here to enable the OMAP1610/OMAP1710/OMAP2420/OMAP3430/OMAP4430 watchdog timer. | 238 | here to enable the OMAP1610/OMAP1710/OMAP2420/OMAP3430/OMAP4430 watchdog timer. |
diff --git a/drivers/watchdog/omap_wdt.c b/drivers/watchdog/omap_wdt.c index 3e3ebbc83faf..89db92d10ade 100644 --- a/drivers/watchdog/omap_wdt.c +++ b/drivers/watchdog/omap_wdt.c | |||
@@ -31,42 +31,34 @@ | |||
31 | #include <linux/module.h> | 31 | #include <linux/module.h> |
32 | #include <linux/types.h> | 32 | #include <linux/types.h> |
33 | #include <linux/kernel.h> | 33 | #include <linux/kernel.h> |
34 | #include <linux/fs.h> | ||
35 | #include <linux/mm.h> | 34 | #include <linux/mm.h> |
36 | #include <linux/miscdevice.h> | ||
37 | #include <linux/watchdog.h> | 35 | #include <linux/watchdog.h> |
38 | #include <linux/reboot.h> | 36 | #include <linux/reboot.h> |
39 | #include <linux/init.h> | 37 | #include <linux/init.h> |
40 | #include <linux/err.h> | 38 | #include <linux/err.h> |
41 | #include <linux/platform_device.h> | 39 | #include <linux/platform_device.h> |
42 | #include <linux/moduleparam.h> | 40 | #include <linux/moduleparam.h> |
43 | #include <linux/bitops.h> | ||
44 | #include <linux/io.h> | 41 | #include <linux/io.h> |
45 | #include <linux/uaccess.h> | ||
46 | #include <linux/slab.h> | 42 | #include <linux/slab.h> |
47 | #include <linux/pm_runtime.h> | 43 | #include <linux/pm_runtime.h> |
48 | #include <linux/platform_data/omap-wd-timer.h> | 44 | #include <linux/platform_data/omap-wd-timer.h> |
49 | 45 | ||
50 | #include "omap_wdt.h" | 46 | #include "omap_wdt.h" |
51 | 47 | ||
52 | static struct platform_device *omap_wdt_dev; | ||
53 | |||
54 | static unsigned timer_margin; | 48 | static unsigned timer_margin; |
55 | module_param(timer_margin, uint, 0); | 49 | module_param(timer_margin, uint, 0); |
56 | MODULE_PARM_DESC(timer_margin, "initial watchdog timeout (in seconds)"); | 50 | MODULE_PARM_DESC(timer_margin, "initial watchdog timeout (in seconds)"); |
57 | 51 | ||
58 | static unsigned int wdt_trgr_pattern = 0x1234; | ||
59 | static DEFINE_SPINLOCK(wdt_lock); | ||
60 | |||
61 | struct omap_wdt_dev { | 52 | struct omap_wdt_dev { |
62 | void __iomem *base; /* physical */ | 53 | void __iomem *base; /* physical */ |
63 | struct device *dev; | 54 | struct device *dev; |
64 | int omap_wdt_users; | 55 | bool omap_wdt_users; |
65 | struct resource *mem; | 56 | struct resource *mem; |
66 | struct miscdevice omap_wdt_miscdev; | 57 | int wdt_trgr_pattern; |
58 | struct mutex lock; /* to avoid races with PM */ | ||
67 | }; | 59 | }; |
68 | 60 | ||
69 | static void omap_wdt_ping(struct omap_wdt_dev *wdev) | 61 | static void omap_wdt_reload(struct omap_wdt_dev *wdev) |
70 | { | 62 | { |
71 | void __iomem *base = wdev->base; | 63 | void __iomem *base = wdev->base; |
72 | 64 | ||
@@ -74,8 +66,8 @@ static void omap_wdt_ping(struct omap_wdt_dev *wdev) | |||
74 | while ((__raw_readl(base + OMAP_WATCHDOG_WPS)) & 0x08) | 66 | while ((__raw_readl(base + OMAP_WATCHDOG_WPS)) & 0x08) |
75 | cpu_relax(); | 67 | cpu_relax(); |
76 | 68 | ||
77 | wdt_trgr_pattern = ~wdt_trgr_pattern; | 69 | wdev->wdt_trgr_pattern = ~wdev->wdt_trgr_pattern; |
78 | __raw_writel(wdt_trgr_pattern, (base + OMAP_WATCHDOG_TGR)); | 70 | __raw_writel(wdev->wdt_trgr_pattern, (base + OMAP_WATCHDOG_TGR)); |
79 | 71 | ||
80 | /* wait for posted write to complete */ | 72 | /* wait for posted write to complete */ |
81 | while ((__raw_readl(base + OMAP_WATCHDOG_WPS)) & 0x08) | 73 | while ((__raw_readl(base + OMAP_WATCHDOG_WPS)) & 0x08) |
@@ -111,18 +103,10 @@ static void omap_wdt_disable(struct omap_wdt_dev *wdev) | |||
111 | cpu_relax(); | 103 | cpu_relax(); |
112 | } | 104 | } |
113 | 105 | ||
114 | static void omap_wdt_adjust_timeout(unsigned new_timeout) | 106 | static void omap_wdt_set_timer(struct omap_wdt_dev *wdev, |
115 | { | 107 | unsigned int timeout) |
116 | if (new_timeout < TIMER_MARGIN_MIN) | ||
117 | new_timeout = TIMER_MARGIN_DEFAULT; | ||
118 | if (new_timeout > TIMER_MARGIN_MAX) | ||
119 | new_timeout = TIMER_MARGIN_MAX; | ||
120 | timer_margin = new_timeout; | ||
121 | } | ||
122 | |||
123 | static void omap_wdt_set_timeout(struct omap_wdt_dev *wdev) | ||
124 | { | 108 | { |
125 | u32 pre_margin = GET_WLDR_VAL(timer_margin); | 109 | u32 pre_margin = GET_WLDR_VAL(timeout); |
126 | void __iomem *base = wdev->base; | 110 | void __iomem *base = wdev->base; |
127 | 111 | ||
128 | /* just count up at 32 KHz */ | 112 | /* just count up at 32 KHz */ |
@@ -134,16 +118,14 @@ static void omap_wdt_set_timeout(struct omap_wdt_dev *wdev) | |||
134 | cpu_relax(); | 118 | cpu_relax(); |
135 | } | 119 | } |
136 | 120 | ||
137 | /* | 121 | static int omap_wdt_start(struct watchdog_device *wdog) |
138 | * Allow only one task to hold it open | ||
139 | */ | ||
140 | static int omap_wdt_open(struct inode *inode, struct file *file) | ||
141 | { | 122 | { |
142 | struct omap_wdt_dev *wdev = platform_get_drvdata(omap_wdt_dev); | 123 | struct omap_wdt_dev *wdev = watchdog_get_drvdata(wdog); |
143 | void __iomem *base = wdev->base; | 124 | void __iomem *base = wdev->base; |
144 | 125 | ||
145 | if (test_and_set_bit(1, (unsigned long *)&(wdev->omap_wdt_users))) | 126 | mutex_lock(&wdev->lock); |
146 | return -EBUSY; | 127 | |
128 | wdev->omap_wdt_users = true; | ||
147 | 129 | ||
148 | pm_runtime_get_sync(wdev->dev); | 130 | pm_runtime_get_sync(wdev->dev); |
149 | 131 | ||
@@ -155,117 +137,81 @@ static int omap_wdt_open(struct inode *inode, struct file *file) | |||
155 | while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x01) | 137 | while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x01) |
156 | cpu_relax(); | 138 | cpu_relax(); |
157 | 139 | ||
158 | file->private_data = (void *) wdev; | 140 | omap_wdt_set_timer(wdev, wdog->timeout); |
159 | 141 | omap_wdt_reload(wdev); /* trigger loading of new timeout value */ | |
160 | omap_wdt_set_timeout(wdev); | ||
161 | omap_wdt_ping(wdev); /* trigger loading of new timeout value */ | ||
162 | omap_wdt_enable(wdev); | 142 | omap_wdt_enable(wdev); |
163 | 143 | ||
164 | return nonseekable_open(inode, file); | 144 | mutex_unlock(&wdev->lock); |
145 | |||
146 | return 0; | ||
165 | } | 147 | } |
166 | 148 | ||
167 | static int omap_wdt_release(struct inode *inode, struct file *file) | 149 | static int omap_wdt_stop(struct watchdog_device *wdog) |
168 | { | 150 | { |
169 | struct omap_wdt_dev *wdev = file->private_data; | 151 | struct omap_wdt_dev *wdev = watchdog_get_drvdata(wdog); |
170 | 152 | ||
171 | /* | 153 | mutex_lock(&wdev->lock); |
172 | * Shut off the timer unless NOWAYOUT is defined. | ||
173 | */ | ||
174 | #ifndef CONFIG_WATCHDOG_NOWAYOUT | ||
175 | omap_wdt_disable(wdev); | 154 | omap_wdt_disable(wdev); |
176 | |||
177 | pm_runtime_put_sync(wdev->dev); | 155 | pm_runtime_put_sync(wdev->dev); |
178 | #else | 156 | wdev->omap_wdt_users = false; |
179 | pr_crit("Unexpected close, not stopping!\n"); | 157 | mutex_unlock(&wdev->lock); |
180 | #endif | ||
181 | wdev->omap_wdt_users = 0; | ||
182 | |||
183 | return 0; | 158 | return 0; |
184 | } | 159 | } |
185 | 160 | ||
186 | static ssize_t omap_wdt_write(struct file *file, const char __user *data, | 161 | static int omap_wdt_ping(struct watchdog_device *wdog) |
187 | size_t len, loff_t *ppos) | ||
188 | { | 162 | { |
189 | struct omap_wdt_dev *wdev = file->private_data; | 163 | struct omap_wdt_dev *wdev = watchdog_get_drvdata(wdog); |
190 | 164 | ||
191 | /* Refresh LOAD_TIME. */ | 165 | mutex_lock(&wdev->lock); |
192 | if (len) { | 166 | omap_wdt_reload(wdev); |
193 | spin_lock(&wdt_lock); | 167 | mutex_unlock(&wdev->lock); |
194 | omap_wdt_ping(wdev); | 168 | |
195 | spin_unlock(&wdt_lock); | 169 | return 0; |
196 | } | ||
197 | return len; | ||
198 | } | 170 | } |
199 | 171 | ||
200 | static long omap_wdt_ioctl(struct file *file, unsigned int cmd, | 172 | static int omap_wdt_set_timeout(struct watchdog_device *wdog, |
201 | unsigned long arg) | 173 | unsigned int timeout) |
202 | { | 174 | { |
203 | struct omap_wd_timer_platform_data *pdata; | 175 | struct omap_wdt_dev *wdev = watchdog_get_drvdata(wdog); |
204 | struct omap_wdt_dev *wdev; | ||
205 | u32 rs; | ||
206 | int new_margin, bs; | ||
207 | static const struct watchdog_info ident = { | ||
208 | .identity = "OMAP Watchdog", | ||
209 | .options = WDIOF_SETTIMEOUT, | ||
210 | .firmware_version = 0, | ||
211 | }; | ||
212 | |||
213 | wdev = file->private_data; | ||
214 | pdata = wdev->dev->platform_data; | ||
215 | |||
216 | switch (cmd) { | ||
217 | case WDIOC_GETSUPPORT: | ||
218 | return copy_to_user((struct watchdog_info __user *)arg, &ident, | ||
219 | sizeof(ident)); | ||
220 | case WDIOC_GETSTATUS: | ||
221 | return put_user(0, (int __user *)arg); | ||
222 | case WDIOC_GETBOOTSTATUS: | ||
223 | if (!pdata || !pdata->read_reset_sources) | ||
224 | return put_user(0, (int __user *)arg); | ||
225 | rs = pdata->read_reset_sources(); | ||
226 | bs = (rs & (1 << OMAP_MPU_WD_RST_SRC_ID_SHIFT)) ? | ||
227 | WDIOF_CARDRESET : 0; | ||
228 | return put_user(bs, (int __user *)arg); | ||
229 | case WDIOC_KEEPALIVE: | ||
230 | spin_lock(&wdt_lock); | ||
231 | omap_wdt_ping(wdev); | ||
232 | spin_unlock(&wdt_lock); | ||
233 | return 0; | ||
234 | case WDIOC_SETTIMEOUT: | ||
235 | if (get_user(new_margin, (int __user *)arg)) | ||
236 | return -EFAULT; | ||
237 | omap_wdt_adjust_timeout(new_margin); | ||
238 | |||
239 | spin_lock(&wdt_lock); | ||
240 | omap_wdt_disable(wdev); | ||
241 | omap_wdt_set_timeout(wdev); | ||
242 | omap_wdt_enable(wdev); | ||
243 | 176 | ||
244 | omap_wdt_ping(wdev); | 177 | mutex_lock(&wdev->lock); |
245 | spin_unlock(&wdt_lock); | 178 | omap_wdt_disable(wdev); |
246 | /* Fall */ | 179 | omap_wdt_set_timer(wdev, timeout); |
247 | case WDIOC_GETTIMEOUT: | 180 | omap_wdt_enable(wdev); |
248 | return put_user(timer_margin, (int __user *)arg); | 181 | omap_wdt_reload(wdev); |
249 | default: | 182 | wdog->timeout = timeout; |
250 | return -ENOTTY; | 183 | mutex_unlock(&wdev->lock); |
251 | } | 184 | |
185 | return 0; | ||
252 | } | 186 | } |
253 | 187 | ||
254 | static const struct file_operations omap_wdt_fops = { | 188 | static const struct watchdog_info omap_wdt_info = { |
255 | .owner = THIS_MODULE, | 189 | .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, |
256 | .write = omap_wdt_write, | 190 | .identity = "OMAP Watchdog", |
257 | .unlocked_ioctl = omap_wdt_ioctl, | 191 | }; |
258 | .open = omap_wdt_open, | 192 | |
259 | .release = omap_wdt_release, | 193 | static const struct watchdog_ops omap_wdt_ops = { |
260 | .llseek = no_llseek, | 194 | .owner = THIS_MODULE, |
195 | .start = omap_wdt_start, | ||
196 | .stop = omap_wdt_stop, | ||
197 | .ping = omap_wdt_ping, | ||
198 | .set_timeout = omap_wdt_set_timeout, | ||
261 | }; | 199 | }; |
262 | 200 | ||
263 | static int omap_wdt_probe(struct platform_device *pdev) | 201 | static int omap_wdt_probe(struct platform_device *pdev) |
264 | { | 202 | { |
203 | struct omap_wd_timer_platform_data *pdata = pdev->dev.platform_data; | ||
204 | bool nowayout = WATCHDOG_NOWAYOUT; | ||
205 | struct watchdog_device *omap_wdt; | ||
265 | struct resource *res, *mem; | 206 | struct resource *res, *mem; |
266 | struct omap_wdt_dev *wdev; | 207 | struct omap_wdt_dev *wdev; |
208 | u32 rs; | ||
267 | int ret; | 209 | int ret; |
268 | 210 | ||
211 | omap_wdt = kzalloc(sizeof(*omap_wdt), GFP_KERNEL); | ||
212 | if (!omap_wdt) | ||
213 | return -ENOMEM; | ||
214 | |||
269 | /* reserve static register mappings */ | 215 | /* reserve static register mappings */ |
270 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 216 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
271 | if (!res) { | 217 | if (!res) { |
@@ -273,11 +219,6 @@ static int omap_wdt_probe(struct platform_device *pdev) | |||
273 | goto err_get_resource; | 219 | goto err_get_resource; |
274 | } | 220 | } |
275 | 221 | ||
276 | if (omap_wdt_dev) { | ||
277 | ret = -EBUSY; | ||
278 | goto err_busy; | ||
279 | } | ||
280 | |||
281 | mem = request_mem_region(res->start, resource_size(res), pdev->name); | 222 | mem = request_mem_region(res->start, resource_size(res), pdev->name); |
282 | if (!mem) { | 223 | if (!mem) { |
283 | ret = -EBUSY; | 224 | ret = -EBUSY; |
@@ -290,9 +231,11 @@ static int omap_wdt_probe(struct platform_device *pdev) | |||
290 | goto err_kzalloc; | 231 | goto err_kzalloc; |
291 | } | 232 | } |
292 | 233 | ||
293 | wdev->omap_wdt_users = 0; | 234 | wdev->omap_wdt_users = false; |
294 | wdev->mem = mem; | 235 | wdev->mem = mem; |
295 | wdev->dev = &pdev->dev; | 236 | wdev->dev = &pdev->dev; |
237 | wdev->wdt_trgr_pattern = 0x1234; | ||
238 | mutex_init(&wdev->lock); | ||
296 | 239 | ||
297 | wdev->base = ioremap(res->start, resource_size(res)); | 240 | wdev->base = ioremap(res->start, resource_size(res)); |
298 | if (!wdev->base) { | 241 | if (!wdev->base) { |
@@ -300,34 +243,47 @@ static int omap_wdt_probe(struct platform_device *pdev) | |||
300 | goto err_ioremap; | 243 | goto err_ioremap; |
301 | } | 244 | } |
302 | 245 | ||
303 | platform_set_drvdata(pdev, wdev); | 246 | omap_wdt->info = &omap_wdt_info; |
247 | omap_wdt->ops = &omap_wdt_ops; | ||
248 | omap_wdt->min_timeout = TIMER_MARGIN_MIN; | ||
249 | omap_wdt->max_timeout = TIMER_MARGIN_MAX; | ||
250 | |||
251 | if (timer_margin >= TIMER_MARGIN_MIN && | ||
252 | timer_margin <= TIMER_MARGIN_MAX) | ||
253 | omap_wdt->timeout = timer_margin; | ||
254 | else | ||
255 | omap_wdt->timeout = TIMER_MARGIN_DEFAULT; | ||
256 | |||
257 | watchdog_set_drvdata(omap_wdt, wdev); | ||
258 | watchdog_set_nowayout(omap_wdt, nowayout); | ||
259 | |||
260 | platform_set_drvdata(pdev, omap_wdt); | ||
304 | 261 | ||
305 | pm_runtime_enable(wdev->dev); | 262 | pm_runtime_enable(wdev->dev); |
306 | pm_runtime_get_sync(wdev->dev); | 263 | pm_runtime_get_sync(wdev->dev); |
307 | 264 | ||
308 | omap_wdt_disable(wdev); | 265 | if (pdata && pdata->read_reset_sources) |
309 | omap_wdt_adjust_timeout(timer_margin); | 266 | rs = pdata->read_reset_sources(); |
267 | else | ||
268 | rs = 0; | ||
269 | omap_wdt->bootstatus = (rs & (1 << OMAP_MPU_WD_RST_SRC_ID_SHIFT)) ? | ||
270 | WDIOF_CARDRESET : 0; | ||
310 | 271 | ||
311 | wdev->omap_wdt_miscdev.parent = &pdev->dev; | 272 | omap_wdt_disable(wdev); |
312 | wdev->omap_wdt_miscdev.minor = WATCHDOG_MINOR; | ||
313 | wdev->omap_wdt_miscdev.name = "watchdog"; | ||
314 | wdev->omap_wdt_miscdev.fops = &omap_wdt_fops; | ||
315 | 273 | ||
316 | ret = misc_register(&(wdev->omap_wdt_miscdev)); | 274 | ret = watchdog_register_device(omap_wdt); |
317 | if (ret) | 275 | if (ret) |
318 | goto err_misc; | 276 | goto err_register; |
319 | 277 | ||
320 | pr_info("OMAP Watchdog Timer Rev 0x%02x: initial timeout %d sec\n", | 278 | pr_info("OMAP Watchdog Timer Rev 0x%02x: initial timeout %d sec\n", |
321 | __raw_readl(wdev->base + OMAP_WATCHDOG_REV) & 0xFF, | 279 | __raw_readl(wdev->base + OMAP_WATCHDOG_REV) & 0xFF, |
322 | timer_margin); | 280 | omap_wdt->timeout); |
323 | 281 | ||
324 | pm_runtime_put_sync(wdev->dev); | 282 | pm_runtime_put_sync(wdev->dev); |
325 | 283 | ||
326 | omap_wdt_dev = pdev; | ||
327 | |||
328 | return 0; | 284 | return 0; |
329 | 285 | ||
330 | err_misc: | 286 | err_register: |
331 | pm_runtime_disable(wdev->dev); | 287 | pm_runtime_disable(wdev->dev); |
332 | platform_set_drvdata(pdev, NULL); | 288 | platform_set_drvdata(pdev, NULL); |
333 | iounmap(wdev->base); | 289 | iounmap(wdev->base); |
@@ -341,37 +297,38 @@ err_kzalloc: | |||
341 | 297 | ||
342 | err_busy: | 298 | err_busy: |
343 | err_get_resource: | 299 | err_get_resource: |
344 | 300 | kfree(omap_wdt); | |
345 | return ret; | 301 | return ret; |
346 | } | 302 | } |
347 | 303 | ||
348 | static void omap_wdt_shutdown(struct platform_device *pdev) | 304 | static void omap_wdt_shutdown(struct platform_device *pdev) |
349 | { | 305 | { |
350 | struct omap_wdt_dev *wdev = platform_get_drvdata(pdev); | 306 | struct watchdog_device *wdog = platform_get_drvdata(pdev); |
307 | struct omap_wdt_dev *wdev = watchdog_get_drvdata(wdog); | ||
351 | 308 | ||
309 | mutex_lock(&wdev->lock); | ||
352 | if (wdev->omap_wdt_users) { | 310 | if (wdev->omap_wdt_users) { |
353 | omap_wdt_disable(wdev); | 311 | omap_wdt_disable(wdev); |
354 | pm_runtime_put_sync(wdev->dev); | 312 | pm_runtime_put_sync(wdev->dev); |
355 | } | 313 | } |
314 | mutex_unlock(&wdev->lock); | ||
356 | } | 315 | } |
357 | 316 | ||
358 | static int omap_wdt_remove(struct platform_device *pdev) | 317 | static int omap_wdt_remove(struct platform_device *pdev) |
359 | { | 318 | { |
360 | struct omap_wdt_dev *wdev = platform_get_drvdata(pdev); | 319 | struct watchdog_device *wdog = platform_get_drvdata(pdev); |
320 | struct omap_wdt_dev *wdev = watchdog_get_drvdata(wdog); | ||
361 | struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 321 | struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
362 | 322 | ||
363 | pm_runtime_disable(wdev->dev); | 323 | pm_runtime_disable(wdev->dev); |
364 | if (!res) | 324 | watchdog_unregister_device(wdog); |
365 | return -ENOENT; | ||
366 | |||
367 | misc_deregister(&(wdev->omap_wdt_miscdev)); | ||
368 | release_mem_region(res->start, resource_size(res)); | 325 | release_mem_region(res->start, resource_size(res)); |
369 | platform_set_drvdata(pdev, NULL); | 326 | platform_set_drvdata(pdev, NULL); |
370 | 327 | ||
371 | iounmap(wdev->base); | 328 | iounmap(wdev->base); |
372 | 329 | ||
373 | kfree(wdev); | 330 | kfree(wdev); |
374 | omap_wdt_dev = NULL; | 331 | kfree(wdog); |
375 | 332 | ||
376 | return 0; | 333 | return 0; |
377 | } | 334 | } |
@@ -386,25 +343,31 @@ static int omap_wdt_remove(struct platform_device *pdev) | |||
386 | 343 | ||
387 | static int omap_wdt_suspend(struct platform_device *pdev, pm_message_t state) | 344 | static int omap_wdt_suspend(struct platform_device *pdev, pm_message_t state) |
388 | { | 345 | { |
389 | struct omap_wdt_dev *wdev = platform_get_drvdata(pdev); | 346 | struct watchdog_device *wdog = platform_get_drvdata(pdev); |
347 | struct omap_wdt_dev *wdev = watchdog_get_drvdata(wdog); | ||
390 | 348 | ||
349 | mutex_lock(&wdev->lock); | ||
391 | if (wdev->omap_wdt_users) { | 350 | if (wdev->omap_wdt_users) { |
392 | omap_wdt_disable(wdev); | 351 | omap_wdt_disable(wdev); |
393 | pm_runtime_put_sync(wdev->dev); | 352 | pm_runtime_put_sync(wdev->dev); |
394 | } | 353 | } |
354 | mutex_unlock(&wdev->lock); | ||
395 | 355 | ||
396 | return 0; | 356 | return 0; |
397 | } | 357 | } |
398 | 358 | ||
399 | static int omap_wdt_resume(struct platform_device *pdev) | 359 | static int omap_wdt_resume(struct platform_device *pdev) |
400 | { | 360 | { |
401 | struct omap_wdt_dev *wdev = platform_get_drvdata(pdev); | 361 | struct watchdog_device *wdog = platform_get_drvdata(pdev); |
362 | struct omap_wdt_dev *wdev = watchdog_get_drvdata(wdog); | ||
402 | 363 | ||
364 | mutex_lock(&wdev->lock); | ||
403 | if (wdev->omap_wdt_users) { | 365 | if (wdev->omap_wdt_users) { |
404 | pm_runtime_get_sync(wdev->dev); | 366 | pm_runtime_get_sync(wdev->dev); |
405 | omap_wdt_enable(wdev); | 367 | omap_wdt_enable(wdev); |
406 | omap_wdt_ping(wdev); | 368 | omap_wdt_reload(wdev); |
407 | } | 369 | } |
370 | mutex_unlock(&wdev->lock); | ||
408 | 371 | ||
409 | return 0; | 372 | return 0; |
410 | } | 373 | } |
@@ -437,5 +400,4 @@ module_platform_driver(omap_wdt_driver); | |||
437 | 400 | ||
438 | MODULE_AUTHOR("George G. Davis"); | 401 | MODULE_AUTHOR("George G. Davis"); |
439 | MODULE_LICENSE("GPL"); | 402 | MODULE_LICENSE("GPL"); |
440 | MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); | ||
441 | MODULE_ALIAS("platform:omap_wdt"); | 403 | MODULE_ALIAS("platform:omap_wdt"); |