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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [drivers/] [char/] [wdt.c] - Blame information for rev 1626

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

Line No. Rev Author Line
1 1626 jcastillo
/*
2
 *      Industrial Computer Source WDT500/501 driver for Linux 1.3.x
3
 *
4
 *      (c) Copyright 1995      CymruNET Ltd
5
 *                              Innovation Centre
6
 *                              Singleton Park
7
 *                              Swansea
8
 *                              Wales
9
 *                              UK
10
 *                              SA2 8PP
11
 *
12
 *      http://www.cymru.net
13
 *
14
 *      This driver is provided under the GNU public license, incorporated
15
 *      herein by reference. The driver is provided without warranty or
16
 *      support.
17
 *
18
 *      Release 0.05.
19
 *
20
 *      Some changes by Dave Gregorich to fix modularisation and minor bugs.
21
 */
22
 
23
#include <linux/config.h>
24
#include <linux/module.h>
25
#include <linux/version.h>
26
#include <linux/types.h>
27
#include <linux/errno.h>
28
#include <linux/kernel.h>
29
#include <linux/sched.h>
30
#include <linux/miscdevice.h>
31
#include "wd501p.h"
32
#include <linux/malloc.h>
33
#include <linux/ioport.h>
34
#include <linux/fcntl.h>
35
#include <asm/io.h>
36
#include <asm/segment.h>
37
#include <asm/system.h>
38
 
39
static int wdt_is_open=0;
40
 
41
/*
42
 *      You must set these - there is no sane way to probe for this board.
43
 */
44
 
45
static int io=0x240;
46
static int irq=14;
47
 
48
#define WD_TIMO (100*60)                /* 1 minute */
49
 
50
/*
51
 *      Programming support
52
 */
53
 
54
static void wdt_ctr_mode(int ctr, int mode)
55
{
56
        ctr<<=6;
57
        ctr|=0x30;
58
        ctr|=(mode<<1);
59
        outb_p(ctr, WDT_CR);
60
}
61
 
62
static void wdt_ctr_load(int ctr, int val)
63
{
64
        outb_p(val&0xFF, WDT_COUNT0+ctr);
65
        outb_p(val>>8, WDT_COUNT0+ctr);
66
}
67
 
68
/*
69
 *      Kernel methods.
70
 */
71
 
72
static void wdt_interrupt(int irq, void *dev_id, struct pt_regs *regs)
73
{
74
        /*
75
         *      Read the status register see what is up and
76
         *      then printk it.
77
         */
78
 
79
        unsigned char status=inb_p(WDT_SR);
80
 
81
        status|=FEATUREMAP1;
82
        status&=~FEATUREMAP2;
83
 
84
        printk(KERN_CRIT "WDT status %d\n", status);
85
 
86
        if(!(status&WDC_SR_TGOOD))
87
                printk(KERN_CRIT "Overheat alarm.(%d)\n",inb_p(WDT_RT));
88
        if(!(status&WDC_SR_PSUOVER))
89
                printk(KERN_CRIT "PSU over voltage.\n");
90
        if(!(status&WDC_SR_PSUUNDR))
91
                printk(KERN_CRIT "PSU under voltage.\n");
92
        if(!(status&WDC_SR_FANGOOD))
93
                printk(KERN_CRIT "Possible fan fault.\n");
94
        if(!(status&WDC_SR_WCCR))
95
#ifdef SOFTWARE_REBOOT
96
#ifdef ONLY_TESTING
97
                printk(KERN_CRIT "Would Reboot.\n");
98
#else           
99
                printk(KERN_CRIT "Initiating system reboot.\n");
100
                hard_reset_now();
101
#endif          
102
#else
103
                printk(KERN_CRIT "Reset in 5ms.\n");
104
#endif          
105
}
106
 
107
 
108
static int wdt_lseek(struct inode *inode, struct file *file, off_t offset,
109
        int origin)
110
{
111
        return -ESPIPE;
112
}
113
 
114
static int wdt_write(struct inode *inode, struct file *file, const char *buf, int count)
115
{
116
        /* Write a watchdog value */
117
        inb_p(WDT_DC);
118
        wdt_ctr_mode(1,2);
119
        wdt_ctr_load(1,WD_TIMO);                /* Timeout */
120
        outb_p(0, WDT_DC);
121
        return count;
122
}
123
 
124
/*
125
 *      Read reports the temperature in farenheit
126
 */
127
 
