OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [char/] [wafer5823wdt.c] - Blame information for rev 1774

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 *      ICP Wafer 5823 Single Board Computer WDT driver for Linux 2.4.x
3
 *      http://www.icpamerica.com/wafer_5823.php
4
 *      May also work on other similar models
5
 *
6
 *      (c) Copyright 2002 Justin Cormack <justin@street-vision.com>
7
 *
8
 *      Release 0.02
9
 *
10
 *      Based on advantechwdt.c which is based on wdt.c.
11
 *      Original copyright messages:
12
 *
13
 *      (c) Copyright 1996-1997 Alan Cox <alan@redhat.com>, All Rights Reserved.
14
 *                              http://www.redhat.com
15
 *
16
 *      This program is free software; you can redistribute it and/or
17
 *      modify it under the terms of the GNU General Public License
18
 *      as published by the Free Software Foundation; either version
19
 *      2 of the License, or (at your option) any later version.
20
 *
21
 *      Neither Alan Cox nor CymruNet Ltd. admit liability nor provide
22
 *      warranty for any of this software. This material is provided
23
 *      "AS-IS" and at no charge.
24
 *
25
 *      (c) Copyright 1995    Alan Cox <alan@lxorguk.ukuu.org.uk>
26
 *
27
 */
28
 
29
#include <linux/module.h>
30
#include <linux/kernel.h>
31
#include <linux/miscdevice.h>
32
#include <linux/watchdog.h>
33
#include <linux/ioport.h>
34
#include <asm/io.h>
35
#include <asm/uaccess.h>
36
#include <linux/notifier.h>
37
#include <linux/reboot.h>
38
#include <linux/init.h>
39
#include <linux/spinlock.h>
40
 
41
static unsigned long wafwdt_is_open;
42
static spinlock_t wafwdt_lock;
43
static int expect_close = 0;
44
 
45
/*
46
 *      You must set these - there is no sane way to probe for this board.
47
 *
48
 *      To enable, write the timeout value in seconds (1 to 255) to I/O
49
 *      port WDT_START, then read the port to start the watchdog. To pat
50
 *      the dog, read port WDT_STOP to stop the timer, then read WDT_START
51
 *      to restart it again.
52
 */
53
 
54
#define WDT_START 0x443
55
#define WDT_STOP 0x843
56
 
57
#define WD_TIMO 60              /* 1 minute */
58
static int wd_margin = WD_TIMO;
59
 
60
#ifdef CONFIG_WATCHDOG_NOWAYOUT
61
static int nowayout = 1;
62
#else
63
static int nowayout = 0;
64
#endif
65
 
66
MODULE_PARM(nowayout,"i");
67
MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
68
 
69
static void wafwdt_ping(void)
70
{
71
        /* pat watchdog */
72
        spin_lock(&wafwdt_lock);
73
        inb_p(WDT_STOP);
74
        inb_p(WDT_START);
75
        spin_unlock(&wafwdt_lock);
76
}
77
 
78
static void wafwdt_start(void)
79
{
80
        /* start up watchdog */
81
        outb_p(wd_margin, WDT_START);
82
        inb_p(WDT_START);
83
}
84
 
85
static void
86
wafwdt_stop(void)
87
{
88
        /* stop watchdog */
89
        inb_p(WDT_STOP);
90
}
91
 
92
static ssize_t wafwdt_write(struct file *file, const char *buf, size_t count, loff_t * ppos)
93
{
94
        /*  Can't seek (pwrite) on this device  */
95
        if (ppos != &file->f_pos)
96
                return -ESPIPE;
97
 
98
        if (count) {
99
                if (!nowayout) {
100
                        size_t i;
101
 
102
                        /* In case it was set long ago */
103
                        expect_close = 0;
104
 
105
                        for (i = 0; i != count; i++) {
106
                                char c;
107
                                if (get_user(c, buf + i))
108
                                        return -EFAULT;
109
                                if (c == 'V')
110
                                        expect_close = 1;
111
                        }
112
                }
113
                wafwdt_ping();
114
                return 1;
115
        }
116
        return 0;
117
}
118
 
119
static int wafwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
120
             unsigned long arg)
