Blame view

drivers/watchdog/sbc_epx_c3.c 5.13 KB
eed6565f7   Calin A. Culianu   [PATCH] Watchdog:...
1
2
3
4
5
6
7
8
9
10
11
12
  /*
   *	SBC EPX C3 0.1	A Hardware Watchdog Device for the Winsystems EPX-C3
   *	single board computer
   *
   *	(c) Copyright 2006 Calin A. Culianu <calin@ajvar.org>, All Rights
   *	Reserved.
   *
   *	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.
   *
29fa0586d   Alan Cox   [PATCH] Switch al...
13
   *	based on softdog.c by Alan Cox <alan@lxorguk.ukuu.org.uk>
eed6565f7   Calin A. Culianu   [PATCH] Watchdog:...
14
15
16
17
   */
  
  #include <linux/module.h>
  #include <linux/moduleparam.h>
eed6565f7   Calin A. Culianu   [PATCH] Watchdog:...
18
19
20
21
22
23
24
25
26
  #include <linux/types.h>
  #include <linux/kernel.h>
  #include <linux/fs.h>
  #include <linux/mm.h>
  #include <linux/miscdevice.h>
  #include <linux/watchdog.h>
  #include <linux/notifier.h>
  #include <linux/reboot.h>
  #include <linux/init.h>
de6c642ca   Alan Cox   [PATCH] SBC EPX d...
27
  #include <linux/ioport.h>
f4f6f65a5   Alan Cox   [WATCHDOG 40/57] ...
28
29
  #include <linux/uaccess.h>
  #include <linux/io.h>
eed6565f7   Calin A. Culianu   [PATCH] Watchdog:...
30
31
32
33
34
35
36
37
  
  #define PFX "epx_c3: "
  static int epx_c3_alive;
  
  #define WATCHDOG_TIMEOUT 1		/* 1 sec default timeout */
  
  static int nowayout = WATCHDOG_NOWAYOUT;
  module_param(nowayout, int, 0);
143a2e54b   Wim Van Sebroeck   [WATCHDOG] More c...
38
39
  MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
  					__MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
