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

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [watchdog/] [cpu5wdt.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 * sma cpu5 watchdog driver
3
 *
4
 * Copyright (C) 2003 Heiko Ronsdorf <hero@ihg.uni-duisburg.de>
5
 *
6
 * This program is free software; you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation; either version 2 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19
 *
20
 */
21
 
22
#include <linux/module.h>
23
#include <linux/moduleparam.h>
24
#include <linux/types.h>
25
#include <linux/errno.h>
26
#include <linux/miscdevice.h>
27
#include <linux/fs.h>
28
#include <linux/init.h>
29
#include <linux/ioport.h>
30
#include <linux/timer.h>
31
#include <linux/completion.h>
32
#include <linux/jiffies.h>
33
#include <asm/io.h>
34
#include <asm/uaccess.h>
35
 
36
#include <linux/watchdog.h>
37
 
38
/* adjustable parameters */
39
 
40
static int verbose = 0;
41
static int port = 0x91;
42
static int ticks = 10000;
43
 
44
#define PFX                     "cpu5wdt: "
45
 
46
#define CPU5WDT_EXTENT          0x0A
47
 
48
#define CPU5WDT_STATUS_REG      0x00
49
#define CPU5WDT_TIME_A_REG      0x02
50
#define CPU5WDT_TIME_B_REG      0x03
51
#define CPU5WDT_MODE_REG        0x04
52
#define CPU5WDT_TRIGGER_REG     0x07
53
#define CPU5WDT_ENABLE_REG      0x08
54
#define CPU5WDT_RESET_REG       0x09
55
 
56
#define CPU5WDT_INTERVAL        (HZ/10+1)
57
 
58
/* some device data */
59
 
60
static struct {
61
        struct completion stop;
62
        volatile int running;
63
        struct timer_list timer;
64
        volatile int queue;
65
        int default_ticks;
66
        unsigned long inuse;
67
} cpu5wdt_device;
68
 
69
/* generic helper functions */
70
 
71
static void cpu5wdt_trigger(unsigned long unused)
72
{
73
        if ( verbose > 2 )
74
                printk(KERN_DEBUG PFX "trigger at %i ticks\n", ticks);
75
 
76
        if( cpu5wdt_device.running )
77
                ticks--;
78
 
79
        /* keep watchdog alive */
80
        outb(1, port + CPU5WDT_TRIGGER_REG);
81
 
82
        /* requeue?? */
83
        if (cpu5wdt_device.queue && ticks)
84
                mod_timer(&cpu5wdt_device.timer, jiffies + CPU5WDT_INTERVAL);
85
        else {
86
                /* ticks doesn't matter anyway */
87
                complete(&cpu5wdt_device.stop);
88
        }
89
 
90
}
91
 
92
static void cpu5wdt_reset(void)
93
{
94
        ticks = cpu5wdt_device.default_ticks;
95
 
96
        if ( verbose )
97
                printk(KERN_DEBUG PFX "reset (%i ticks)\n", (int) ticks);
98
 
99
}
100
 
101
static void cpu5wdt_start(void)
102
{
103
        if ( !cpu5wdt_device.queue ) {
104
                cpu5wdt_device.queue = 1;
105
                outb(0, port + CPU5WDT_TIME_A_REG);
106
                outb(0, port + CPU5WDT_TIME_B_REG);
107
                outb(1, port + CPU5WDT_MODE_REG);
108
                outb(0, port + CPU5WDT_RESET_REG);
109
                outb(0, port + CPU5WDT_ENABLE_REG);
110
                mod_timer(&cpu5wdt_device.timer, jiffies + CPU5WDT_INTERVAL);
111
        }
112
        /* if process dies, counter is not decremented */
113
        cpu5wdt_device.running++;
114
}
115
 
116
static int cpu5wdt_stop(void)
117
{
118
        if ( cpu5wdt_device.running )
119
                cpu5wdt_device.running = 0;
120
 
121
        ticks = cpu5wdt_device.default_ticks;
122
 
123
        if ( verbose )
124
                printk(KERN_CRIT PFX "stop not possible\n");
125
 
126
        return -EIO;
127
}
128
 
129
/* filesystem operations */
130
 
131
static int cpu5wdt_open(struct inode *inode, struct file *file)
132
{
133
        if ( test_and_set_bit(0, &cpu5wdt_device.inuse) )
134
                return -EBUSY;
135
 
136
        return nonseekable_open(inode, file);
137
}
138
 
139
static int cpu5wdt_release(struct inode *inode, struct file *file)
140
{
141
        clear_bit(0, &cpu5wdt_device.inuse);
142
        return 0;
143
}
144
 
145
static int cpu5wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
146
{
147
        void __user *argp = (void __user *)arg;
148
        unsigned int value;
149
        static struct watchdog_info ident =
150
        {
151
                .options = WDIOF_CARDRESET,
152
                .identity = "CPU5 WDT",
153
        };
154
 
155
        switch(cmd) {
156
                case WDIOC_KEEPALIVE:
157
                        cpu5wdt_reset();
158
                        break;
159
                case WDIOC_GETSTATUS:
160
                        value = inb(port + CPU5WDT_STATUS_REG);
161
                        value = (value >> 2) & 1;
162
                        if ( copy_to_user(argp, &value, sizeof(int)) )
163
                                return -EFAULT;
164
                        break;
165
                case WDIOC_GETBOOTSTATUS:
166
                        if ( copy_to_user(argp, &value, sizeof(int)) )
167
                                return -EFAULT;
168
                        break;
169
                case WDIOC_GETSUPPORT:
170
                        if ( copy_to_user(argp, &ident, sizeof(ident)) )
171
                                return -EFAULT;
172
                        break;
173
                case WDIOC_SETOPTIONS:
174
                        if ( copy_from_user(&value, argp, sizeof(int)) )
175
                                return -EFAULT;
176
                        switch(value) {
177
                                case WDIOS_ENABLECARD:
178
                                        cpu5wdt_start();
179
                                        break;
180
                                case WDIOS_DISABLECARD:
181
                                        return cpu5wdt_stop();
182
                                default:
183
                                        return -EINVAL;
184
                        }
185
                        break;
186
                default:
187
                        return -ENOTTY;
188
        }
189
        return 0;
190
}
191
 
192
static ssize_t cpu5wdt_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
193
{
194
        if ( !count )
195
                return -EIO;
196
 
197
        cpu5wdt_reset();
198
 
199
        return count;
200
}
201
 
202
static const struct file_operations cpu5wdt_fops = {
203
        .owner          = THIS_MODULE,
204
        .llseek         = no_llseek,
205
        .ioctl          = cpu5wdt_ioctl,
206
        .open           = cpu5wdt_open,
207
        .write          = cpu5wdt_write,
208
        .release        = cpu5wdt_release,
209
};
210
 
211
static struct miscdevice cpu5wdt_misc = {
212
        .minor  = WATCHDOG_MINOR,
213
        .name   = "watchdog",
214
        .fops   = &cpu5wdt_fops,
215
};
216
 
217
/* init/exit function */
218
 
219
static int __devinit cpu5wdt_init(void)
220
{
221
        unsigned int val;
222
        int err;
223
 
224
        if ( verbose )
225
                printk(KERN_DEBUG PFX "port=0x%x, verbose=%i\n", port, verbose);
226
 
227
        if ( !request_region(port, CPU5WDT_EXTENT, PFX) ) {
228
                printk(KERN_ERR PFX "request_region failed\n");
229
                err = -EBUSY;
230
                goto no_port;
231
        }
232
 
233
        if ( (err = misc_register(&cpu5wdt_misc)) < 0 ) {
234
                printk(KERN_ERR PFX "misc_register failed\n");
235
                goto no_misc;
236
        }
237
 
238
        /* watchdog reboot? */
239
        val = inb(port + CPU5WDT_STATUS_REG);
240
        val = (val >> 2) & 1;
241
        if ( !val )
242
                printk(KERN_INFO PFX "sorry, was my fault\n");
243
 
244
        init_completion(&cpu5wdt_device.stop);
245
        cpu5wdt_device.queue = 0;
246
 
247
        clear_bit(0, &cpu5wdt_device.inuse);
248
 
249
        setup_timer(&cpu5wdt_device.timer, cpu5wdt_trigger, 0);
250
 
251
        cpu5wdt_device.default_ticks = ticks;
252
 
253
        printk(KERN_INFO PFX "init success\n");
254
 
255
        return 0;
256
 
257
no_misc:
258
        release_region(port, CPU5WDT_EXTENT);
259
no_port:
260
        return err;
261
}
262
 
263
static int __devinit cpu5wdt_init_module(void)
264
{
265
        return cpu5wdt_init();
266
}
267
 
268
static void __devexit cpu5wdt_exit(void)
269
{
270
        if ( cpu5wdt_device.queue ) {
271
                cpu5wdt_device.queue = 0;
272
                wait_for_completion(&cpu5wdt_device.stop);
273
        }
274
 
275
        misc_deregister(&cpu5wdt_misc);
276
 
277
        release_region(port, CPU5WDT_EXTENT);
278
 
279
}
280
 
281
static void __devexit cpu5wdt_exit_module(void)
282
{
283
        cpu5wdt_exit();
284
}
285
 
286
/* module entry points */
287
 
288
module_init(cpu5wdt_init_module);
289
module_exit(cpu5wdt_exit_module);
290
 
291
MODULE_AUTHOR("Heiko Ronsdorf <hero@ihg.uni-duisburg.de>");
292
MODULE_DESCRIPTION("sma cpu5 watchdog driver");
293
MODULE_SUPPORTED_DEVICE("sma cpu5 watchdog");
294
MODULE_LICENSE("GPL");
295
MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
296
 
297
module_param(port, int, 0);
298
MODULE_PARM_DESC(port, "base address of watchdog card, default is 0x91");
299
 
300
module_param(verbose, int, 0);
301
MODULE_PARM_DESC(verbose, "be verbose, default is 0 (no)");
302
 
303
module_param(ticks, int, 0);
304
MODULE_PARM_DESC(ticks, "count down ticks, default is 10000");

powered by: WebSVN 2.1.0

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