Blame view

drivers/watchdog/at32ap700x_wdt.c 10 KB
a9cb3959a   Hans-Christian Egtvedt   [WATCHDOG] Watchd...
1
2
3
4
5
6
7
8
  /*
   * Watchdog driver for Atmel AT32AP700X devices
   *
   * Copyright (C) 2005-2006 Atmel Corporation
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License version 2 as
   * published by the Free Software Foundation.
bb133450e   Hans-Christian Egtvedt   [WATCHDOG] at32ap...
9
10
11
12
13
14
15
16
17
18
19
20
21
   *
   *
   * Errata: WDT Clear is blocked after WDT Reset
   *
   * A watchdog timer event will, after reset, block writes to the WDT_CLEAR
   * register, preventing the program to clear the next Watchdog Timer Reset.
   *
   * If you still want to use the WDT after a WDT reset a small code can be
   * insterted at the startup checking the AVR32_PM.rcause register for WDT reset
   * and use a GPIO pin to reset the system. This method requires that one of the
   * GPIO pins are available and connected externally to the RESET_N pin. After
   * the GPIO pin has pulled down the reset line the GPIO will be reset and leave
   * the pin tristated with pullup.
a9cb3959a   Hans-Christian Egtvedt   [WATCHDOG] Watchd...
22
23
24
25
26
27
28
29
30
31
   */
  
  #include <linux/init.h>
  #include <linux/kernel.h>
  #include <linux/module.h>
  #include <linux/moduleparam.h>
  #include <linux/miscdevice.h>
  #include <linux/fs.h>
  #include <linux/platform_device.h>
  #include <linux/watchdog.h>
c37f27132   Andrew Morton   [WATCHDOG] watchd...
32
33
  #include <linux/uaccess.h>
  #include <linux/io.h>
e75e65775   Wim Van Sebroeck   [WATCHDOG] at32ap...
34
  #include <linux/spinlock.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
35
  #include <linux/slab.h>
a9cb3959a   Hans-Christian Egtvedt   [WATCHDOG] Watchd...
36
37
  
  #define TIMEOUT_MIN		1
a9cb3959a   Hans-Christian Egtvedt   [WATCHDOG] Watchd...
38
  #define TIMEOUT_MAX		2
726c9f611   Wim Van Sebroeck   [WATCHDOG] at32ap...
39
40
41
42
43
44
45
46
  #define TIMEOUT_DEFAULT		TIMEOUT_MAX
  
  /* module parameters */
  static int timeout =  TIMEOUT_DEFAULT;
  module_param(timeout, int, 0);
  MODULE_PARM_DESC(timeout,
  		"Timeout value. Limited to be 1 or 2 seconds. (default="
  		__MODULE_STRING(TIMEOUT_DEFAULT) ")");
a9cb3959a   Hans-Christian Egtvedt   [WATCHDOG] Watchd...
47

28401140a   Wim Van Sebroeck   [WATCHDOG] at32ap...
48
49
50
51
  static int nowayout = WATCHDOG_NOWAYOUT;
  module_param(nowayout, int, 0);
  MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
  		__MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
a9cb3959a   Hans-Christian Egtvedt   [WATCHDOG] Watchd...
52
53
54
55
56
57
58
  /* Watchdog registers and write/read macro */
  #define WDT_CTRL		0x00
  #define WDT_CTRL_EN		   0
  #define WDT_CTRL_PSEL		   8
  #define WDT_CTRL_KEY		  24
  
  #define WDT_CLR			0x04
bb133450e   Hans-Christian Egtvedt   [WATCHDOG] at32ap...
59
60
61
62
63
64
  #define WDT_RCAUSE		0x10
  #define WDT_RCAUSE_POR		   0
  #define WDT_RCAUSE_EXT		   2
  #define WDT_RCAUSE_WDT		   3
  #define WDT_RCAUSE_JTAG		   4
  #define WDT_RCAUSE_SERP		   5
a9cb3959a   Hans-Christian Egtvedt   [WATCHDOG] Watchd...
65
  #define WDT_BIT(name)		(1 << WDT_##name)
c0ead7e0f   Wim Van Sebroeck   [WATCHDOG] at32ap...
66
  #define WDT_BF(name, value)	((value) << WDT_##name)
a9cb3959a   Hans-Christian Egtvedt   [WATCHDOG] Watchd...
67

