Blame view

drivers/watchdog/mpcore_wdt.c 10.6 KB
b9d36b851   Russell King   [ARM SMP] Add MPC...
1
2
3
4
5
6
  /*
   *	Watchdog driver for the mpcore watchdog timer
   *
   *	(c) Copyright 2004 ARM Limited
   *
   *	Based on the SoftDog driver:
29fa0586d   Alan Cox   [PATCH] Switch al...
7
   *	(c) Copyright 1996 Alan Cox <alan@lxorguk.ukuu.org.uk>,
143a2e54b   Wim Van Sebroeck   [WATCHDOG] More c...
8
   *						All Rights Reserved.
b9d36b851   Russell King   [ARM SMP] Add MPC...
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
   *
   *	This program is free software; you can redistribute it and/or
   *	modify it under the terms of the GNU General Public License
   *	as published by the Free Software Foundation; either version
   *	2 of the License, or (at your option) any later version.
   *
   *	Neither Alan Cox nor CymruNet Ltd. admit liability nor provide
   *	warranty for any of this software. This material is provided
   *	"AS-IS" and at no charge.
   *
   *	(c) Copyright 1995    Alan Cox <alan@lxorguk.ukuu.org.uk>
   *
   */
  #include <linux/module.h>
  #include <linux/moduleparam.h>
b9d36b851   Russell King   [ARM SMP] Add MPC...
24
25
26
27
28
29
30
  #include <linux/types.h>
  #include <linux/miscdevice.h>
  #include <linux/watchdog.h>
  #include <linux/fs.h>
  #include <linux/reboot.h>
  #include <linux/init.h>
  #include <linux/interrupt.h>
d052d1bef   Russell King   Create platform_d...
31
  #include <linux/platform_device.h>
83ab1a53f   Alan Cox   [WATCHDOG 27/57] ...
32
  #include <linux/uaccess.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
33
  #include <linux/slab.h>
98af05709   Srinidhi Kasagar   ARM: 6126/1: ARM ...
34
  #include <linux/io.h>
ad4162f37   Russell King   [ARM SMP] Add tim...
35

98af05709   Srinidhi Kasagar   ARM: 6126/1: ARM ...
36
  #include <asm/smp_twd.h>
b9d36b851   Russell King   [ARM SMP] Add MPC...
37
38
39
40
41
42
43
44
45
46
47
  
  struct mpcore_wdt {
  	unsigned long	timer_alive;
  	struct device	*dev;
  	void __iomem	*base;
  	int		irq;
  	unsigned int	perturb;
  	char		expect_close;
  };
  
  static struct platform_device *mpcore_wdt_dev;
98af05709   Srinidhi Kasagar   ARM: 6126/1: ARM ...
48
  static DEFINE_SPINLOCK(wdt_lock);
b9d36b851   Russell King   [ARM SMP] Add MPC...
49
50
51
52
  
  #define TIMER_MARGIN	60
  static int mpcore_margin = TIMER_MARGIN;
  module_param(mpcore_margin, int, 0);
83ab1a53f   Alan Cox   [WATCHDOG 27/57] ...
53
54
55
  MODULE_PARM_DESC(mpcore_margin,
  	"MPcore timer margin in seconds. (0 < mpcore_margin < 65536, default="
  				__MODULE_STRING(TIMER_MARGIN) ")");
b9d36b851   Russell King   [ARM SMP] Add MPC...
56
57
58
  
  static int nowayout = WATCHDOG_NOWAYOUT;
  module_param(nowayout, int, 0);
