1d0173278SGuenter Roeck // SPDX-License-Identifier: GPL-2.0+
2b7e04f8cSWim Van Sebroeck /*
3b7e04f8cSWim Van Sebroeck * IB700 Single Board Computer WDT driver
4b7e04f8cSWim Van Sebroeck *
5b7e04f8cSWim Van Sebroeck * (c) Copyright 2001 Charles Howes <chowes@vsol.net>
6b7e04f8cSWim Van Sebroeck *
7b7e04f8cSWim Van Sebroeck * Based on advantechwdt.c which is based on acquirewdt.c which
8b7e04f8cSWim Van Sebroeck * is based on wdt.c.
9b7e04f8cSWim Van Sebroeck *
10b7e04f8cSWim Van Sebroeck * (c) Copyright 2000-2001 Marek Michalkiewicz <marekm@linux.org.pl>
11b7e04f8cSWim Van Sebroeck *
12b7e04f8cSWim Van Sebroeck * Based on acquirewdt.c which is based on wdt.c.
13b7e04f8cSWim Van Sebroeck * Original copyright messages:
14b7e04f8cSWim Van Sebroeck *
1529fa0586SAlan Cox * (c) Copyright 1996 Alan Cox <alan@lxorguk.ukuu.org.uk>,
1629fa0586SAlan Cox * All Rights Reserved.
17b7e04f8cSWim Van Sebroeck *
18b7e04f8cSWim Van Sebroeck * Neither Alan Cox nor CymruNet Ltd. admit liability nor provide
19b7e04f8cSWim Van Sebroeck * warranty for any of this software. This material is provided
20b7e04f8cSWim Van Sebroeck * "AS-IS" and at no charge.
21b7e04f8cSWim Van Sebroeck *
2229fa0586SAlan Cox * (c) Copyright 1995 Alan Cox <alan@lxorguk.ukuu.org.uk>
23b7e04f8cSWim Van Sebroeck *
24b7e04f8cSWim Van Sebroeck * 14-Dec-2001 Matt Domsch <Matt_Domsch@dell.com>
25b7e04f8cSWim Van Sebroeck * Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
26b7e04f8cSWim Van Sebroeck * Added timeout module option to override default
27b7e04f8cSWim Van Sebroeck *
28b7e04f8cSWim Van Sebroeck */
29b7e04f8cSWim Van Sebroeck
3027c766aaSJoe Perches #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
3127c766aaSJoe Perches
32b7e04f8cSWim Van Sebroeck #include <linux/module.h>
33b7e04f8cSWim Van Sebroeck #include <linux/types.h>
34b7e04f8cSWim Van Sebroeck #include <linux/miscdevice.h>
35b7e04f8cSWim Van Sebroeck #include <linux/watchdog.h>
36b7e04f8cSWim Van Sebroeck #include <linux/ioport.h>
37b7e04f8cSWim Van Sebroeck #include <linux/fs.h>
38b7e04f8cSWim Van Sebroeck #include <linux/init.h>
39b7e04f8cSWim Van Sebroeck #include <linux/spinlock.h>
40b7e04f8cSWim Van Sebroeck #include <linux/moduleparam.h>
41b7e04f8cSWim Van Sebroeck #include <linux/platform_device.h>
422e43ba73SAlan Cox #include <linux/io.h>
432e43ba73SAlan Cox #include <linux/uaccess.h>
44089ab079SWim Van Sebroeck
45b7e04f8cSWim Van Sebroeck
46b7e04f8cSWim Van Sebroeck static struct platform_device *ibwdt_platform_device;
47b7e04f8cSWim Van Sebroeck static unsigned long ibwdt_is_open;
48c7dfd0ccSAlexey Dobriyan static DEFINE_SPINLOCK(ibwdt_lock);
49b7e04f8cSWim Van Sebroeck static char expect_close;
50b7e04f8cSWim Van Sebroeck
51b7e04f8cSWim Van Sebroeck /* Module information */
52b7e04f8cSWim Van Sebroeck #define DRV_NAME "ib700wdt"
53b7e04f8cSWim Van Sebroeck
54b7e04f8cSWim Van Sebroeck /*
55b7e04f8cSWim Van Sebroeck *
56b7e04f8cSWim Van Sebroeck * Watchdog Timer Configuration
57b7e04f8cSWim Van Sebroeck *
58b7e04f8cSWim Van Sebroeck * The function of the watchdog timer is to reset the system
59b7e04f8cSWim Van Sebroeck * automatically and is defined at I/O port 0443H. To enable the
60b7e04f8cSWim Van Sebroeck * watchdog timer and allow the system to reset, write I/O port 0443H.
61b7e04f8cSWim Van Sebroeck * To disable the timer, write I/O port 0441H for the system to stop the
62b7e04f8cSWim Van Sebroeck * watchdog function. The timer has a tolerance of 20% for its
63b7e04f8cSWim Van Sebroeck * intervals.
64b7e04f8cSWim Van Sebroeck *
65b7e04f8cSWim Van Sebroeck * The following describes how the timer should be programmed.
66b7e04f8cSWim Van Sebroeck *
67b7e04f8cSWim Van Sebroeck * Enabling Watchdog:
68b7e04f8cSWim Van Sebroeck * MOV AX,000FH (Choose the values from 0 to F)
69b7e04f8cSWim Van Sebroeck * MOV DX,0443H
70b7e04f8cSWim Van Sebroeck * OUT DX,AX
71b7e04f8cSWim Van Sebroeck *
72b7e04f8cSWim Van Sebroeck * Disabling Watchdog:
73b7e04f8cSWim Van Sebroeck * MOV AX,000FH (Any value is fine.)
74b7e04f8cSWim Van Sebroeck * MOV DX,0441H
75b7e04f8cSWim Van Sebroeck * OUT DX,AX
76b7e04f8cSWim Van Sebroeck *
77b7e04f8cSWim Van Sebroeck * Watchdog timer control table:
78b7e04f8cSWim Van Sebroeck * Level Value Time/sec | Level Value Time/sec
79b7e04f8cSWim Van Sebroeck * 1 F 0 | 9 7 16
80b7e04f8cSWim Van Sebroeck * 2 E 2 | 10 6 18
81b7e04f8cSWim Van Sebroeck * 3 D 4 | 11 5 20
82b7e04f8cSWim Van Sebroeck * 4 C 6 | 12 4 22
83b7e04f8cSWim Van Sebroeck * 5 B 8 | 13 3 24
84b7e04f8cSWim Van Sebroeck * 6 A 10 | 14 2 26
85b7e04f8cSWim Van Sebroeck * 7 9 12 | 15 1 28
86b7e04f8cSWim Van Sebroeck * 8 8 14 | 16 0 30
87b7e04f8cSWim Van Sebroeck *
88b7e04f8cSWim Van Sebroeck */
89b7e04f8cSWim Van Sebroeck
90b7e04f8cSWim Van Sebroeck #define WDT_STOP 0x441
91b7e04f8cSWim Van Sebroeck #define WDT_START 0x443
92b7e04f8cSWim Van Sebroeck
93b7e04f8cSWim Van Sebroeck /* Default timeout */
94794db26fSWim Van Sebroeck #define WATCHDOG_TIMEOUT 30 /* 30 seconds +/- 20% */
95794db26fSWim Van Sebroeck static int timeout = WATCHDOG_TIMEOUT; /* in seconds */
96794db26fSWim Van Sebroeck module_param(timeout, int, 0);
97794db26fSWim Van Sebroeck MODULE_PARM_DESC(timeout,
98794db26fSWim Van Sebroeck "Watchdog timeout in seconds. 0<= timeout <=30, default="
99794db26fSWim Van Sebroeck __MODULE_STRING(WATCHDOG_TIMEOUT) ".");
100b7e04f8cSWim Van Sebroeck
10186a1e189SWim Van Sebroeck static bool nowayout = WATCHDOG_NOWAYOUT;
10286a1e189SWim Van Sebroeck module_param(nowayout, bool, 0);
1032e43ba73SAlan Cox MODULE_PARM_DESC(nowayout,
1042e43ba73SAlan Cox "Watchdog cannot be stopped once started (default="
1052e43ba73SAlan Cox __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
106b7e04f8cSWim Van Sebroeck
107b7e04f8cSWim Van Sebroeck
108b7e04f8cSWim Van Sebroeck /*
109b7e04f8cSWim Van Sebroeck * Watchdog Operations
110b7e04f8cSWim Van Sebroeck */
111b7e04f8cSWim Van Sebroeck
ibwdt_ping(void)1127944d3a5SWim Van Sebroeck static void ibwdt_ping(void)
113b7e04f8cSWim Van Sebroeck {
114794db26fSWim Van Sebroeck int wd_margin = 15 - ((timeout + 1) / 2);
115794db26fSWim Van Sebroeck
116b7e04f8cSWim Van Sebroeck spin_lock(&ibwdt_lock);
117b7e04f8cSWim Van Sebroeck
118b7e04f8cSWim Van Sebroeck /* Write a watchdog value */
119b7e04f8cSWim Van Sebroeck outb_p(wd_margin, WDT_START);
120b7e04f8cSWim Van Sebroeck
121b7e04f8cSWim Van Sebroeck spin_unlock(&ibwdt_lock);
122b7e04f8cSWim Van Sebroeck }
123b7e04f8cSWim Van Sebroeck
ibwdt_disable(void)1247944d3a5SWim Van Sebroeck static void ibwdt_disable(void)
125b7e04f8cSWim Van Sebroeck {
126b7e04f8cSWim Van Sebroeck spin_lock(&ibwdt_lock);
127b7e04f8cSWim Van Sebroeck outb_p(0, WDT_STOP);
128b7e04f8cSWim Van Sebroeck spin_unlock(&ibwdt_lock);
129b7e04f8cSWim Van Sebroeck }
130b7e04f8cSWim Van Sebroeck
ibwdt_set_heartbeat(int t)1317944d3a5SWim Van Sebroeck static int ibwdt_set_heartbeat(int t)
132b7e04f8cSWim Van Sebroeck {
133794db26fSWim Van Sebroeck if (t < 0 || t > 30)
134b7e04f8cSWim Van Sebroeck return -EINVAL;
135b7e04f8cSWim Van Sebroeck
136794db26fSWim Van Sebroeck timeout = t;
137b7e04f8cSWim Van Sebroeck return 0;
138b7e04f8cSWim Van Sebroeck }
139b7e04f8cSWim Van Sebroeck
140b7e04f8cSWim Van Sebroeck /*
141b7e04f8cSWim Van Sebroeck * /dev/watchdog handling
142b7e04f8cSWim Van Sebroeck */
143b7e04f8cSWim Van Sebroeck
ibwdt_write(struct file * file,const char __user * buf,size_t count,loff_t * ppos)1442e43ba73SAlan Cox static ssize_t ibwdt_write(struct file *file, const char __user *buf,
1452e43ba73SAlan Cox size_t count, loff_t *ppos)
146b7e04f8cSWim Van Sebroeck {
147b7e04f8cSWim Van Sebroeck if (count) {
148b7e04f8cSWim Van Sebroeck if (!nowayout) {
149b7e04f8cSWim Van Sebroeck size_t i;
150b7e04f8cSWim Van Sebroeck
151b7e04f8cSWim Van Sebroeck /* In case it was set long ago */
152b7e04f8cSWim Van Sebroeck expect_close = 0;
153b7e04f8cSWim Van Sebroeck
154b7e04f8cSWim Van Sebroeck for (i = 0; i != count; i++) {
155b7e04f8cSWim Van Sebroeck char c;
156b7e04f8cSWim Van Sebroeck if (get_user(c, buf + i))
157b7e04f8cSWim Van Sebroeck return -EFAULT;
158b7e04f8cSWim Van Sebroeck if (c == 'V')
159b7e04f8cSWim Van Sebroeck expect_close = 42;
160b7e04f8cSWim Van Sebroeck }
161b7e04f8cSWim Van Sebroeck }
162b7e04f8cSWim Van Sebroeck ibwdt_ping();
163b7e04f8cSWim Van Sebroeck }
164b7e04f8cSWim Van Sebroeck return count;
165b7e04f8cSWim Van Sebroeck }
166b7e04f8cSWim Van Sebroeck
ibwdt_ioctl(struct file * file,unsigned int cmd,unsigned long arg)1672e43ba73SAlan Cox static long ibwdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
168b7e04f8cSWim Van Sebroeck {
169b7e04f8cSWim Van Sebroeck int new_margin;
170b7e04f8cSWim Van Sebroeck void __user *argp = (void __user *)arg;
171b7e04f8cSWim Van Sebroeck int __user *p = argp;
172b7e04f8cSWim Van Sebroeck
17342747d71SWim Van Sebroeck static const struct watchdog_info ident = {
1742e43ba73SAlan Cox .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT
1752e43ba73SAlan Cox | WDIOF_MAGICCLOSE,
176b7e04f8cSWim Van Sebroeck .firmware_version = 1,
177b7e04f8cSWim Van Sebroeck .identity = "IB700 WDT",
178b7e04f8cSWim Van Sebroeck };
179b7e04f8cSWim Van Sebroeck
180b7e04f8cSWim Van Sebroeck switch (cmd) {
181b7e04f8cSWim Van Sebroeck case WDIOC_GETSUPPORT:
182b7e04f8cSWim Van Sebroeck if (copy_to_user(argp, &ident, sizeof(ident)))
183b7e04f8cSWim Van Sebroeck return -EFAULT;
184b7e04f8cSWim Van Sebroeck break;
185b7e04f8cSWim Van Sebroeck
186b7e04f8cSWim Van Sebroeck case WDIOC_GETSTATUS:
187b7e04f8cSWim Van Sebroeck case WDIOC_GETBOOTSTATUS:
188b7e04f8cSWim Van Sebroeck return put_user(0, p);
189b7e04f8cSWim Van Sebroeck
190b7e04f8cSWim Van Sebroeck case WDIOC_SETOPTIONS:
191b7e04f8cSWim Van Sebroeck {
192b7e04f8cSWim Van Sebroeck int options, retval = -EINVAL;
193b7e04f8cSWim Van Sebroeck
194b7e04f8cSWim Van Sebroeck if (get_user(options, p))
195b7e04f8cSWim Van Sebroeck return -EFAULT;
196b7e04f8cSWim Van Sebroeck
197b7e04f8cSWim Van Sebroeck if (options & WDIOS_DISABLECARD) {
198b7e04f8cSWim Van Sebroeck ibwdt_disable();
199b7e04f8cSWim Van Sebroeck retval = 0;
200b7e04f8cSWim Van Sebroeck }
201b7e04f8cSWim Van Sebroeck if (options & WDIOS_ENABLECARD) {
202b7e04f8cSWim Van Sebroeck ibwdt_ping();
203b7e04f8cSWim Van Sebroeck retval = 0;
204b7e04f8cSWim Van Sebroeck }
205b7e04f8cSWim Van Sebroeck return retval;
206b7e04f8cSWim Van Sebroeck }
2070c06090cSWim Van Sebroeck case WDIOC_KEEPALIVE:
2080c06090cSWim Van Sebroeck ibwdt_ping();
2090c06090cSWim Van Sebroeck break;
2100c06090cSWim Van Sebroeck
2110c06090cSWim Van Sebroeck case WDIOC_SETTIMEOUT:
2120c06090cSWim Van Sebroeck if (get_user(new_margin, p))
2130c06090cSWim Van Sebroeck return -EFAULT;
2140c06090cSWim Van Sebroeck if (ibwdt_set_heartbeat(new_margin))
2150c06090cSWim Van Sebroeck return -EINVAL;
2160c06090cSWim Van Sebroeck ibwdt_ping();
217bd490f82SGustavo A. R. Silva fallthrough;
2180c06090cSWim Van Sebroeck
2190c06090cSWim Van Sebroeck case WDIOC_GETTIMEOUT:
220794db26fSWim Van Sebroeck return put_user(timeout, p);
2210c06090cSWim Van Sebroeck
222b7e04f8cSWim Van Sebroeck default:
223b7e04f8cSWim Van Sebroeck return -ENOTTY;
224b7e04f8cSWim Van Sebroeck }
225b7e04f8cSWim Van Sebroeck return 0;
226b7e04f8cSWim Van Sebroeck }
227b7e04f8cSWim Van Sebroeck
ibwdt_open(struct inode * inode,struct file * file)2282e43ba73SAlan Cox static int ibwdt_open(struct inode *inode, struct file *file)
229b7e04f8cSWim Van Sebroeck {
2302e43ba73SAlan Cox if (test_and_set_bit(0, &ibwdt_is_open))
231b7e04f8cSWim Van Sebroeck return -EBUSY;
232b7e04f8cSWim Van Sebroeck if (nowayout)
233b7e04f8cSWim Van Sebroeck __module_get(THIS_MODULE);
234b7e04f8cSWim Van Sebroeck
235b7e04f8cSWim Van Sebroeck /* Activate */
236b7e04f8cSWim Van Sebroeck ibwdt_ping();
237c5bf68feSKirill Smelkov return stream_open(inode, file);
238b7e04f8cSWim Van Sebroeck }
239b7e04f8cSWim Van Sebroeck
ibwdt_close(struct inode * inode,struct file * file)2407944d3a5SWim Van Sebroeck static int ibwdt_close(struct inode *inode, struct file *file)
241b7e04f8cSWim Van Sebroeck {
242b7e04f8cSWim Van Sebroeck if (expect_close == 42) {
243b7e04f8cSWim Van Sebroeck ibwdt_disable();
244b7e04f8cSWim Van Sebroeck } else {
24527c766aaSJoe Perches pr_crit("WDT device closed unexpectedly. WDT will not stop!\n");
246b7e04f8cSWim Van Sebroeck ibwdt_ping();
247b7e04f8cSWim Van Sebroeck }
248b7e04f8cSWim Van Sebroeck clear_bit(0, &ibwdt_is_open);
249b7e04f8cSWim Van Sebroeck expect_close = 0;
250b7e04f8cSWim Van Sebroeck return 0;
251b7e04f8cSWim Van Sebroeck }
252b7e04f8cSWim Van Sebroeck
253b7e04f8cSWim Van Sebroeck /*
254b7e04f8cSWim Van Sebroeck * Kernel Interfaces
255b7e04f8cSWim Van Sebroeck */
256b7e04f8cSWim Van Sebroeck
257b7e04f8cSWim Van Sebroeck static const struct file_operations ibwdt_fops = {
258b7e04f8cSWim Van Sebroeck .owner = THIS_MODULE,
259b7e04f8cSWim Van Sebroeck .llseek = no_llseek,
260b7e04f8cSWim Van Sebroeck .write = ibwdt_write,
2612e43ba73SAlan Cox .unlocked_ioctl = ibwdt_ioctl,
262b6dfb247SArnd Bergmann .compat_ioctl = compat_ptr_ioctl,
263b7e04f8cSWim Van Sebroeck .open = ibwdt_open,
264b7e04f8cSWim Van Sebroeck .release = ibwdt_close,
265b7e04f8cSWim Van Sebroeck };
266b7e04f8cSWim Van Sebroeck
267b7e04f8cSWim Van Sebroeck static struct miscdevice ibwdt_miscdev = {
268b7e04f8cSWim Van Sebroeck .minor = WATCHDOG_MINOR,
269b7e04f8cSWim Van Sebroeck .name = "watchdog",
270b7e04f8cSWim Van Sebroeck .fops = &ibwdt_fops,
271b7e04f8cSWim Van Sebroeck };
272b7e04f8cSWim Van Sebroeck
273b7e04f8cSWim Van Sebroeck /*
274b7e04f8cSWim Van Sebroeck * Init & exit routines
275b7e04f8cSWim Van Sebroeck */
276b7e04f8cSWim Van Sebroeck
ibwdt_probe(struct platform_device * dev)277996735ffSJean Delvare static int __init ibwdt_probe(struct platform_device *dev)
278b7e04f8cSWim Van Sebroeck {
279b7e04f8cSWim Van Sebroeck int res;
280b7e04f8cSWim Van Sebroeck
281b7e04f8cSWim Van Sebroeck #if WDT_START != WDT_STOP
282b7e04f8cSWim Van Sebroeck if (!request_region(WDT_STOP, 1, "IB700 WDT")) {
28327c766aaSJoe Perches pr_err("STOP method I/O %X is not available\n", WDT_STOP);
284b7e04f8cSWim Van Sebroeck res = -EIO;
285b7e04f8cSWim Van Sebroeck goto out_nostopreg;
286b7e04f8cSWim Van Sebroeck }
287b7e04f8cSWim Van Sebroeck #endif
288b7e04f8cSWim Van Sebroeck
289b7e04f8cSWim Van Sebroeck if (!request_region(WDT_START, 1, "IB700 WDT")) {
29027c766aaSJoe Perches pr_err("START method I/O %X is not available\n", WDT_START);
291b7e04f8cSWim Van Sebroeck res = -EIO;
292b7e04f8cSWim Van Sebroeck goto out_nostartreg;
293b7e04f8cSWim Van Sebroeck }
294b7e04f8cSWim Van Sebroeck
295794db26fSWim Van Sebroeck /* Check that the heartbeat value is within it's range ;
296794db26fSWim Van Sebroeck * if not reset to the default */
297794db26fSWim Van Sebroeck if (ibwdt_set_heartbeat(timeout)) {
298794db26fSWim Van Sebroeck ibwdt_set_heartbeat(WATCHDOG_TIMEOUT);
29927c766aaSJoe Perches pr_info("timeout value must be 0<=x<=30, using %d\n", timeout);
300794db26fSWim Van Sebroeck }
301794db26fSWim Van Sebroeck
302b7e04f8cSWim Van Sebroeck res = misc_register(&ibwdt_miscdev);
303b7e04f8cSWim Van Sebroeck if (res) {
30427c766aaSJoe Perches pr_err("failed to register misc device\n");
305b7e04f8cSWim Van Sebroeck goto out_nomisc;
306b7e04f8cSWim Van Sebroeck }
307b7e04f8cSWim Van Sebroeck return 0;
308b7e04f8cSWim Van Sebroeck
309b7e04f8cSWim Van Sebroeck out_nomisc:
310b7e04f8cSWim Van Sebroeck release_region(WDT_START, 1);
311b7e04f8cSWim Van Sebroeck out_nostartreg:
312b7e04f8cSWim Van Sebroeck #if WDT_START != WDT_STOP
313b7e04f8cSWim Van Sebroeck release_region(WDT_STOP, 1);
314b7e04f8cSWim Van Sebroeck #endif
315b7e04f8cSWim Van Sebroeck out_nostopreg:
316b7e04f8cSWim Van Sebroeck return res;
317b7e04f8cSWim Van Sebroeck }
318b7e04f8cSWim Van Sebroeck
ibwdt_remove(struct platform_device * dev)319*40529e7eSUwe Kleine-König static void ibwdt_remove(struct platform_device *dev)
320b7e04f8cSWim Van Sebroeck {
321b7e04f8cSWim Van Sebroeck misc_deregister(&ibwdt_miscdev);
322b7e04f8cSWim Van Sebroeck release_region(WDT_START, 1);
323b7e04f8cSWim Van Sebroeck #if WDT_START != WDT_STOP
324b7e04f8cSWim Van Sebroeck release_region(WDT_STOP, 1);
325b7e04f8cSWim Van Sebroeck #endif
326b7e04f8cSWim Van Sebroeck }
327b7e04f8cSWim Van Sebroeck
ibwdt_shutdown(struct platform_device * dev)328b7e04f8cSWim Van Sebroeck static void ibwdt_shutdown(struct platform_device *dev)
329b7e04f8cSWim Van Sebroeck {
330b7e04f8cSWim Van Sebroeck /* Turn the WDT off if we have a soft shutdown */
331b7e04f8cSWim Van Sebroeck ibwdt_disable();
332b7e04f8cSWim Van Sebroeck }
333b7e04f8cSWim Van Sebroeck
334b7e04f8cSWim Van Sebroeck static struct platform_driver ibwdt_driver = {
335*40529e7eSUwe Kleine-König .remove_new = ibwdt_remove,
336b7e04f8cSWim Van Sebroeck .shutdown = ibwdt_shutdown,
337b7e04f8cSWim Van Sebroeck .driver = {
338b7e04f8cSWim Van Sebroeck .name = DRV_NAME,
339b7e04f8cSWim Van Sebroeck },
340b7e04f8cSWim Van Sebroeck };
341b7e04f8cSWim Van Sebroeck
ibwdt_init(void)342b7e04f8cSWim Van Sebroeck static int __init ibwdt_init(void)
343b7e04f8cSWim Van Sebroeck {
344b7e04f8cSWim Van Sebroeck int err;
345b7e04f8cSWim Van Sebroeck
34627c766aaSJoe Perches pr_info("WDT driver for IB700 single board computer initialising\n");
347b7e04f8cSWim Van Sebroeck
3482e43ba73SAlan Cox ibwdt_platform_device = platform_device_register_simple(DRV_NAME,
3492e43ba73SAlan Cox -1, NULL, 0);
350996735ffSJean Delvare if (IS_ERR(ibwdt_platform_device))
351996735ffSJean Delvare return PTR_ERR(ibwdt_platform_device);
352996735ffSJean Delvare
353996735ffSJean Delvare err = platform_driver_probe(&ibwdt_driver, ibwdt_probe);
354996735ffSJean Delvare if (err)
355996735ffSJean Delvare goto unreg_platform_device;
356b7e04f8cSWim Van Sebroeck
357b7e04f8cSWim Van Sebroeck return 0;
358b7e04f8cSWim Van Sebroeck
359996735ffSJean Delvare unreg_platform_device:
360996735ffSJean Delvare platform_device_unregister(ibwdt_platform_device);
361b7e04f8cSWim Van Sebroeck return err;
362b7e04f8cSWim Van Sebroeck }
363b7e04f8cSWim Van Sebroeck
ibwdt_exit(void)364b7e04f8cSWim Van Sebroeck static void __exit ibwdt_exit(void)
365b7e04f8cSWim Van Sebroeck {
366b7e04f8cSWim Van Sebroeck platform_device_unregister(ibwdt_platform_device);
367b7e04f8cSWim Van Sebroeck platform_driver_unregister(&ibwdt_driver);
36827c766aaSJoe Perches pr_info("Watchdog Module Unloaded\n");
369b7e04f8cSWim Van Sebroeck }
370b7e04f8cSWim Van Sebroeck
371b7e04f8cSWim Van Sebroeck module_init(ibwdt_init);
372b7e04f8cSWim Van Sebroeck module_exit(ibwdt_exit);
373b7e04f8cSWim Van Sebroeck
374b7e04f8cSWim Van Sebroeck MODULE_AUTHOR("Charles Howes <chowes@vsol.net>");
375b7e04f8cSWim Van Sebroeck MODULE_DESCRIPTION("IB700 SBC watchdog driver");
376b7e04f8cSWim Van Sebroeck MODULE_LICENSE("GPL");
377b7e04f8cSWim Van Sebroeck
378b7e04f8cSWim Van Sebroeck /* end of ib700wdt.c */
379