128
static int wdt_read(struct inode *inode, struct file *file, char *buf, int count)
129
{
130
        unsigned short c=inb_p(WDT_RT);
131
        unsigned char cp;
132
        int err;
133
 
134
        switch(MINOR(inode->i_rdev))
135
        {
136
                case TEMP_MINOR:
137
                        err=verify_area(VERIFY_WRITE, buf, 1);
138
                        if(err)
139
                                return err;
140
                        c*=11;
141
                        c/=15;
142
                        cp=c+7;
143
                        memcpy_tofs(buf,&cp,1);
144
                        return 1;
145
                default:
146
                        return -EINVAL;
147
        }
148
}
149
 
150
static int wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
151
        unsigned long arg)
152
{
153
        return -EINVAL;
154
}
155
 
156
static int wdt_open(struct inode *inode, struct file *file)
157
{
158
        switch(MINOR(inode->i_rdev))
159
        {
160
                case WATCHDOG_MINOR:
161
                        if(wdt_is_open)
162
                                return -EBUSY;
163
                        MOD_INC_USE_COUNT;
164
                        /*
165
                         *      Activate
166
                         */
167
 
168
                        wdt_is_open=1;
169
                        inb_p(WDT_DC);          /* Disable */
170
                        wdt_ctr_mode(0,3);
171
                        wdt_ctr_mode(1,2);
172
                        wdt_ctr_mode(2,0);
173
                        wdt_ctr_load(0, 8948);           /* count at 100Hz */
174
                        wdt_ctr_load(1,WD_TIMO);        /* Timeout 120 seconds */
175
                        wdt_ctr_load(2,65535);
176
                        outb_p(0, WDT_DC);       /* Enable */
177
                        return 0;
178
                case TEMP_MINOR:
179
                        MOD_INC_USE_COUNT;
180
                        return 0;
181
                default:
182
                        return -ENODEV;
183
        }
184
}
185
 
186
static void wdt_release(struct inode *inode, struct file *file)
187
{
188
        if(MINOR(inode->i_rdev)==WATCHDOG_MINOR)
189
        {
190
#ifndef CONFIG_WATCHDOG_NOWAYOUT        
191
                inb_p(WDT_DC);          /* Disable counters */
192
                wdt_ctr_load(2,0);       /* 0 length reset pulses now */
193
#endif          
194
                wdt_is_open=0;
195
        }
196
        MOD_DEC_USE_COUNT;
197
}
198
 
199
/*
200
 *      Kernel Interfaces
201
 */
202
 
203
 
204
static struct file_operations wdt_fops = {
205
        wdt_lseek,
206
        wdt_read,
207
        wdt_write,
208
        NULL,           /* No Readdir */
209
        NULL,           /* No Select */
210
        wdt_ioctl,
211
        NULL,           /* No mmap */
212
        wdt_open,
213
        wdt_release
214
};
215
 
216
static struct miscdevice wdt_miscdev=
217
{
218
        WATCHDOG_MINOR,
219
        "wdt",
220
        &wdt_fops
221
};
222
 
223
#ifdef CONFIG_WDT_501
224
static struct miscdevice temp_miscdev=
225
{
226
        TEMP_MINOR,
227
        "temperature",
228
        &wdt_fops
229
};
230
#endif
231
 
232
#ifdef MODULE
233
 
234
int init_module(void)
235
{
236
        printk("WDT501-P module at %X(Interrupt %d)\n", io,irq);
237
        if(request_irq(irq, wdt_interrupt, SA_INTERRUPT, "wdt501p", NULL))
238
        {
239
                printk("IRQ %d is not free.\n", irq);
240
                return -EIO;
241
        }
242
        misc_register(&wdt_miscdev);
243
#ifdef CONFIG_WDT_501   
244
        misc_register(&temp_miscdev);
245
#endif  
246
        request_region(io, 8, "wdt501");
247
        return 0;
248
}
249
 
250
void cleanup_module(void)
251
{
252
        misc_deregister(&wdt_miscdev);
253
#ifdef CONFIG_WDT_501   
254
        misc_deregister(&temp_miscdev);
255
#endif  
256
        release_region(io,8);
257
        free_irq(irq, NULL);
258
}
259
 
260
#else
261
 
262
int wdt_init(void)
263
{
264
        printk("WDT500/501-P driver at %X(Interrupt %d)\n", io,irq);
265
        if(request_irq(irq, wdt_interrupt, SA_INTERRUPT, "wdt501p", NULL))
266
        {
267
                printk("IRQ %d is not free.\n", irq);
268
                return -EIO;
269
        }
270
        misc_register(&wdt_miscdev);
271
#ifdef CONFIG_WDT_501   
272
        misc_register(&temp_miscdev);
273
#endif  
274
        request_region(io, 8, "wdt501");
275
        return 0;
276
}
277
 
278
#endif

powered by: WebSVN 2.1.0

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