rc32434_wdt.c (703a3cd72817e99201cef84a8a7aecc60b2b3581) | rc32434_wdt.c (9b655e07d77e3b1a00c1c8302e2ef3b7fb719de3) |
---|---|
1/* 2 * IDT Interprise 79RC32434 watchdog driver 3 * 4 * Copyright (C) 2006, Ondrej Zajicek <santiago@crfreenet.org> 5 * Copyright (C) 2008, Florian Fainelli <florian@openwrt.org> 6 * 7 * based on 8 * SoftDog 0.05: A Software Watchdog Device 9 * 10 * (c) Copyright 1996 Alan Cox <alan@lxorguk.ukuu.org.uk>, 11 * All Rights Reserved. 12 * 13 * This program is free software; you can redistribute it and/or 14 * modify it under the terms of the GNU General Public License 15 * as published by the Free Software Foundation; either version 16 * 2 of the License, or (at your option) any later version. 17 * 18 */ 19 | 1/* 2 * IDT Interprise 79RC32434 watchdog driver 3 * 4 * Copyright (C) 2006, Ondrej Zajicek <santiago@crfreenet.org> 5 * Copyright (C) 2008, Florian Fainelli <florian@openwrt.org> 6 * 7 * based on 8 * SoftDog 0.05: A Software Watchdog Device 9 * 10 * (c) Copyright 1996 Alan Cox <alan@lxorguk.ukuu.org.uk>, 11 * All Rights Reserved. 12 * 13 * This program is free software; you can redistribute it and/or 14 * modify it under the terms of the GNU General Public License 15 * as published by the Free Software Foundation; either version 16 * 2 of the License, or (at your option) any later version. 17 * 18 */ 19 |
20#include <linux/module.h> 21#include <linux/types.h> 22#include <linux/kernel.h> 23#include <linux/fs.h> 24#include <linux/mm.h> 25#include <linux/miscdevice.h> 26#include <linux/watchdog.h> 27#include <linux/reboot.h> 28#include <linux/smp_lock.h> 29#include <linux/init.h> 30#include <linux/platform_device.h> 31#include <linux/uaccess.h> | 20#include <linux/module.h> /* For module specific items */ 21#include <linux/moduleparam.h> /* For new moduleparam's */ 22#include <linux/types.h> /* For standard types (like size_t) */ 23#include <linux/errno.h> /* For the -ENODEV/... values */ 24#include <linux/kernel.h> /* For printk/panic/... */ 25#include <linux/fs.h> /* For file operations */ 26#include <linux/miscdevice.h> /* For MODULE_ALIAS_MISCDEV 27 (WATCHDOG_MINOR) */ 28#include <linux/watchdog.h> /* For the watchdog specific items */ 29#include <linux/init.h> /* For __init/__exit/... */ 30#include <linux/platform_device.h> /* For platform_driver framework */ 31#include <linux/uaccess.h> /* For copy_to_user/put_user/... */ |
32 | 32 |
33#include <asm/bootinfo.h> 34#include <asm/time.h> 35#include <asm/mach-rc32434/integ.h> | 33#include <asm/mach-rc32434/integ.h> /* For the Watchdog registers */ |
36 | 34 |
35#define PFX KBUILD_MODNAME ": " 36 |
|
37#define VERSION "0.4" 38 39static struct { 40 unsigned long inuse; 41} rc32434_wdt_device; 42 43static struct integ __iomem *wdt_reg; 44 --- 40 unchanged lines hidden (view full) --- 85 86 SET_BITS(wdt_reg->errcs, or, nand); 87 88 /* reset WTC timeout bit and enable WDT */ 89 nand = 1 << RC32434_WTC_TO; 90 or = 1 << RC32434_WTC_EN; 91 92 SET_BITS(wdt_reg->wtc, or, nand); | 37#define VERSION "0.4" 38 39static struct { 40 unsigned long inuse; 41} rc32434_wdt_device; 42 43static struct integ __iomem *wdt_reg; 44 --- 40 unchanged lines hidden (view full) --- 85 86 SET_BITS(wdt_reg->errcs, or, nand); 87 88 /* reset WTC timeout bit and enable WDT */ 89 nand = 1 << RC32434_WTC_TO; 90 or = 1 << RC32434_WTC_EN; 91 92 SET_BITS(wdt_reg->wtc, or, nand); |
93 94 printk(KERN_INFO PFX "Started watchdog timer.\n"); |
|
93} 94 95static void rc32434_wdt_stop(void) 96{ 97 /* Disable WDT */ 98 SET_BITS(wdt_reg->wtc, 0, 1 << RC32434_WTC_EN); | 95} 96 97static void rc32434_wdt_stop(void) 98{ 99 /* Disable WDT */ 100 SET_BITS(wdt_reg->wtc, 0, 1 << RC32434_WTC_EN); |
101 102 printk(KERN_INFO PFX "Stopped watchdog timer.\n"); |
|
99} 100 101static int rc32434_wdt_set(int new_timeout) 102{ 103 int max_to = WTCOMP2SEC((u32)-1); 104 105 if (new_timeout < 0 || new_timeout > max_to) { | 103} 104 105static int rc32434_wdt_set(int new_timeout) 106{ 107 int max_to = WTCOMP2SEC((u32)-1); 108 109 if (new_timeout < 0 || new_timeout > max_to) { |
106 printk(KERN_ERR KBUILD_MODNAME 107 ": timeout value must be between 0 and %d", | 110 printk(KERN_ERR PFX "timeout value must be between 0 and %d", |
108 max_to); 109 return -EINVAL; 110 } 111 timeout = new_timeout; 112 writel(SEC2WTCOMP(timeout), &wdt_reg->wtcompare); 113 114 return 0; 115} --- 16 unchanged lines hidden (view full) --- 132 133 return nonseekable_open(inode, file); 134} 135 136static int rc32434_wdt_release(struct inode *inode, struct file *file) 137{ 138 if (expect_close == 42) { 139 rc32434_wdt_stop(); | 111 max_to); 112 return -EINVAL; 113 } 114 timeout = new_timeout; 115 writel(SEC2WTCOMP(timeout), &wdt_reg->wtcompare); 116 117 return 0; 118} --- 16 unchanged lines hidden (view full) --- 135 136 return nonseekable_open(inode, file); 137} 138 139static int rc32434_wdt_release(struct inode *inode, struct file *file) 140{ 141 if (expect_close == 42) { 142 rc32434_wdt_stop(); |
140 printk(KERN_INFO KBUILD_MODNAME ": disabling watchdog timer\n"); | |
141 module_put(THIS_MODULE); 142 } else { | 143 module_put(THIS_MODULE); 144 } else { |
143 printk(KERN_CRIT KBUILD_MODNAME 144 ": device closed unexpectedly. WDT will not stop !\n"); | 145 printk(KERN_CRIT PFX 146 "device closed unexpectedly. WDT will not stop!\n"); |
145 rc32434_wdt_ping(); 146 } 147 clear_bit(0, &rc32434_wdt_device.inuse); 148 return 0; 149} 150 151static ssize_t rc32434_wdt_write(struct file *file, const char *data, 152 size_t len, loff_t *ppos) --- 27 unchanged lines hidden (view full) --- 180 unsigned int value; 181 static struct watchdog_info ident = { 182 .options = WDIOF_SETTIMEOUT | 183 WDIOF_KEEPALIVEPING | 184 WDIOF_MAGICCLOSE, 185 .identity = "RC32434_WDT Watchdog", 186 }; 187 switch (cmd) { | 147 rc32434_wdt_ping(); 148 } 149 clear_bit(0, &rc32434_wdt_device.inuse); 150 return 0; 151} 152 153static ssize_t rc32434_wdt_write(struct file *file, const char *data, 154 size_t len, loff_t *ppos) --- 27 unchanged lines hidden (view full) --- 182 unsigned int value; 183 static struct watchdog_info ident = { 184 .options = WDIOF_SETTIMEOUT | 185 WDIOF_KEEPALIVEPING | 186 WDIOF_MAGICCLOSE, 187 .identity = "RC32434_WDT Watchdog", 188 }; 189 switch (cmd) { |
188 case WDIOC_KEEPALIVE: 189 rc32434_wdt_ping(); | 190 case WDIOC_GETSUPPORT: 191 if (copy_to_user(argp, &ident, sizeof(ident))) 192 return -EFAULT; |
190 break; 191 case WDIOC_GETSTATUS: 192 case WDIOC_GETBOOTSTATUS: 193 value = 0; 194 if (copy_to_user(argp, &value, sizeof(int))) 195 return -EFAULT; 196 break; | 193 break; 194 case WDIOC_GETSTATUS: 195 case WDIOC_GETBOOTSTATUS: 196 value = 0; 197 if (copy_to_user(argp, &value, sizeof(int))) 198 return -EFAULT; 199 break; |
197 case WDIOC_GETSUPPORT: 198 if (copy_to_user(argp, &ident, sizeof(ident))) 199 return -EFAULT; 200 break; | |
201 case WDIOC_SETOPTIONS: 202 if (copy_from_user(&value, argp, sizeof(int))) 203 return -EFAULT; 204 switch (value) { 205 case WDIOS_ENABLECARD: 206 rc32434_wdt_start(); 207 break; 208 case WDIOS_DISABLECARD: 209 rc32434_wdt_stop(); 210 break; 211 default: 212 return -EINVAL; 213 } 214 break; | 200 case WDIOC_SETOPTIONS: 201 if (copy_from_user(&value, argp, sizeof(int))) 202 return -EFAULT; 203 switch (value) { 204 case WDIOS_ENABLECARD: 205 rc32434_wdt_start(); 206 break; 207 case WDIOS_DISABLECARD: 208 rc32434_wdt_stop(); 209 break; 210 default: 211 return -EINVAL; 212 } 213 break; |
214 case WDIOC_KEEPALIVE: 215 rc32434_wdt_ping(); 216 break; |
|
215 case WDIOC_SETTIMEOUT: 216 if (copy_from_user(&new_timeout, argp, sizeof(int))) 217 return -EFAULT; 218 if (rc32434_wdt_set(new_timeout)) 219 return -EINVAL; 220 /* Fall through */ 221 case WDIOC_GETTIMEOUT: 222 return copy_to_user(argp, &timeout, sizeof(int)); --- 14 unchanged lines hidden (view full) --- 237}; 238 239static struct miscdevice rc32434_wdt_miscdev = { 240 .minor = WATCHDOG_MINOR, 241 .name = "watchdog", 242 .fops = &rc32434_wdt_fops, 243}; 244 | 217 case WDIOC_SETTIMEOUT: 218 if (copy_from_user(&new_timeout, argp, sizeof(int))) 219 return -EFAULT; 220 if (rc32434_wdt_set(new_timeout)) 221 return -EINVAL; 222 /* Fall through */ 223 case WDIOC_GETTIMEOUT: 224 return copy_to_user(argp, &timeout, sizeof(int)); --- 14 unchanged lines hidden (view full) --- 239}; 240 241static struct miscdevice rc32434_wdt_miscdev = { 242 .minor = WATCHDOG_MINOR, 243 .name = "watchdog", 244 .fops = &rc32434_wdt_fops, 245}; 246 |
245static char banner[] __devinitdata = KERN_INFO KBUILD_MODNAME 246 ": Watchdog Timer version " VERSION ", timer margin: %d sec\n"; | 247static char banner[] __devinitdata = KERN_INFO PFX 248 "Watchdog Timer version " VERSION ", timer margin: %d sec\n"; |
247 248static int __devinit rc32434_wdt_probe(struct platform_device *pdev) 249{ 250 int ret; 251 struct resource *r; 252 253 r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rb532_wdt_res"); 254 if (!r) { | 249 250static int __devinit rc32434_wdt_probe(struct platform_device *pdev) 251{ 252 int ret; 253 struct resource *r; 254 255 r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rb532_wdt_res"); 256 if (!r) { |
255 printk(KERN_ERR KBUILD_MODNAME 256 "failed to retrieve resources\n"); | 257 printk(KERN_ERR PFX "failed to retrieve resources\n"); |
257 return -ENODEV; 258 } 259 260 wdt_reg = ioremap_nocache(r->start, r->end - r->start); 261 if (!wdt_reg) { | 258 return -ENODEV; 259 } 260 261 wdt_reg = ioremap_nocache(r->start, r->end - r->start); 262 if (!wdt_reg) { |
262 printk(KERN_ERR KBUILD_MODNAME 263 "failed to remap I/O resources\n"); | 263 printk(KERN_ERR PFX "failed to remap I/O resources\n"); |
264 return -ENXIO; 265 } 266 267 ret = misc_register(&rc32434_wdt_miscdev); 268 if (ret < 0) { | 264 return -ENXIO; 265 } 266 267 ret = misc_register(&rc32434_wdt_miscdev); 268 if (ret < 0) { |
269 printk(KERN_ERR KBUILD_MODNAME 270 "failed to register watchdog device\n"); | 269 printk(KERN_ERR PFX "failed to register watchdog device\n"); |
271 goto unmap; 272 } 273 274 printk(banner, timeout); 275 276 return 0; 277 278unmap: 279 iounmap(wdt_reg); 280 return ret; 281} 282 283static int __devexit rc32434_wdt_remove(struct platform_device *pdev) 284{ 285 misc_deregister(&rc32434_wdt_miscdev); 286 iounmap(wdt_reg); 287 return 0; 288} 289 | 270 goto unmap; 271 } 272 273 printk(banner, timeout); 274 275 return 0; 276 277unmap: 278 iounmap(wdt_reg); 279 return ret; 280} 281 282static int __devexit rc32434_wdt_remove(struct platform_device *pdev) 283{ 284 misc_deregister(&rc32434_wdt_miscdev); 285 iounmap(wdt_reg); 286 return 0; 287} 288 |
290static struct platform_driver rc32434_wdt = { | 289static struct platform_driver rc32434_wdt_driver = { |
291 .probe = rc32434_wdt_probe, 292 .remove = __devexit_p(rc32434_wdt_remove), 293 .driver = { 294 .name = "rc32434_wdt", 295 } 296}; 297 298static int __init rc32434_wdt_init(void) 299{ | 290 .probe = rc32434_wdt_probe, 291 .remove = __devexit_p(rc32434_wdt_remove), 292 .driver = { 293 .name = "rc32434_wdt", 294 } 295}; 296 297static int __init rc32434_wdt_init(void) 298{ |
300 return platform_driver_register(&rc32434_wdt); | 299 return platform_driver_register(&rc32434_wdt_driver); |
301} 302 303static void __exit rc32434_wdt_exit(void) 304{ | 300} 301 302static void __exit rc32434_wdt_exit(void) 303{ |
305 platform_driver_unregister(&rc32434_wdt); | 304 platform_driver_unregister(&rc32434_wdt_driver); |
306} 307 308module_init(rc32434_wdt_init); 309module_exit(rc32434_wdt_exit); 310 311MODULE_AUTHOR("Ondrej Zajicek <santiago@crfreenet.org>," 312 "Florian Fainelli <florian@openwrt.org>"); 313MODULE_DESCRIPTION("Driver for the IDT RC32434 SoC watchdog"); 314MODULE_LICENSE("GPL"); 315MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); | 305} 306 307module_init(rc32434_wdt_init); 308module_exit(rc32434_wdt_exit); 309 310MODULE_AUTHOR("Ondrej Zajicek <santiago@crfreenet.org>," 311 "Florian Fainelli <florian@openwrt.org>"); 312MODULE_DESCRIPTION("Driver for the IDT RC32434 SoC watchdog"); 313MODULE_LICENSE("GPL"); 314MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); |