~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux-2.6.17/drivers/char/watchdog/mv64x60_wdt.c

Version: ~ [ 2.6.16 ] ~ [ 2.6.17 ] ~
Architecture: ~ [ ia64 ] ~ [ i386 ] ~ [ arm ] ~ [ ppc ] ~ [ sparc64 ] ~

  1 /*
  2  * mv64x60_wdt.c - MV64X60 (Marvell Discovery) watchdog userspace interface
  3  *
  4  * Author: James Chapman <jchapman@katalix.com>
  5  *
  6  * Platform-specific setup code should configure the dog to generate
  7  * interrupt or reset as required.  This code only enables/disables
  8  * and services the watchdog.
  9  *
 10  * Derived from mpc8xx_wdt.c, with the following copyright.
 11  * 
 12  * 2002 (c) Florian Schirmer <jolt@tuxbox.org> This file is licensed under
 13  * the terms of the GNU General Public License version 2. This program
 14  * is licensed "as is" without any warranty of any kind, whether express
 15  * or implied.
 16  */
 17 
 18 #include <linux/config.h>
 19 #include <linux/fs.h>
 20 #include <linux/init.h>
 21 #include <linux/kernel.h>
 22 #include <linux/miscdevice.h>
 23 #include <linux/module.h>
 24 #include <linux/watchdog.h>
 25 #include <linux/platform_device.h>
 26 
 27 #include <asm/mv64x60.h>
 28 #include <asm/uaccess.h>
 29 #include <asm/io.h>
 30 
 31 /* MV64x60 WDC (config) register access definitions */
 32 #define MV64x60_WDC_CTL1_MASK   (3 << 24)
 33 #define MV64x60_WDC_CTL1(val)   ((val & 3) << 24)
 34 #define MV64x60_WDC_CTL2_MASK   (3 << 26)
 35 #define MV64x60_WDC_CTL2(val)   ((val & 3) << 26)
 36 
 37 /* Flags bits */
 38 #define MV64x60_WDOG_FLAG_OPENED        0
 39 #define MV64x60_WDOG_FLAG_ENABLED       1
 40 
 41 static unsigned long wdt_flags;
 42 static int wdt_status;
 43 static void __iomem *mv64x60_regs;
 44 static int mv64x60_wdt_timeout;
 45 
 46 static void mv64x60_wdt_reg_write(u32 val)
 47 {
 48         /* Allow write only to CTL1 / CTL2 fields, retaining values in
 49          * other fields.
 50          */
 51         u32 data = readl(mv64x60_regs + MV64x60_WDT_WDC);
 52         data &= ~(MV64x60_WDC_CTL1_MASK | MV64x60_WDC_CTL2_MASK);
 53         data |= val;
 54         writel(data, mv64x60_regs + MV64x60_WDT_WDC);
 55 }
 56 
 57 static void mv64x60_wdt_service(void)
 58 {
 59         /* Write 01 followed by 10 to CTL2 */
 60         mv64x60_wdt_reg_write(MV64x60_WDC_CTL2(0x01));
 61         mv64x60_wdt_reg_write(MV64x60_WDC_CTL2(0x02));
 62 }
 63 
 64 static void mv64x60_wdt_handler_disable(void)
 65 {
 66         if (test_and_clear_bit(MV64x60_WDOG_FLAG_ENABLED, &wdt_flags)) {
 67                 /* Write 01 followed by 10 to CTL1 */
 68                 mv64x60_wdt_reg_write(MV64x60_WDC_CTL1(0x01));
 69                 mv64x60_wdt_reg_write(MV64x60_WDC_CTL1(0x02));
 70                 printk(KERN_NOTICE "mv64x60_wdt: watchdog deactivated\n");
 71         }
 72 }
 73 
 74 static void mv64x60_wdt_handler_enable(void)
 75 {
 76         if (!test_and_set_bit(MV64x60_WDOG_FLAG_ENABLED, &wdt_flags)) {
 77                 /* Write 01 followed by 10 to CTL1 */
 78                 mv64x60_wdt_reg_write(MV64x60_WDC_CTL1(0x01));
 79                 mv64x60_wdt_reg_write(MV64x60_WDC_CTL1(0x02));
 80                 printk(KERN_NOTICE "mv64x60_wdt: watchdog activated\n");
 81         }
 82 }
 83 
 84 static int mv64x60_wdt_open(struct inode *inode, struct file *file)
 85 {
 86         if (test_and_set_bit(MV64x60_WDOG_FLAG_OPENED, &wdt_flags))
 87                 return -EBUSY;
 88 
 89         mv64x60_wdt_service();
 90         mv64x60_wdt_handler_enable();
 91 
 92         nonseekable_open(inode, file);
 93 
 94         return 0;
 95 }
 96 
 97 static int mv64x60_wdt_release(struct inode *inode, struct file *file)
 98 {
 99         mv64x60_wdt_service();
100 
101 #if !defined(CONFIG_WATCHDOG_NOWAYOUT)
102         mv64x60_wdt_handler_disable();
103 #endif
104 
105         clear_bit(MV64x60_WDOG_FLAG_OPENED, &wdt_flags);
106 
107         return 0;
108 }
109 
110 static ssize_t mv64x60_wdt_write(struct file *file, const char __user *data,
111                                  size_t len, loff_t * ppos)
112 {
113         if (len)
114                 mv64x60_wdt_service();
115 
116         return len;
117 }
118 
119 static int mv64x60_wdt_ioctl(struct inode *inode, struct file *file,
120                              unsigned int cmd, unsigned long arg)
121 {
122         int timeout;
123         void __user *argp = (void __user *)arg;
124         static struct watchdog_info info = {
125                 .options = WDIOF_KEEPALIVEPING,
126                 .firmware_version = 0,
127                 .identity = "MV64x60 watchdog",
128         };
129 
130         switch (cmd) {
131         case WDIOC_GETSUPPORT:
132                 if (copy_to_user(argp, &info, sizeof(info)))
133                         return -EFAULT;
134                 break;
135 
136         case WDIOC_GETSTATUS:
137         case WDIOC_GETBOOTSTATUS:
138                 if (put_user(wdt_status, (int __user *)argp))
139                         return -EFAULT;
140                 wdt_status &= ~WDIOF_KEEPALIVEPING;
141                 break;
142 
143         case WDIOC_GETTEMP:
144                 return -EOPNOTSUPP;
145 
146         case WDIOC_SETOPTIONS:
147                 return -EOPNOTSUPP;
148 
149         case WDIOC_KEEPALIVE:
150                 mv64x60_wdt_service();
151                 wdt_status |= WDIOF_KEEPALIVEPING;
152                 break;
153 
154         case WDIOC_SETTIMEOUT:
155                 return -EOPNOTSUPP;
156 
157         case WDIOC_GETTIMEOUT:
158                 timeout = mv64x60_wdt_timeout * HZ;
159                 if (put_user(timeout, (int __user *)argp))
160                         return -EFAULT;
161                 break;
162 
163         default:
164                 return -ENOIOCTLCMD;
165         }
166 
167         return 0;
168 }
169 
170 static struct file_operations mv64x60_wdt_fops = {
171         .owner = THIS_MODULE,
172         .llseek = no_llseek,
173         .write = mv64x60_wdt_write,
174         .ioctl = mv64x60_wdt_ioctl,
175         .open = mv64x60_wdt_open,
176         .release = mv64x60_wdt_release,
177 };
178 
179 static struct miscdevice mv64x60_wdt_miscdev = {
180         .minor = WATCHDOG_MINOR,
181         .name = "watchdog",
182         .fops = &mv64x60_wdt_fops,
183 };
184 
185 static int __devinit mv64x60_wdt_probe(struct platform_device *dev)
186 {
187         struct mv64x60_wdt_pdata *pdata = dev->dev.platform_data;
188         int bus_clk = 133;
189 
190         mv64x60_wdt_timeout = 10;
191         if (pdata) {
192                 mv64x60_wdt_timeout = pdata->timeout;
193                 bus_clk = pdata->bus_clk;
194         }
195 
196         mv64x60_regs = mv64x60_get_bridge_vbase();
197 
198         writel((mv64x60_wdt_timeout * (bus_clk * 1000000)) >> 8,
199                mv64x60_regs + MV64x60_WDT_WDC);
200 
201         return misc_register(&mv64x60_wdt_miscdev);
202 }
203 
204 static int __devexit mv64x60_wdt_remove(struct platform_device *dev)
205 {
206         misc_deregister(&mv64x60_wdt_miscdev);
207 
208         mv64x60_wdt_service();
209         mv64x60_wdt_handler_disable();
210 
211         return 0;
212 }
213 
214 static struct platform_driver mv64x60_wdt_driver = {
215         .probe = mv64x60_wdt_probe,
216         .remove = __devexit_p(mv64x60_wdt_remove),
217         .driver = {
218                 .owner = THIS_MODULE,
219                 .name = MV64x60_WDT_NAME,
220         },
221 };
222 
223 static struct platform_device *mv64x60_wdt_dev;
224 
225 static int __init mv64x60_wdt_init(void)
226 {
227         int ret;
228 
229         printk(KERN_INFO "MV64x60 watchdog driver\n");
230 
231         mv64x60_wdt_dev = platform_device_alloc(MV64x60_WDT_NAME, -1);
232         if (!mv64x60_wdt_dev) {
233                 ret = -ENOMEM;
234                 goto out;
235         }
236 
237         ret = platform_device_add(mv64x60_wdt_dev);
238         if (ret) {
239                 platform_device_put(mv64x60_wdt_dev);
240                 goto out;
241         }
242 
243         ret = platform_driver_register(&mv64x60_wdt_driver);
244         if (ret) {
245                 platform_device_unregister(mv64x60_wdt_dev);
246                 goto out;
247         }
248 
249  out:
250         return ret;
251 }
252 
253 static void __exit mv64x60_wdt_exit(void)
254 {
255         platform_driver_unregister(&mv64x60_wdt_driver);
256         platform_device_unregister(mv64x60_wdt_dev);
257 }
258 
259 module_init(mv64x60_wdt_init);
260 module_exit(mv64x60_wdt_exit);
261 
262 MODULE_AUTHOR("James Chapman <jchapman@katalix.com>");
263 MODULE_DESCRIPTION("MV64x60 watchdog driver");
264 MODULE_LICENSE("GPL");
265 MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
266 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.