blob: ac6fbace47241d2f8c218d0cc69c057613e9ca8e [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * mpc8xx_wdt.c - MPC8xx watchdog userspace interface
3 *
4 * Author: Florian Schirmer <jolt@tuxbox.org>
5 *
6 * 2002 (c) Florian Schirmer <jolt@tuxbox.org> This file is licensed under
7 * the terms of the GNU General Public License version 2. This program
8 * is licensed "as is" without any warranty of any kind, whether express
9 * or implied.
10 */
11
12#include <linux/config.h>
13#include <linux/fs.h>
14#include <linux/init.h>
15#include <linux/kernel.h>
16#include <linux/miscdevice.h>
17#include <linux/module.h>
18#include <linux/watchdog.h>
19#include <asm/8xx_immap.h>
20#include <asm/uaccess.h>
21#include <syslib/m8xx_wdt.h>
22
23static unsigned long wdt_opened;
24static int wdt_status;
25
26static void mpc8xx_wdt_handler_disable(void)
27{
28 volatile immap_t *imap = (volatile immap_t *)IMAP_ADDR;
29
Marcelo Tosattifb64c242005-11-24 11:32:09 -020030 if (!m8xx_has_internal_rtc)
31 m8xx_wdt_stop_timer();
32 else
33 out_be32(imap->im_sit.sit_piscr, in_be32(&imap->im_sit.sit_piscr) & ~(PISCR_PIE | PISCR_PTE));
Linus Torvalds1da177e2005-04-16 15:20:36 -070034
35 printk(KERN_NOTICE "mpc8xx_wdt: keep-alive handler deactivated\n");
36}
37
38static void mpc8xx_wdt_handler_enable(void)
39{
40 volatile immap_t *imap = (volatile immap_t *)IMAP_ADDR;
41
Marcelo Tosattifb64c242005-11-24 11:32:09 -020042 if (!m8xx_has_internal_rtc)
43 m8xx_wdt_install_timer();
44 else
45 out_be32(&imap->im_sit.sit_piscr, in_be32(&imap->im_sit.sit_piscr) | PISCR_PIE | PISCR_PTE);
Linus Torvalds1da177e2005-04-16 15:20:36 -070046
47 printk(KERN_NOTICE "mpc8xx_wdt: keep-alive handler activated\n");
48}
49
50static int mpc8xx_wdt_open(struct inode *inode, struct file *file)
51{
52 if (test_and_set_bit(0, &wdt_opened))
53 return -EBUSY;
54
55 m8xx_wdt_reset();
56 mpc8xx_wdt_handler_disable();
57
58 return 0;
59}
60
61static int mpc8xx_wdt_release(struct inode *inode, struct file *file)
62{
63 m8xx_wdt_reset();
64
65#if !defined(CONFIG_WATCHDOG_NOWAYOUT)
66 mpc8xx_wdt_handler_enable();
67#endif
68
69 clear_bit(0, &wdt_opened);
70
71 return 0;
72}
73
74static ssize_t mpc8xx_wdt_write(struct file *file, const char *data, size_t len,
75 loff_t * ppos)
76{
Linus Torvalds1da177e2005-04-16 15:20:36 -070077 if (len)
78 m8xx_wdt_reset();
79
80 return len;
81}
82
83static int mpc8xx_wdt_ioctl(struct inode *inode, struct file *file,
84 unsigned int cmd, unsigned long arg)
85{
86 int timeout;
87 static struct watchdog_info info = {
88 .options = WDIOF_KEEPALIVEPING,
89 .firmware_version = 0,
90 .identity = "MPC8xx watchdog",
91 };
92
93 switch (cmd) {
94 case WDIOC_GETSUPPORT:
95 if (copy_to_user((void *)arg, &info, sizeof(info)))
96 return -EFAULT;
97 break;
98
99 case WDIOC_GETSTATUS:
100 case WDIOC_GETBOOTSTATUS:
101 if (put_user(wdt_status, (int *)arg))
102 return -EFAULT;
103 wdt_status &= ~WDIOF_KEEPALIVEPING;
104 break;
105
106 case WDIOC_GETTEMP:
107 return -EOPNOTSUPP;
108
109 case WDIOC_SETOPTIONS:
110 return -EOPNOTSUPP;
111
112 case WDIOC_KEEPALIVE:
113 m8xx_wdt_reset();
114 wdt_status |= WDIOF_KEEPALIVEPING;
115 break;
116
117 case WDIOC_SETTIMEOUT:
118 return -EOPNOTSUPP;
119
120 case WDIOC_GETTIMEOUT:
121 timeout = m8xx_wdt_get_timeout();
122 if (put_user(timeout, (int *)arg))
123 return -EFAULT;
124 break;
125
126 default:
127 return -ENOIOCTLCMD;
128 }
129
130 return 0;
131}
132
133static struct file_operations mpc8xx_wdt_fops = {
134 .owner = THIS_MODULE,
135 .llseek = no_llseek,
136 .write = mpc8xx_wdt_write,
137 .ioctl = mpc8xx_wdt_ioctl,
138 .open = mpc8xx_wdt_open,
139 .release = mpc8xx_wdt_release,
140};
141
142static struct miscdevice mpc8xx_wdt_miscdev = {
143 .minor = WATCHDOG_MINOR,
144 .name = "watchdog",
145 .fops = &mpc8xx_wdt_fops,
146};
147
148static int __init mpc8xx_wdt_init(void)
149{
150 return misc_register(&mpc8xx_wdt_miscdev);
151}
152
153static void __exit mpc8xx_wdt_exit(void)
154{
155 misc_deregister(&mpc8xx_wdt_miscdev);
156
157 m8xx_wdt_reset();
158 mpc8xx_wdt_handler_enable();
159}
160
161module_init(mpc8xx_wdt_init);
162module_exit(mpc8xx_wdt_exit);
163
164MODULE_AUTHOR("Florian Schirmer <jolt@tuxbox.org>");
165MODULE_DESCRIPTION("MPC8xx watchdog driver");
166MODULE_LICENSE("GPL");
167MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);