c0ead7e0f   Wim Van Sebroeck   [WATCHDOG] at32ap...
68
  #define wdt_readl(dev, reg)				\
a9cb3959a   Hans-Christian Egtvedt   [WATCHDOG] Watchd...
69
  	__raw_readl((dev)->regs + WDT_##reg)
c0ead7e0f   Wim Van Sebroeck   [WATCHDOG] at32ap...
70
  #define wdt_writel(dev, reg, value)			\
a9cb3959a   Hans-Christian Egtvedt   [WATCHDOG] Watchd...
71
72
73
74
  	__raw_writel((value), (dev)->regs + WDT_##reg)
  
  struct wdt_at32ap700x {
  	void __iomem		*regs;
e75e65775   Wim Van Sebroeck   [WATCHDOG] at32ap...
75
  	spinlock_t		io_lock;
a9cb3959a   Hans-Christian Egtvedt   [WATCHDOG] Watchd...
76
  	int			timeout;
bb133450e   Hans-Christian Egtvedt   [WATCHDOG] at32ap...
77
  	int			boot_status;
7e2a1498a   Wim Van Sebroeck   [WATCHDOG] at32ap...
78
  	unsigned long		users;
a9cb3959a   Hans-Christian Egtvedt   [WATCHDOG] Watchd...
79
80
81
82
  	struct miscdevice	miscdev;
  };
  
  static struct wdt_at32ap700x *wdt;
28401140a   Wim Van Sebroeck   [WATCHDOG] at32ap...
83
  static char expect_release;
a9cb3959a   Hans-Christian Egtvedt   [WATCHDOG] Watchd...
84
85
86
87
  
  /*
   * Disable the watchdog.
   */
c0ead7e0f   Wim Van Sebroeck   [WATCHDOG] at32ap...
88
  static inline void at32_wdt_stop(void)
a9cb3959a   Hans-Christian Egtvedt   [WATCHDOG] Watchd...
89
  {
7e2a1498a   Wim Van Sebroeck   [WATCHDOG] at32ap...
90
  	unsigned long psel;
e75e65775   Wim Van Sebroeck   [WATCHDOG] at32ap...
91
  	spin_lock(&wdt->io_lock);
7e2a1498a   Wim Van Sebroeck   [WATCHDOG] at32ap...
92
  	psel = wdt_readl(wdt, CTRL) & WDT_BF(CTRL_PSEL, 0x0f);
a9cb3959a   Hans-Christian Egtvedt   [WATCHDOG] Watchd...
93
94
  	wdt_writel(wdt, CTRL, psel | WDT_BF(CTRL_KEY, 0x55));
  	wdt_writel(wdt, CTRL, psel | WDT_BF(CTRL_KEY, 0xaa));
e75e65775   Wim Van Sebroeck   [WATCHDOG] at32ap...
95
  	spin_unlock(&wdt->io_lock);
a9cb3959a   Hans-Christian Egtvedt   [WATCHDOG] Watchd...
96
97
98
99
100
  }
  
  /*
   * Enable and reset the watchdog.
   */
c0ead7e0f   Wim Van Sebroeck   [WATCHDOG] at32ap...
101
  static inline void at32_wdt_start(void)
a9cb3959a   Hans-Christian Egtvedt   [WATCHDOG] Watchd...
102
103
104
  {
  	/* 0xf is 2^16 divider = 2 sec, 0xe is 2^15 divider = 1 sec */
  	unsigned long psel = (wdt->timeout > 1) ? 0xf : 0xe;
e75e65775   Wim Van Sebroeck   [WATCHDOG] at32ap...
105
  	spin_lock(&wdt->io_lock);
a9cb3959a   Hans-Christian Egtvedt   [WATCHDOG] Watchd...
106
107
108
109
110
111
  	wdt_writel(wdt, CTRL, WDT_BIT(CTRL_EN)
  			| WDT_BF(CTRL_PSEL, psel)
  			| WDT_BF(CTRL_KEY, 0x55));
  	wdt_writel(wdt, CTRL, WDT_BIT(CTRL_EN)
  			| WDT_BF(CTRL_PSEL, psel)
  			| WDT_BF(CTRL_KEY, 0xaa));
e75e65775   Wim Van Sebroeck   [WATCHDOG] at32ap...
112
  	spin_unlock(&wdt->io_lock);
a9cb3959a   Hans-Christian Egtvedt   [WATCHDOG] Watchd...
113
114
115
116
117
  }
  
  /*
   * Pat the watchdog timer.
   */
c0ead7e0f   Wim Van Sebroeck   [WATCHDOG] at32ap...
118
  static inline void at32_wdt_pat(void)
a9cb3959a   Hans-Christian Egtvedt   [WATCHDOG] Watchd...
119
  {
e75e65775   Wim Van Sebroeck   [WATCHDOG] at32ap...
120
  	spin_lock(&wdt->io_lock);
a9cb3959a   Hans-Christian Egtvedt   [WATCHDOG] Watchd...
121
  	wdt_writel(wdt, CLR, 0x42);
e75e65775   Wim Van Sebroeck   [WATCHDOG] at32ap...
122
  	spin_unlock(&wdt->io_lock);
a9cb3959a   Hans-Christian Egtvedt   [WATCHDOG] Watchd...
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
  }
  
  /*
   * Watchdog device is opened, and watchdog starts running.
   */
  static int at32_wdt_open(struct inode *inode, struct file *file)
  {
  	if (test_and_set_bit(1, &wdt->users))
  		return -EBUSY;
  
  	at32_wdt_start();
  	return nonseekable_open(inode, file);
  }
  
  /*
28401140a   Wim Van Sebroeck   [WATCHDOG] at32ap...
138
   * Close the watchdog device.
a9cb3959a   Hans-Christian Egtvedt   [WATCHDOG] Watchd...
139
140
141
   */
  static int at32_wdt_close(struct inode *inode, struct file *file)
  {
28401140a   Wim Van Sebroeck   [WATCHDOG] at32ap...
142
143
144
145
  	if (expect_release == 42) {
  		at32_wdt_stop();
  	} else {
  		dev_dbg(wdt->miscdev.parent,
bb133450e   Hans-Christian Egtvedt   [WATCHDOG] at32ap...
146
147
  			"unexpected close, not stopping watchdog!
  ");
28401140a   Wim Van Sebroeck   [WATCHDOG] at32ap...
148
149
  		at32_wdt_pat();
  	}
a9cb3959a   Hans-Christian Egtvedt   [WATCHDOG] Watchd...
150
  	clear_bit(1, &wdt->users);
28401140a   Wim Van Sebroeck   [WATCHDOG] at32ap...
151
  	expect_release = 0;
a9cb3959a   Hans-Christian Egtvedt   [WATCHDOG] Watchd...
152
153
154
155
156
157
158
159
160
161
162
163
164
165
  	return 0;
  }
  
  /*
   * Change the watchdog time interval.
   */
  static int at32_wdt_settimeout(int time)
  {
  	/*
  	 * All counting occurs at 1 / SLOW_CLOCK (32 kHz) and max prescaler is
  	 * 2 ^ 16 allowing up to 2 seconds timeout.
  	 */
  	if ((time < TIMEOUT_MIN) || (time > TIMEOUT_MAX))
  		return -EINVAL;
c37f27132   Andrew Morton   [WATCHDOG] watchd...
166
167
168
169
  	/*
  	 * Set new watchdog time. It will be used when at32_wdt_start() is
  	 * called.
  	 */
a9cb3959a   Hans-Christian Egtvedt   [WATCHDOG] Watchd...
170
171
172
  	wdt->timeout = time;
  	return 0;
  }
bb133450e   Hans-Christian Egtvedt   [WATCHDOG] at32ap...
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
  /*
   * Get the watchdog status.
   */
  static int at32_wdt_get_status(void)
  {
  	int rcause;
  	int status = 0;
  
  	rcause = wdt_readl(wdt, RCAUSE);
  
  	switch (rcause) {
  	case WDT_BIT(RCAUSE_EXT):
  		status = WDIOF_EXTERN1;
  		break;
  	case WDT_BIT(RCAUSE_WDT):
  		status = WDIOF_CARDRESET;
  		break;
  	case WDT_BIT(RCAUSE_POR):  /* fall through */
  	case WDT_BIT(RCAUSE_JTAG): /* fall through */
  	case WDT_BIT(RCAUSE_SERP): /* fall through */
  	default:
  		break;
  	}
  
  	return status;
  }
42747d712   Wim Van Sebroeck   [WATCHDOG] watchd...
199
  static const struct watchdog_info at32_wdt_info = {
a9cb3959a   Hans-Christian Egtvedt   [WATCHDOG] Watchd...
200
  	.identity	= "at32ap700x watchdog",
28401140a   Wim Van Sebroeck   [WATCHDOG] at32ap...
201
202
203
  	.options	= WDIOF_SETTIMEOUT |
  			  WDIOF_KEEPALIVEPING |
  			  WDIOF_MAGICCLOSE,
a9cb3959a   Hans-Christian Egtvedt   [WATCHDOG] Watchd...
204
205
206
207
208
  };
  
  /*
   * Handle commands from user-space.
   */
a6be8e5ff   Alan Cox   [WATCHDOG 05/57] ...
209
210
  static long at32_wdt_ioctl(struct file *file,
  				unsigned int cmd, unsigned long arg)
a9cb3959a   Hans-Christian Egtvedt   [WATCHDOG] Watchd...
211
212
213
214
215
  {
  	int ret = -ENOTTY;
  	int time;
  	void __user *argp = (void __user *)arg;
  	int __user *p = argp;
c37f27132   Andrew Morton   [WATCHDOG] watchd...
216
  	switch (cmd) {
a9cb3959a   Hans-Christian Egtvedt   [WATCHDOG] Watchd...
217
218
219
220
  	case WDIOC_GETSUPPORT:
  		ret = copy_to_user(argp, &at32_wdt_info,
  				sizeof(at32_wdt_info)) ? -EFAULT : 0;
  		break;
bb133450e   Hans-Christian Egtvedt   [WATCHDOG] at32ap...
221
  	case WDIOC_GETSTATUS:
a9cb3959a   Hans-Christian Egtvedt   [WATCHDOG] Watchd...
222
223
  		ret = put_user(0, p);
  		break;
bb133450e   Hans-Christian Egtvedt   [WATCHDOG] at32ap...
224
225
226
  	case WDIOC_GETBOOTSTATUS:
  		ret = put_user(wdt->boot_status, p);
  		break;
a9cb3959a   Hans-Christian Egtvedt   [WATCHDOG] Watchd...
227
228
229
230
231
232
233
234
235
236
  	case WDIOC_SETOPTIONS:
  		ret = get_user(time, p);
  		if (ret)
  			break;
  		if (time & WDIOS_DISABLECARD)
  			at32_wdt_stop();
  		if (time & WDIOS_ENABLECARD)
  			at32_wdt_start();
  		ret = 0;
  		break;
0c06090c9   Wim Van Sebroeck   [WATCHDOG] Coding...
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
  	case WDIOC_KEEPALIVE:
  		at32_wdt_pat();
  		ret = 0;
  		break;
  	case WDIOC_SETTIMEOUT:
  		ret = get_user(time, p);
  		if (ret)
  			break;
  		ret = at32_wdt_settimeout(time);
  		if (ret)
  			break;
  		/* Enable new time value */
  		at32_wdt_start();
  		/* fall through */
  	case WDIOC_GETTIMEOUT:
  		ret = put_user(wdt->timeout, p);
  		break;
a9cb3959a   Hans-Christian Egtvedt   [WATCHDOG] Watchd...
254
255
256
257
  	}
  
  	return ret;
  }
28401140a   Wim Van Sebroeck   [WATCHDOG] at32ap...
258
259
  static ssize_t at32_wdt_write(struct file *file, const char __user *data,
  				size_t len, loff_t *ppos)
a9cb3959a   Hans-Christian Egtvedt   [WATCHDOG] Watchd...
260
  {
28401140a   Wim Van Sebroeck   [WATCHDOG] at32ap...
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
  	/* See if we got the magic character 'V' and reload the timer */
  	if (len) {
  		if (!nowayout) {
  			size_t i;
  
  			/*
  			 * note: just in case someone wrote the magic
  			 * character five months ago...
  			 */
  			expect_release = 0;
  
  			/*
  			 * scan to see whether or not we got the magic
  			 * character
  			 */
  			for (i = 0; i != len; i++) {
  				char c;
7944d3a5a   Wim Van Sebroeck   [WATCHDOG] more c...
278
  				if (get_user(c, data + i))
28401140a   Wim Van Sebroeck   [WATCHDOG] at32ap...
279
280
281
282
283
284
285
286
  					return -EFAULT;
  				if (c == 'V')
  					expect_release = 42;
  			}
  		}
  		/* someone wrote to us, we should pat the watchdog */
  		at32_wdt_pat();
  	}
a9cb3959a   Hans-Christian Egtvedt   [WATCHDOG] Watchd...
287
288
289
290
291
292
  	return len;
  }
  
  static const struct file_operations at32_wdt_fops = {
  	.owner		= THIS_MODULE,
  	.llseek		= no_llseek,
a6be8e5ff   Alan Cox   [WATCHDOG 05/57] ...
293
  	.unlocked_ioctl	= at32_wdt_ioctl,
a9cb3959a   Hans-Christian Egtvedt   [WATCHDOG] Watchd...
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
  	.open		= at32_wdt_open,
  	.release	= at32_wdt_close,
  	.write		= at32_wdt_write,
  };
  
  static int __init at32_wdt_probe(struct platform_device *pdev)
  {
  	struct resource	*regs;
  	int ret;
  
  	if (wdt) {
  		dev_dbg(&pdev->dev, "only 1 wdt instance supported.
  ");
  		return -EBUSY;
  	}
  
  	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  	if (!regs) {
  		dev_dbg(&pdev->dev, "missing mmio resource
  ");
  		return -ENXIO;
  	}
  
  	wdt = kzalloc(sizeof(struct wdt_at32ap700x), GFP_KERNEL);
  	if (!wdt) {
  		dev_dbg(&pdev->dev, "no memory for wdt structure
  ");
  		return -ENOMEM;
  	}
b782a5637   H Hartley Sweeten   [WATCHDOG] use re...
323
  	wdt->regs = ioremap(regs->start, resource_size(regs));
47d17763e   Hans-Christian Egtvedt   [WATCHDOG] at32ap...
324
325
326
327
328
329
  	if (!wdt->regs) {
  		ret = -ENOMEM;
  		dev_dbg(&pdev->dev, "could not map I/O memory
  ");
  		goto err_free;
  	}
bb133450e   Hans-Christian Egtvedt   [WATCHDOG] at32ap...
330

e75e65775   Wim Van Sebroeck   [WATCHDOG] at32ap...
331
  	spin_lock_init(&wdt->io_lock);
bb133450e   Hans-Christian Egtvedt   [WATCHDOG] at32ap...
332
333
334
335
336
337
338
339
340
341
342
343
  	wdt->boot_status = at32_wdt_get_status();
  
  	/* Work-around for watchdog silicon errata. */
  	if (wdt->boot_status & WDIOF_CARDRESET) {
  		dev_info(&pdev->dev, "CPU must be reset with external "
  				"reset or POR due to silicon errata.
  ");
  		ret = -EIO;
  		goto err_iounmap;
  	} else {
  		wdt->users = 0;
  	}
f1f5bda4e   Hans-Christian Egtvedt   watchdog: at32ap7...
344
345
346
347
348
349
350
  
  	wdt->miscdev.minor	= WATCHDOG_MINOR;
  	wdt->miscdev.name	= "watchdog";
  	wdt->miscdev.fops	= &at32_wdt_fops;
  	wdt->miscdev.parent	= &pdev->dev;
  
  	platform_set_drvdata(pdev, wdt);
a9cb3959a   Hans-Christian Egtvedt   [WATCHDOG] Watchd...
351

726c9f611   Wim Van Sebroeck   [WATCHDOG] at32ap...
352
353
  	if (at32_wdt_settimeout(timeout)) {
  		at32_wdt_settimeout(TIMEOUT_DEFAULT);
a9cb3959a   Hans-Christian Egtvedt   [WATCHDOG] Watchd...
354
355
356
  		dev_dbg(&pdev->dev,
  			"default timeout invalid, set to %d sec.
  ",
726c9f611   Wim Van Sebroeck   [WATCHDOG] at32ap...
357
  			TIMEOUT_DEFAULT);
a9cb3959a   Hans-Christian Egtvedt   [WATCHDOG] Watchd...
358
359
360
361
362
363
  	}
  
  	ret = misc_register(&wdt->miscdev);
  	if (ret) {
  		dev_dbg(&pdev->dev, "failed to register wdt miscdev
  ");
f1f5bda4e   Hans-Christian Egtvedt   watchdog: at32ap7...
364
  		goto err_register;
a9cb3959a   Hans-Christian Egtvedt   [WATCHDOG] Watchd...
365
  	}
28401140a   Wim Van Sebroeck   [WATCHDOG] at32ap...
366
367
368
369
  	dev_info(&pdev->dev,
  		"AT32AP700X WDT at 0x%p, timeout %d sec (nowayout=%d)
  ",
  		wdt->regs, wdt->timeout, nowayout);
a9cb3959a   Hans-Christian Egtvedt   [WATCHDOG] Watchd...
370
371
  
  	return 0;
f1f5bda4e   Hans-Christian Egtvedt   watchdog: at32ap7...
372
373
  err_register:
  	platform_set_drvdata(pdev, NULL);
47d17763e   Hans-Christian Egtvedt   [WATCHDOG] at32ap...
374
375
376
  err_iounmap:
  	iounmap(wdt->regs);
  err_free:
a9cb3959a   Hans-Christian Egtvedt   [WATCHDOG] Watchd...
377
378
379
380
381
382
383
384
  	kfree(wdt);
  	wdt = NULL;
  	return ret;
  }
  
  static int __exit at32_wdt_remove(struct platform_device *pdev)
  {
  	if (wdt && platform_get_drvdata(pdev) == wdt) {
28401140a   Wim Van Sebroeck   [WATCHDOG] at32ap...
385
386
387
  		/* Stop the timer before we leave */
  		if (!nowayout)
  			at32_wdt_stop();
a9cb3959a   Hans-Christian Egtvedt   [WATCHDOG] Watchd...
388
  		misc_deregister(&wdt->miscdev);
ff7323161   Hans-Christian Egtvedt   [WATCHDOG] at32ap...
389
  		iounmap(wdt->regs);
a9cb3959a   Hans-Christian Egtvedt   [WATCHDOG] Watchd...
390
391
392
393
  		kfree(wdt);
  		wdt = NULL;
  		platform_set_drvdata(pdev, NULL);
  	}
a9cb3959a   Hans-Christian Egtvedt   [WATCHDOG] Watchd...
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
  	return 0;
  }
  
  static void at32_wdt_shutdown(struct platform_device *pdev)
  {
  	at32_wdt_stop();
  }
  
  #ifdef CONFIG_PM
  static int at32_wdt_suspend(struct platform_device *pdev, pm_message_t message)
  {
  	at32_wdt_stop();
  	return 0;
  }
  
  static int at32_wdt_resume(struct platform_device *pdev)
  {
  	if (wdt->users)
  		at32_wdt_start();
  	return 0;
  }
97a2a2ea1   Andrew Morton   [WATCHDOG] watchd...
415
416
417
  #else
  #define at32_wdt_suspend NULL
  #define at32_wdt_resume NULL
a9cb3959a   Hans-Christian Egtvedt   [WATCHDOG] Watchd...
418
  #endif
f37d193c7   Kay Sievers   watchdog: fix pla...
419
420
  /* work with hotplug and coldplug */
  MODULE_ALIAS("platform:at32_wdt");
a9cb3959a   Hans-Christian Egtvedt   [WATCHDOG] Watchd...
421
422
  static struct platform_driver at32_wdt_driver = {
  	.remove		= __exit_p(at32_wdt_remove),
a9cb3959a   Hans-Christian Egtvedt   [WATCHDOG] Watchd...
423
424
  	.suspend	= at32_wdt_suspend,
  	.resume		= at32_wdt_resume,
a9cb3959a   Hans-Christian Egtvedt   [WATCHDOG] Watchd...
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
  	.driver		= {
  		.name	= "at32_wdt",
  		.owner	= THIS_MODULE,
  	},
  	.shutdown	= at32_wdt_shutdown,
  };
  
  static int __init at32_wdt_init(void)
  {
  	return platform_driver_probe(&at32_wdt_driver, at32_wdt_probe);
  }
  module_init(at32_wdt_init);
  
  static void __exit at32_wdt_exit(void)
  {
  	platform_driver_unregister(&at32_wdt_driver);
  }
  module_exit(at32_wdt_exit);
aeb0aea14   Hans-Christian Egtvedt   watchdog: update ...
443
  MODULE_AUTHOR("Hans-Christian Egtvedt <egtvedt@samfundet.no>");
a9cb3959a   Hans-Christian Egtvedt   [WATCHDOG] Watchd...
444
445
446
  MODULE_DESCRIPTION("Watchdog driver for Atmel AT32AP700X");
  MODULE_LICENSE("GPL");
  MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);