eed6565f7   Calin A. Culianu   [PATCH] Watchdog:...
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
  
  #define EPXC3_WATCHDOG_CTL_REG 0x1ee /* write 1 to enable, 0 to disable */
  #define EPXC3_WATCHDOG_PET_REG 0x1ef /* write anything to pet once enabled */
  
  static void epx_c3_start(void)
  {
  	outb(1, EPXC3_WATCHDOG_CTL_REG);
  }
  
  static void epx_c3_stop(void)
  {
  
  	outb(0, EPXC3_WATCHDOG_CTL_REG);
  
  	printk(KERN_INFO PFX "Stopped watchdog timer.
  ");
  }
  
  static void epx_c3_pet(void)
  {
  	outb(1, EPXC3_WATCHDOG_PET_REG);
  }
  
  /*
   *	Allow only one person to hold it open
   */
  static int epx_c3_open(struct inode *inode, struct file *file)
  {
  	if (epx_c3_alive)
  		return -EBUSY;
  
  	if (nowayout)
  		__module_get(THIS_MODULE);
  
  	/* Activate timer */
  	epx_c3_start();
  	epx_c3_pet();
  
  	epx_c3_alive = 1;
  	printk(KERN_INFO "Started watchdog timer.
  ");
  
  	return nonseekable_open(inode, file);
  }
  
  static int epx_c3_release(struct inode *inode, struct file *file)
  {
  	/* Shut off the timer.
  	 * Lock it in if it's a module and we defined ...NOWAYOUT */
  	if (!nowayout)
  		epx_c3_stop();		/* Turn the WDT off */
  
  	epx_c3_alive = 0;
  
  	return 0;
  }
73a09e626   Al Viro   [PATCH] drivers/c...
96
  static ssize_t epx_c3_write(struct file *file, const char __user *data,
eed6565f7   Calin A. Culianu   [PATCH] Watchdog:...
97
98
99
100
101
102
103
  			size_t len, loff_t *ppos)
  {
  	/* Refresh the timer. */
  	if (len)
  		epx_c3_pet();
  	return len;
  }
f4f6f65a5   Alan Cox   [WATCHDOG 40/57] ...
104
105
  static long epx_c3_ioctl(struct file *file, unsigned int cmd,
  						unsigned long arg)
eed6565f7   Calin A. Culianu   [PATCH] Watchdog:...
106
107
  {
  	int options, retval = -EINVAL;
73a09e626   Al Viro   [PATCH] drivers/c...
108
  	int __user *argp = (void __user *)arg;
f4f6f65a5   Alan Cox   [WATCHDOG 40/57] ...
109
  	static const struct watchdog_info ident = {
e73a78027   Wim Van Sebroeck   [WATCHDOG] Correc...
110
  		.options		= WDIOF_KEEPALIVEPING,
eed6565f7   Calin A. Culianu   [PATCH] Watchdog:...
111
112
113
114
115
116
  		.firmware_version	= 0,
  		.identity		= "Winsystems EPX-C3 H/W Watchdog",
  	};
  
  	switch (cmd) {
  	case WDIOC_GETSUPPORT:
73a09e626   Al Viro   [PATCH] drivers/c...
117
  		if (copy_to_user(argp, &ident, sizeof(ident)))
eed6565f7   Calin A. Culianu   [PATCH] Watchdog:...
118
119
120
121
  			return -EFAULT;
  		return 0;
  	case WDIOC_GETSTATUS:
  	case WDIOC_GETBOOTSTATUS:
73a09e626   Al Viro   [PATCH] drivers/c...
122
  		return put_user(0, argp);
73a09e626   Al Viro   [PATCH] drivers/c...
123
124
  	case WDIOC_SETOPTIONS:
  		if (get_user(options, argp))
eed6565f7   Calin A. Culianu   [PATCH] Watchdog:...
125
126
127
128
129
130
131
132
133
134
135
136
137
  			return -EFAULT;
  
  		if (options & WDIOS_DISABLECARD) {
  			epx_c3_stop();
  			retval = 0;
  		}
  
  		if (options & WDIOS_ENABLECARD) {
  			epx_c3_start();
  			retval = 0;
  		}
  
  		return retval;
0c06090c9   Wim Van Sebroeck   [WATCHDOG] Coding...
138
139
140
141
142
  	case WDIOC_KEEPALIVE:
  		epx_c3_pet();
  		return 0;
  	case WDIOC_GETTIMEOUT:
  		return put_user(WATCHDOG_TIMEOUT, argp);
eed6565f7   Calin A. Culianu   [PATCH] Watchdog:...
143
  	default:
795b89d20   Samuel Tardieu   [WATCHDOG] use EN...
144
  		return -ENOTTY;
eed6565f7   Calin A. Culianu   [PATCH] Watchdog:...
145
146
147
148
149
150
151
152
153
154
155
  	}
  }
  
  static int epx_c3_notify_sys(struct notifier_block *this, unsigned long code,
  				void *unused)
  {
  	if (code == SYS_DOWN || code == SYS_HALT)
  		epx_c3_stop();		/* Turn the WDT off */
  
  	return NOTIFY_DONE;
  }
62322d255   Arjan van de Ven   [PATCH] make more...
156
  static const struct file_operations epx_c3_fops = {
eed6565f7   Calin A. Culianu   [PATCH] Watchdog:...
157
158
159
  	.owner		= THIS_MODULE,
  	.llseek		= no_llseek,
  	.write		= epx_c3_write,
f4f6f65a5   Alan Cox   [WATCHDOG 40/57] ...
160
  	.unlocked_ioctl	= epx_c3_ioctl,
eed6565f7   Calin A. Culianu   [PATCH] Watchdog:...
161
162
163
164
165
166
167
168
169
170
171
172
173
  	.open		= epx_c3_open,
  	.release	= epx_c3_release,
  };
  
  static struct miscdevice epx_c3_miscdev = {
  	.minor		= WATCHDOG_MINOR,
  	.name		= "watchdog",
  	.fops		= &epx_c3_fops,
  };
  
  static struct notifier_block epx_c3_notifier = {
  	.notifier_call = epx_c3_notify_sys,
  };
4e8858d51   Andi Kleen   watchdog: Initcon...
174
  static const char banner[] __initconst = KERN_INFO PFX
a77dba7e4   Wim Van Sebroeck   [WATCHDOG] Some m...
175
176
  	"Hardware Watchdog Timer for Winsystems EPX-C3 SBC: 0.1
  ";
eed6565f7   Calin A. Culianu   [PATCH] Watchdog:...
177
178
179
180
  
  static int __init watchdog_init(void)
  {
  	int ret;
de6c642ca   Alan Cox   [PATCH] SBC EPX d...
181
182
  	if (!request_region(EPXC3_WATCHDOG_CTL_REG, 2, "epxc3_watchdog"))
  		return -EBUSY;
eed6565f7   Calin A. Culianu   [PATCH] Watchdog:...
183
184
185
186
187
  	ret = register_reboot_notifier(&epx_c3_notifier);
  	if (ret) {
  		printk(KERN_ERR PFX "cannot register reboot notifier "
  			"(err=%d)
  ", ret);
de6c642ca   Alan Cox   [PATCH] SBC EPX d...
188
  		goto out;
eed6565f7   Calin A. Culianu   [PATCH] Watchdog:...
189
190
191
192
193
194
195
196
  	}
  
  	ret = misc_register(&epx_c3_miscdev);
  	if (ret) {
  		printk(KERN_ERR PFX "cannot register miscdev on minor=%d "
  			"(err=%d)
  ", WATCHDOG_MINOR, ret);
  		unregister_reboot_notifier(&epx_c3_notifier);
de6c642ca   Alan Cox   [PATCH] SBC EPX d...
197
  		goto out;
eed6565f7   Calin A. Culianu   [PATCH] Watchdog:...
198
199
200
201
202
  	}
  
  	printk(banner);
  
  	return 0;
de6c642ca   Alan Cox   [PATCH] SBC EPX d...
203
204
205
206
  
  out:
  	release_region(EPXC3_WATCHDOG_CTL_REG, 2);
  	return ret;
eed6565f7   Calin A. Culianu   [PATCH] Watchdog:...
207
208
209
210
211
212
  }
  
  static void __exit watchdog_exit(void)
  {
  	misc_deregister(&epx_c3_miscdev);
  	unregister_reboot_notifier(&epx_c3_notifier);
de6c642ca   Alan Cox   [PATCH] SBC EPX d...
213
  	release_region(EPXC3_WATCHDOG_CTL_REG, 2);
eed6565f7   Calin A. Culianu   [PATCH] Watchdog:...
214
215
216
217
218
219
  }
  
  module_init(watchdog_init);
  module_exit(watchdog_exit);
  
  MODULE_AUTHOR("Calin A. Culianu <calin@ajvar.org>");
a77dba7e4   Wim Van Sebroeck   [WATCHDOG] Some m...
220
221
  MODULE_DESCRIPTION("Hardware Watchdog Device for Winsystems EPX-C3 SBC.  "
  	"Note that there is no way to probe for this device -- "
ae0e47f02   Justin P. Mattock   Remove one to man...
222
  	"so only use it if you are *sure* you are running on this specific "
a77dba7e4   Wim Van Sebroeck   [WATCHDOG] Some m...
223
  	"SBC system from Winsystems!  It writes to IO ports 0x1ee and 0x1ef!");
eed6565f7   Calin A. Culianu   [PATCH] Watchdog:...
224
225
  MODULE_LICENSE("GPL");
  MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);