121
{
122
        int new_margin;
123
        static struct watchdog_info ident = {
124
                WDIOF_KEEPALIVEPING |
125
                WDIOF_SETTIMEOUT |
126
                WDIOF_MAGICCLOSE,
127
                1, "Wafer 5823 WDT"
128
        };
129
        int one=1;
130
 
131
        switch (cmd) {
132
        case WDIOC_GETSUPPORT:
133
                if (copy_to_user
134
                    ((struct watchdog_info *) arg, &ident, sizeof (ident)))
135
                        return -EFAULT;
136
                break;
137
 
138
        case WDIOC_GETSTATUS:
139
                if (copy_to_user((int *) arg, &one, sizeof (int)))
140
                        return -EFAULT;
141
                break;
142
 
143
        case WDIOC_KEEPALIVE:
144
                wafwdt_ping();
145
                break;
146
 
147
        case WDIOC_SETTIMEOUT:
148
                if (get_user(new_margin, (int *)arg))
149
                        return -EFAULT;
150
                if ((new_margin < 1) || (new_margin > 255))
151
                        return -EINVAL;
152
                wd_margin = new_margin;
153
                wafwdt_stop();
154
                wafwdt_start();
155
                /* Fall */
156
        case WDIOC_GETTIMEOUT:
157
                return put_user(wd_margin, (int *)arg);
158
 
159
        default:
160
                return -ENOTTY;
161
        }
162
        return 0;
163
}
164
 
165
static int wafwdt_open(struct inode *inode, struct file *file)
166
{
167
        if (test_and_set_bit(0, &wafwdt_is_open))
168
                return -EBUSY;
169
        wafwdt_start();
170
        return 0;
171
}
172
 
173
static int
174
wafwdt_close(struct inode *inode, struct file *file)
175
{
176
        clear_bit(0, &wafwdt_is_open);
177
        if (expect_close) {
178
                wafwdt_stop();
179
        } else {
180
                printk(KERN_CRIT "WDT device closed unexpectedly.  WDT will not stop!\n");
181
        }
182
        return 0;
183
}
184
 
185
/*
186
 *      Notifier for system down
187
 */
188
 
189
static int wafwdt_notify_sys(struct notifier_block *this, unsigned long code, void *unused)
190
{
191
        if (code == SYS_DOWN || code == SYS_HALT) {
192
                /* Turn the WDT off */
193
                wafwdt_stop();
194
        }
195
        return NOTIFY_DONE;
196
}
197
 
198
/*
199
 *      Kernel Interfaces
200
 */
201
 
202
static struct file_operations wafwdt_fops = {
203
        owner:THIS_MODULE,
204
        write:wafwdt_write,
205
        ioctl:wafwdt_ioctl,
206
        open:wafwdt_open,
207
        release:wafwdt_close,
208
};
209
 
210
static struct miscdevice wafwdt_miscdev = {
211
        WATCHDOG_MINOR,
212
        "watchdog",
213
        &wafwdt_fops
214
};
215
 
216
/*
217
 *      The WDT needs to learn about soft shutdowns in order to
218
 *      turn the timebomb registers off.
219
 */
220
 
221
static struct notifier_block wafwdt_notifier = {
222
        wafwdt_notify_sys,
223
        NULL,
224
 
225
};
226
 
227
static int __init wafwdt_init(void)
228
{
229
        printk(KERN_INFO "WDT driver for Wafer 5823 single board computer initialising.\n");
230
 
231
        spin_lock_init(&wafwdt_lock);
232
        if(!request_region(WDT_STOP, 1, "Wafer 5823 WDT"))
233
                goto error;
234
        if(!request_region(WDT_START, 1, "Wafer 5823 WDT"))
235
                goto error2;
236
        if(misc_register(&wafwdt_miscdev)<0)
237
                goto error3;
238
        register_reboot_notifier(&wafwdt_notifier);
239
        return 0;
240
error3:
241
        release_region(WDT_START, 1);
242
error2:
243
        release_region(WDT_STOP, 1);
244
error:
245
        return -ENODEV;
246
}
247
 
248
static void __exit wafwdt_exit(void)
249
{
250
        misc_deregister(&wafwdt_miscdev);
251
        unregister_reboot_notifier(&wafwdt_notifier);
252
        release_region(WDT_STOP, 1);
253
        release_region(WDT_START, 1);
254
}
255
 
256
module_init(wafwdt_init);
257
module_exit(wafwdt_exit);
258
 
259
MODULE_AUTHOR("Justin Cormack");
260
MODULE_LICENSE("GPL");
261
EXPORT_NO_SYMBOLS;
262
 
263
/* end of wafer5823wdt.c */

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.