83ab1a53f   Alan Cox   [WATCHDOG 27/57] ...
59
60
61
  MODULE_PARM_DESC(nowayout,
  	"Watchdog cannot be stopped once started (default="
  				__MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
b9d36b851   Russell King   [ARM SMP] Add MPC...
62
63
64
65
  
  #define ONLY_TESTING	0
  static int mpcore_noboot = ONLY_TESTING;
  module_param(mpcore_noboot, int, 0);
a77dba7e4   Wim Van Sebroeck   [WATCHDOG] Some m...
66
67
68
  MODULE_PARM_DESC(mpcore_noboot, "MPcore watchdog action, "
  	"set to 1 to ignore reboots, 0 to reboot (default="
  					__MODULE_STRING(ONLY_TESTING) ")");
b9d36b851   Russell King   [ARM SMP] Add MPC...
69
70
71
72
73
  
  /*
   *	This is the interrupt handler.  Note that we only use this
   *	in testing mode, so don't actually do a reboot here.
   */
7d12e780e   David Howells   IRQ: Maintain reg...
74
  static irqreturn_t mpcore_wdt_fire(int irq, void *arg)
b9d36b851   Russell King   [ARM SMP] Add MPC...
75
76
77
78
79
  {
  	struct mpcore_wdt *wdt = arg;
  
  	/* Check it really was our interrupt */
  	if (readl(wdt->base + TWD_WDOG_INTSTAT)) {
83ab1a53f   Alan Cox   [WATCHDOG 27/57] ...
80
81
82
  		dev_printk(KERN_CRIT, wdt->dev,
  					"Triggered - Reboot ignored.
  ");
b9d36b851   Russell King   [ARM SMP] Add MPC...
83
84
  		/* Clear the interrupt on the watchdog */
  		writel(1, wdt->base + TWD_WDOG_INTSTAT);
b9d36b851   Russell King   [ARM SMP] Add MPC...
85
86
  		return IRQ_HANDLED;
  	}
b9d36b851   Russell King   [ARM SMP] Add MPC...
87
88
89
90
91
92
93
94
95
96
97
98
  	return IRQ_NONE;
  }
  
  /*
   *	mpcore_wdt_keepalive - reload the timer
   *
   *	Note that the spec says a DIFFERENT value must be written to the reload
   *	register each time.  The "perturb" variable deals with this by adding 1
   *	to the count every other time the function is called.
   */
  static void mpcore_wdt_keepalive(struct mpcore_wdt *wdt)
  {
98af05709   Srinidhi Kasagar   ARM: 6126/1: ARM ...
99
  	unsigned long count;
b9d36b851   Russell King   [ARM SMP] Add MPC...
100

98af05709   Srinidhi Kasagar   ARM: 6126/1: ARM ...
101
  	spin_lock(&wdt_lock);
b9d36b851   Russell King   [ARM SMP] Add MPC...
102
  	/* Assume prescale is set to 256 */
98af05709   Srinidhi Kasagar   ARM: 6126/1: ARM ...
103
104
105
  	count =  __raw_readl(wdt->base + TWD_WDOG_COUNTER);
  	count = (0xFFFFFFFFU - count) * (HZ / 5);
  	count = (count / 256) * mpcore_margin;
b9d36b851   Russell King   [ARM SMP] Add MPC...
106
107
108
  
  	/* Reload the counter */
  	writel(count + wdt->perturb, wdt->base + TWD_WDOG_LOAD);
b9d36b851   Russell King   [ARM SMP] Add MPC...
109
  	wdt->perturb = wdt->perturb ? 0 : 1;
83ab1a53f   Alan Cox   [WATCHDOG 27/57] ...
110
  	spin_unlock(&wdt_lock);
b9d36b851   Russell King   [ARM SMP] Add MPC...
111
112
113
114
  }
  
  static void mpcore_wdt_stop(struct mpcore_wdt *wdt)
  {
83ab1a53f   Alan Cox   [WATCHDOG 27/57] ...
115
  	spin_lock(&wdt_lock);
b9d36b851   Russell King   [ARM SMP] Add MPC...
116
117
118
  	writel(0x12345678, wdt->base + TWD_WDOG_DISABLE);
  	writel(0x87654321, wdt->base + TWD_WDOG_DISABLE);
  	writel(0x0, wdt->base + TWD_WDOG_CONTROL);
83ab1a53f   Alan Cox   [WATCHDOG 27/57] ...
119
  	spin_unlock(&wdt_lock);
b9d36b851   Russell King   [ARM SMP] Add MPC...
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
  }
  
  static void mpcore_wdt_start(struct mpcore_wdt *wdt)
  {
  	dev_printk(KERN_INFO, wdt->dev, "enabling watchdog.
  ");
  
  	/* This loads the count register but does NOT start the count yet */
  	mpcore_wdt_keepalive(wdt);
  
  	if (mpcore_noboot) {
  		/* Enable watchdog - prescale=256, watchdog mode=0, enable=1 */
  		writel(0x0000FF01, wdt->base + TWD_WDOG_CONTROL);
  	} else {
  		/* Enable watchdog - prescale=256, watchdog mode=1, enable=1 */
  		writel(0x0000FF09, wdt->base + TWD_WDOG_CONTROL);
  	}
  }
  
  static int mpcore_wdt_set_heartbeat(int t)
  {
  	if (t < 0x0001 || t > 0xFFFF)
  		return -EINVAL;
  
  	mpcore_margin = t;
  	return 0;
  }
  
  /*
   *	/dev/watchdog handling
   */
  static int mpcore_wdt_open(struct inode *inode, struct file *file)
  {
3ae5eaec1   Russell King   [DRIVER MODEL] Co...
153
  	struct mpcore_wdt *wdt = platform_get_drvdata(mpcore_wdt_dev);
b9d36b851   Russell King   [ARM SMP] Add MPC...
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
  
  	if (test_and_set_bit(0, &wdt->timer_alive))
  		return -EBUSY;
  
  	if (nowayout)
  		__module_get(THIS_MODULE);
  
  	file->private_data = wdt;
  
  	/*
  	 *	Activate timer
  	 */
  	mpcore_wdt_start(wdt);
  
  	return nonseekable_open(inode, file);
  }
  
  static int mpcore_wdt_release(struct inode *inode, struct file *file)
  {
  	struct mpcore_wdt *wdt = file->private_data;
  
  	/*
  	 *	Shut off the timer.
5f3b27569   Wim Van Sebroeck   watchdog: cleanup...
177
  	 *	Lock it in if it's a module and we set nowayout
b9d36b851   Russell King   [ARM SMP] Add MPC...
178
  	 */
83ab1a53f   Alan Cox   [WATCHDOG 27/57] ...
179
  	if (wdt->expect_close == 42)
b9d36b851   Russell King   [ARM SMP] Add MPC...
180
  		mpcore_wdt_stop(wdt);
83ab1a53f   Alan Cox   [WATCHDOG 27/57] ...
181
182
183
184
  	else {
  		dev_printk(KERN_CRIT, wdt->dev,
  				"unexpected close, not stopping watchdog!
  ");
b9d36b851   Russell King   [ARM SMP] Add MPC...
185
186
187
188
189
190
  		mpcore_wdt_keepalive(wdt);
  	}
  	clear_bit(0, &wdt->timer_alive);
  	wdt->expect_close = 0;
  	return 0;
  }
83ab1a53f   Alan Cox   [WATCHDOG 27/57] ...
191
192
  static ssize_t mpcore_wdt_write(struct file *file, const char *data,
  						size_t len, loff_t *ppos)
b9d36b851   Russell King   [ARM SMP] Add MPC...
193
194
  {
  	struct mpcore_wdt *wdt = file->private_data;
b9d36b851   Russell King   [ARM SMP] Add MPC...
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
  	/*
  	 *	Refresh the timer.
  	 */
  	if (len) {
  		if (!nowayout) {
  			size_t i;
  
  			/* In case it was set long ago */
  			wdt->expect_close = 0;
  
  			for (i = 0; i != len; i++) {
  				char c;
  
  				if (get_user(c, data + i))
  					return -EFAULT;
  				if (c == 'V')
  					wdt->expect_close = 42;
  			}
  		}
  		mpcore_wdt_keepalive(wdt);
  	}
  	return len;
  }
42747d712   Wim Van Sebroeck   [WATCHDOG] watchd...
218
  static const struct watchdog_info ident = {
b9d36b851   Russell King   [ARM SMP] Add MPC...
219
220
221
222
223
  	.options		= WDIOF_SETTIMEOUT |
  				  WDIOF_KEEPALIVEPING |
  				  WDIOF_MAGICCLOSE,
  	.identity		= "MPcore Watchdog",
  };
83ab1a53f   Alan Cox   [WATCHDOG 27/57] ...
224
225
  static long mpcore_wdt_ioctl(struct file *file, unsigned int cmd,
  							unsigned long arg)
b9d36b851   Russell King   [ARM SMP] Add MPC...
226
227
228
229
230
231
232
233
234
  {
  	struct mpcore_wdt *wdt = file->private_data;
  	int ret;
  	union {
  		struct watchdog_info ident;
  		int i;
  	} uarg;
  
  	if (_IOC_DIR(cmd) && _IOC_SIZE(cmd) > sizeof(uarg))
795b89d20   Samuel Tardieu   [WATCHDOG] use EN...
235
  		return -ENOTTY;
b9d36b851   Russell King   [ARM SMP] Add MPC...
236
237
238
239
240
241
242
243
244
245
246
247
  
  	if (_IOC_DIR(cmd) & _IOC_WRITE) {
  		ret = copy_from_user(&uarg, (void __user *)arg, _IOC_SIZE(cmd));
  		if (ret)
  			return -EFAULT;
  	}
  
  	switch (cmd) {
  	case WDIOC_GETSUPPORT:
  		uarg.ident = ident;
  		ret = 0;
  		break;
0c06090c9   Wim Van Sebroeck   [WATCHDOG] Coding...
248
249
250
251
252
  	case WDIOC_GETSTATUS:
  	case WDIOC_GETBOOTSTATUS:
  		uarg.i = 0;
  		ret = 0;
  		break;
b9d36b851   Russell King   [ARM SMP] Add MPC...
253
254
255
256
257
258
259
260
261
262
263
  	case WDIOC_SETOPTIONS:
  		ret = -EINVAL;
  		if (uarg.i & WDIOS_DISABLECARD) {
  			mpcore_wdt_stop(wdt);
  			ret = 0;
  		}
  		if (uarg.i & WDIOS_ENABLECARD) {
  			mpcore_wdt_start(wdt);
  			ret = 0;
  		}
  		break;
b9d36b851   Russell King   [ARM SMP] Add MPC...
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
  	case WDIOC_KEEPALIVE:
  		mpcore_wdt_keepalive(wdt);
  		ret = 0;
  		break;
  
  	case WDIOC_SETTIMEOUT:
  		ret = mpcore_wdt_set_heartbeat(uarg.i);
  		if (ret)
  			break;
  
  		mpcore_wdt_keepalive(wdt);
  		/* Fall */
  	case WDIOC_GETTIMEOUT:
  		uarg.i = mpcore_margin;
  		ret = 0;
  		break;
  
  	default:
795b89d20   Samuel Tardieu   [WATCHDOG] use EN...
282
  		return -ENOTTY;
b9d36b851   Russell King   [ARM SMP] Add MPC...
283
284
285
286
287
288
289
290
291
292
293
294
295
296
  	}
  
  	if (ret == 0 && _IOC_DIR(cmd) & _IOC_READ) {
  		ret = copy_to_user((void __user *)arg, &uarg, _IOC_SIZE(cmd));
  		if (ret)
  			ret = -EFAULT;
  	}
  	return ret;
  }
  
  /*
   *	System shutdown handler.  Turn off the watchdog if we're
   *	restarting or halting the system.
   */
3ae5eaec1   Russell King   [DRIVER MODEL] Co...
297
  static void mpcore_wdt_shutdown(struct platform_device *dev)
b9d36b851   Russell King   [ARM SMP] Add MPC...
298
  {
3ae5eaec1   Russell King   [DRIVER MODEL] Co...
299
  	struct mpcore_wdt *wdt = platform_get_drvdata(dev);
b9d36b851   Russell King   [ARM SMP] Add MPC...
300
301
302
303
304
305
306
307
  
  	if (system_state == SYSTEM_RESTART || system_state == SYSTEM_HALT)
  		mpcore_wdt_stop(wdt);
  }
  
  /*
   *	Kernel Interfaces
   */
62322d255   Arjan van de Ven   [PATCH] make more...
308
  static const struct file_operations mpcore_wdt_fops = {
b9d36b851   Russell King   [ARM SMP] Add MPC...
309
310
311
  	.owner		= THIS_MODULE,
  	.llseek		= no_llseek,
  	.write		= mpcore_wdt_write,
83ab1a53f   Alan Cox   [WATCHDOG 27/57] ...
312
  	.unlocked_ioctl	= mpcore_wdt_ioctl,
b9d36b851   Russell King   [ARM SMP] Add MPC...
313
314
315
316
317
318
319
320
321
  	.open		= mpcore_wdt_open,
  	.release	= mpcore_wdt_release,
  };
  
  static struct miscdevice mpcore_wdt_miscdev = {
  	.minor		= WATCHDOG_MINOR,
  	.name		= "watchdog",
  	.fops		= &mpcore_wdt_fops,
  };
3ae5eaec1   Russell King   [DRIVER MODEL] Co...
322
  static int __devinit mpcore_wdt_probe(struct platform_device *dev)
b9d36b851   Russell King   [ARM SMP] Add MPC...
323
  {
b9d36b851   Russell King   [ARM SMP] Add MPC...
324
325
326
327
328
329
330
331
332
333
334
335
336
  	struct mpcore_wdt *wdt;
  	struct resource *res;
  	int ret;
  
  	/* We only accept one device, and it must have an id of -1 */
  	if (dev->id != -1)
  		return -ENODEV;
  
  	res = platform_get_resource(dev, IORESOURCE_MEM, 0);
  	if (!res) {
  		ret = -ENODEV;
  		goto err_out;
  	}
dd00cc486   Yoann Padioleau   some kmalloc/mems...
337
  	wdt = kzalloc(sizeof(struct mpcore_wdt), GFP_KERNEL);
b9d36b851   Russell King   [ARM SMP] Add MPC...
338
339
340
341
  	if (!wdt) {
  		ret = -ENOMEM;
  		goto err_out;
  	}
b9d36b851   Russell King   [ARM SMP] Add MPC...
342
343
344
  
  	wdt->dev = &dev->dev;
  	wdt->irq = platform_get_irq(dev, 0);
489447380   David Vrabel   [PATCH] handle er...
345
346
347
348
  	if (wdt->irq < 0) {
  		ret = -ENXIO;
  		goto err_free;
  	}
b782a5637   H Hartley Sweeten   [WATCHDOG] use re...
349
  	wdt->base = ioremap(res->start, resource_size(res));
b9d36b851   Russell King   [ARM SMP] Add MPC...
350
351
352
353
  	if (!wdt->base) {
  		ret = -ENOMEM;
  		goto err_free;
  	}
e0b79e0bc   Andrew Victor   [WATCHDOG] watchd...
354
  	mpcore_wdt_miscdev.parent = &dev->dev;
b9d36b851   Russell King   [ARM SMP] Add MPC...
355
356
  	ret = misc_register(&mpcore_wdt_miscdev);
  	if (ret) {
98af05709   Srinidhi Kasagar   ARM: 6126/1: ARM ...
357
  		dev_printk(KERN_ERR, wdt->dev,
83ab1a53f   Alan Cox   [WATCHDOG 27/57] ...
358
359
360
  			"cannot register miscdev on minor=%d (err=%d)
  ",
  							WATCHDOG_MINOR, ret);
b9d36b851   Russell King   [ARM SMP] Add MPC...
361
362
  		goto err_misc;
  	}
86b591288   Yong Zhang   watchdog: irq: Re...
363
  	ret = request_irq(wdt->irq, mpcore_wdt_fire, 0, "mpcore_wdt", wdt);
b9d36b851   Russell King   [ARM SMP] Add MPC...
364
  	if (ret) {
98af05709   Srinidhi Kasagar   ARM: 6126/1: ARM ...
365
  		dev_printk(KERN_ERR, wdt->dev,
83ab1a53f   Alan Cox   [WATCHDOG 27/57] ...
366
367
  			"cannot register IRQ%d for watchdog
  ", wdt->irq);
b9d36b851   Russell King   [ARM SMP] Add MPC...
368
369
370
371
  		goto err_irq;
  	}
  
  	mpcore_wdt_stop(wdt);
98af05709   Srinidhi Kasagar   ARM: 6126/1: ARM ...
372
  	platform_set_drvdata(dev, wdt);
b9d36b851   Russell King   [ARM SMP] Add MPC...
373
374
375
  	mpcore_wdt_dev = dev;
  
  	return 0;
7944d3a5a   Wim Van Sebroeck   [WATCHDOG] more c...
376
  err_irq:
b9d36b851   Russell King   [ARM SMP] Add MPC...
377
  	misc_deregister(&mpcore_wdt_miscdev);
7944d3a5a   Wim Van Sebroeck   [WATCHDOG] more c...
378
  err_misc:
b9d36b851   Russell King   [ARM SMP] Add MPC...
379
  	iounmap(wdt->base);
7944d3a5a   Wim Van Sebroeck   [WATCHDOG] more c...
380
  err_free:
b9d36b851   Russell King   [ARM SMP] Add MPC...
381
  	kfree(wdt);
7944d3a5a   Wim Van Sebroeck   [WATCHDOG] more c...
382
  err_out:
b9d36b851   Russell King   [ARM SMP] Add MPC...
383
384
  	return ret;
  }
3ae5eaec1   Russell King   [DRIVER MODEL] Co...
385
  static int __devexit mpcore_wdt_remove(struct platform_device *dev)
b9d36b851   Russell King   [ARM SMP] Add MPC...
386
  {
3ae5eaec1   Russell King   [DRIVER MODEL] Co...
387
  	struct mpcore_wdt *wdt = platform_get_drvdata(dev);
b9d36b851   Russell King   [ARM SMP] Add MPC...
388

3ae5eaec1   Russell King   [DRIVER MODEL] Co...
389
  	platform_set_drvdata(dev, NULL);
b9d36b851   Russell King   [ARM SMP] Add MPC...
390
391
392
393
394
395
396
397
398
399
  
  	misc_deregister(&mpcore_wdt_miscdev);
  
  	mpcore_wdt_dev = NULL;
  
  	free_irq(wdt->irq, wdt);
  	iounmap(wdt->base);
  	kfree(wdt);
  	return 0;
  }
641e4f449   Peter Fordham   watchdog: mpcore_...
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
  #ifdef CONFIG_PM
  static int mpcore_wdt_suspend(struct platform_device *dev, pm_message_t msg)
  {
  	struct mpcore_wdt *wdt = platform_get_drvdata(dev);
  	mpcore_wdt_stop(wdt);		/* Turn the WDT off */
  	return 0;
  }
  
  static int mpcore_wdt_resume(struct platform_device *dev)
  {
  	struct mpcore_wdt *wdt = platform_get_drvdata(dev);
  	/* re-activate timer */
  	if (test_bit(0, &wdt->timer_alive))
  		mpcore_wdt_start(wdt);
  	return 0;
  }
  #else
  #define mpcore_wdt_suspend	NULL
  #define mpcore_wdt_resume	NULL
  #endif
f37d193c7   Kay Sievers   watchdog: fix pla...
420
421
  /* work with hotplug and coldplug */
  MODULE_ALIAS("platform:mpcore_wdt");
3ae5eaec1   Russell King   [DRIVER MODEL] Co...
422
  static struct platform_driver mpcore_wdt_driver = {
b9d36b851   Russell King   [ARM SMP] Add MPC...
423
424
  	.probe		= mpcore_wdt_probe,
  	.remove		= __devexit_p(mpcore_wdt_remove),
641e4f449   Peter Fordham   watchdog: mpcore_...
425
426
  	.suspend	= mpcore_wdt_suspend,
  	.resume		= mpcore_wdt_resume,
b9d36b851   Russell King   [ARM SMP] Add MPC...
427
  	.shutdown	= mpcore_wdt_shutdown,
3ae5eaec1   Russell King   [DRIVER MODEL] Co...
428
429
430
431
  	.driver		= {
  		.owner	= THIS_MODULE,
  		.name	= "mpcore_wdt",
  	},
b9d36b851   Russell King   [ARM SMP] Add MPC...
432
  };
a77dba7e4   Wim Van Sebroeck   [WATCHDOG] Some m...
433
434
435
  static char banner[] __initdata = KERN_INFO "MPcore Watchdog Timer: 0.1. "
  		"mpcore_noboot=%d mpcore_margin=%d sec (nowayout= %d)
  ";
b9d36b851   Russell King   [ARM SMP] Add MPC...
436
437
438
439
440
441
442
443
444
  
  static int __init mpcore_wdt_init(void)
  {
  	/*
  	 * Check that the margin value is within it's range;
  	 * if not reset to the default
  	 */
  	if (mpcore_wdt_set_heartbeat(mpcore_margin)) {
  		mpcore_wdt_set_heartbeat(TIMER_MARGIN);
83ab1a53f   Alan Cox   [WATCHDOG 27/57] ...
445
446
  		printk(KERN_INFO "mpcore_margin value must be 0 < mpcore_margin < 65536, using %d
  ",
b9d36b851   Russell King   [ARM SMP] Add MPC...
447
448
449
450
  			TIMER_MARGIN);
  	}
  
  	printk(banner, mpcore_noboot, mpcore_margin, nowayout);
3ae5eaec1   Russell King   [DRIVER MODEL] Co...
451
  	return platform_driver_register(&mpcore_wdt_driver);
b9d36b851   Russell King   [ARM SMP] Add MPC...
452
453
454
455
  }
  
  static void __exit mpcore_wdt_exit(void)
  {
3ae5eaec1   Russell King   [DRIVER MODEL] Co...
456
  	platform_driver_unregister(&mpcore_wdt_driver);
b9d36b851   Russell King   [ARM SMP] Add MPC...
457
458
459
460
461
462
463
464
465
  }
  
  module_init(mpcore_wdt_init);
  module_exit(mpcore_wdt_exit);
  
  MODULE_AUTHOR("ARM Limited");
  MODULE_DESCRIPTION("MPcore Watchdog Device Driver");
  MODULE_LICENSE("GPL");
  MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);