MOXA linux-2.6.x / linux-2.6.19-uc1 from UC-7110-LX-BOOTLOADER-1.9_VERSION-4.2.tgz
[linux-2.6.19-moxart.git] / drivers / char / watchdog / avalonwdt.c
blobff37447178dcf45e8af93e147f3d4baf461e7f92
1 /*
2 * WDT driver for the Nios2
4 * (c) Copyright 2005 Walter Goossens <walter.goossens@emdes.nl>
5 * Neither Walter Goossens nor Emdes Embedded Systems admit liability
6 * nor provide warranty for any of this software. This material is
7 * provided "AS-IS" and at no charge.
9 * Based on wdt.c.
10 * Original copyright messages:
12 * (c) Copyright 1996 Alan Cox <alan@redhat.com>, All Rights Reserved.
13 * http://www.redhat.com
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version
18 * 2 of the License, or (at your option) any later version.
20 * Neither Alan Cox nor CymruNet Ltd. admit liability nor provide
21 * warranty for any of this software. This material is provided
22 * "AS-IS" and at no charge.
24 * (c) Copyright 1995 Alan Cox <alan@redhat.com>
27 #include <linux/module.h>
28 #include <linux/miscdevice.h>
29 #include <linux/watchdog.h>
30 #include <linux/fs.h>
31 #include <linux/ioport.h>
32 #include <linux/init.h>
34 #include <asm/io.h>
35 #include <asm/uaccess.h>
36 #include <asm/system.h>
38 // Change this line if you used another name in your PTF file.
40 #define AVALON_WDT_BASE na_watchdog
41 #define AVALON_WDT_STATUS AVALON_WDT_BASE
42 #define AVALON_WDT_CONTROL (AVALON_WDT_BASE + 0x04)
43 #define AVALON_WDT_PERIODL (AVALON_WDT_BASE + 0x08)
44 #define AVALON_WDT_PERIODH (AVALON_WDT_BASE + 0x0C)
45 #define AVALON_WDT_SIZE 0x18
47 #define AVALON_WDT_RUN_BIT 0x04
49 static unsigned long wdt_is_open;
51 /**
52 * avalon_wdt_start:
54 * Start the watchdog driver.
56 static int avalon_wdt_start(void) {
57 outw_p(inw_p(AVALON_WDT_CONTROL) | AVALON_WDT_RUN_BIT, AVALON_WDT_CONTROL);
58 printk(KERN_INFO "avalonwdt: Starting watchdog timer\n");
59 return 0;
62 /**
63 * avalon_wdt_ping:
65 * Reload counter one with the watchdog heartbeat.
67 static int avalon_wdt_ping(void) {
68 //It doesn't matter what value we write
69 outw_p(1,AVALON_WDT_PERIODL);
70 return 0;
73 /**
74 * avalon_wdt_write:
75 * @file: file handle to the watchdog
76 * @buf: buffer to write (unused as data does not matter here
77 * @count: count of bytes
78 * @ppos: pointer to the position to write. No seeks allowed
80 * A write to a watchdog device is defined as a keepalive signal. Any
81 * write of data will do, as we we don't define content meaning.
84 static ssize_t avalon_wdt_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) {
85 if(count) {
86 avalon_wdt_ping();
88 return count;
91 /**
92 * avalon_wdt_ioctl:
93 * @inode: inode of the device
94 * @file: file handle to the device
95 * @cmd: watchdog command
96 * @arg: argument pointer
98 * The watchdog API defines a common set of functions for all watchdogs
99 * according to their available features. We only actually usefully support
100 * querying capabilities and current status.
103 static int avalon_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) {
104 void __user *argp = (void __user *)arg;
106 static struct watchdog_info ident = {
107 .options = WDIOF_KEEPALIVEPING,
108 .firmware_version = 1,
109 .identity = "Nios2_avalon_wdt",
112 switch(cmd) {
113 case WDIOC_GETSUPPORT:
114 return copy_to_user(argp, &ident, sizeof(ident))?-EFAULT:0;
115 case WDIOC_KEEPALIVE:
116 avalon_wdt_ping();
117 return 0;
118 default:
119 return -ENOIOCTLCMD;
124 * avalon_wdt_open:
125 * @inode: inode of device
126 * @file: file handle to device
128 * The watchdog device has been opened. The watchdog device is single
129 * open and on opening we load the counters.
130 * The timeout depends on the value you selected in SOPC-builder.
132 static int avalon_wdt_open(struct inode *inode, struct file *file) {
133 if(test_and_set_bit(0, &wdt_is_open))
134 return -EBUSY;
135 avalon_wdt_start();
136 return nonseekable_open(inode, file);
140 * avalon_wdt_release:
141 * @inode: inode to board
142 * @file: file handle to board
145 static int avalon_wdt_release(struct inode *inode, struct file *file) {
146 clear_bit(0, &wdt_is_open);
147 printk(KERN_CRIT "avalonwdt: WDT device closed unexpectedly. WDT will (can) not stop!\n");
148 avalon_wdt_ping();
149 return 0;
153 * Kernel Interfaces
156 static struct file_operations avalon_wdt_fops = {
157 .owner = THIS_MODULE,
158 .llseek = no_llseek,
159 .write = avalon_wdt_write,
160 .ioctl = avalon_wdt_ioctl,
161 .open = avalon_wdt_open,
162 .release = avalon_wdt_release,
165 static struct miscdevice avalon_wdt_miscdev = {
166 .minor = WATCHDOG_MINOR,
167 .name = "watchdog",
168 .fops = &avalon_wdt_fops,
172 * cleanup_module:
174 * Unload the watchdog. You cannot do this with any file handles open.
175 * If your watchdog is set to continue ticking on close and you unload
176 * it, well it keeps ticking. We won't get the interrupt but the board
177 * will not touch PC memory so all is fine. You just have to load a new
178 * module in 30 seconds or reboot.
181 static void __exit avalon_wdt_exit(void)
183 misc_deregister(&avalon_wdt_miscdev);
184 release_region(AVALON_WDT_BASE,AVALON_WDT_SIZE);
188 * avalon_wdt_init:
190 * Set up the WDT watchdog board. All we have to do is grab the
191 * resources we require and bitch if anyone beat us to them.
192 * The open() function will actually kick the board off.
195 static int __init avalon_wdt_init(void)
197 int ret;
199 if (!request_region(AVALON_WDT_BASE, AVALON_WDT_SIZE, "Nios2_avalon_wdt")) {
200 printk(KERN_ERR "wdt: I/O address 0x%08x already in use\n", AVALON_WDT_BASE);
201 return -EBUSY;
203 ret = misc_register(&avalon_wdt_miscdev);
204 if (ret) {
205 printk(KERN_ERR "wdt: cannot register miscdev on minor=%d (err=%d)\n", WATCHDOG_MINOR, ret);
206 release_region(AVALON_WDT_BASE,AVALON_WDT_SIZE);
207 return ret;
210 printk(KERN_INFO "Nios2 Avalon Watchdog driver 0.01 at 0x%08x\n", AVALON_WDT_BASE);
211 return 0;
214 module_init(avalon_wdt_init);
215 module_exit(avalon_wdt_exit);
217 MODULE_AUTHOR("Walter Goossens");
218 MODULE_DESCRIPTION("Driver for Nios2 Watchdog");
219 MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
220 MODULE_LICENSE("GPL");