Merge master.kernel.org:/pub/scm/linux/kernel/git/wim/linux-2.6-watchdog

+2251 -42
+72 -21
drivers/char/watchdog/Kconfig
··· 84 85 Not sure? It's safe to say N. 86 87 config IXP4XX_WATCHDOG 88 tristate "IXP4xx Watchdog" 89 depends on WATCHDOG && ARCH_IXP4XX ··· 108 which doesn't reset any peripherals. There are circumstances 109 where the watchdog will fail to reset the board correctly 110 (e.g., if the boot ROM is in an unreadable state). 111 - 112 - Say N if you are unsure. 113 - 114 - config IXP2000_WATCHDOG 115 - tristate "IXP2000 Watchdog" 116 - depends on WATCHDOG && ARCH_IXP2000 117 - help 118 - Say Y here if to include support for the watchdog timer 119 - in the Intel IXP2000(2400, 2800, 2850) network processors. 120 - This driver can be built as a module by choosing M. The module 121 - will be called ixp2000_wdt. 122 123 Say N if you are unsure. 124 ··· 233 234 Most people will say N. 235 236 config WAFER_WDT 237 tristate "ICP Wafer 5823 Single Board Computer Watchdog" 238 depends on WATCHDOG && X86 ··· 252 253 To compile this driver as a module, choose M here: the 254 module will be called wafer5823wdt. 255 256 config I8XX_TCO 257 tristate "Intel i8xx TCO Timer/Watchdog" ··· 318 You can compile this driver directly into the kernel, or use 319 it as a module. The module will be called sbc60xxwdt. 320 321 config CPU5_WDT 322 tristate "SMA CPU5 Watchdog" 323 depends on WATCHDOG && X86 ··· 369 370 Most people will say N. 371 372 config MACHZ_WDT 373 tristate "ZF MachZ Watchdog" 374 depends on WATCHDOG && X86 ··· 401 tristate "MPC8xx Watchdog Timer" 402 depends on WATCHDOG && 8xx 403 404 config BOOKE_WDT 405 tristate "PowerPC Book-E Watchdog Timer" 406 depends on WATCHDOG && (BOOKE || 4xx) 407 ---help--- 408 Please see Documentation/watchdog/watchdog-api.txt for 409 more information. 410 411 # MIPS Architecture 412 ··· 490 Say Y here to support the hardware watchdog capability on Sun RIO 491 machines. The watchdog timeout period is normally one minute but 492 can be changed with a boot-time parameter. 493 - 494 - # ppc64 RTAS watchdog 495 - config WATCHDOG_RTAS 496 - tristate "RTAS watchdog" 497 - depends on WATCHDOG && PPC_RTAS 498 - help 499 - This driver adds watchdog support for the RTAS watchdog. 500 - 501 - To compile this driver as a module, choose M here. The module 502 - will be called wdrtas. 503 504 # 505 # ISA-based Watchdog Cards
··· 84 85 Not sure? It's safe to say N. 86 87 + config IXP2000_WATCHDOG 88 + tristate "IXP2000 Watchdog" 89 + depends on WATCHDOG && ARCH_IXP2000 90 + help 91 + Say Y here if to include support for the watchdog timer 92 + in the Intel IXP2000(2400, 2800, 2850) network processors. 93 + This driver can be built as a module by choosing M. The module 94 + will be called ixp2000_wdt. 95 + 96 + Say N if you are unsure. 97 + 98 config IXP4XX_WATCHDOG 99 tristate "IXP4xx Watchdog" 100 depends on WATCHDOG && ARCH_IXP4XX ··· 97 which doesn't reset any peripherals. There are circumstances 98 where the watchdog will fail to reset the board correctly 99 (e.g., if the boot ROM is in an unreadable state). 100 101 Say N if you are unsure. 102 ··· 233 234 Most people will say N. 235 236 + config IBMASR 237 + tristate "IBM Automatic Server Restart" 238 + depends on WATCHDOG && X86 239 + help 240 + This is the driver for the IBM Automatic Server Restart watchdog 241 + timer builtin into some eServer xSeries machines. 242 + 243 + To compile this driver as a module, choose M here: the 244 + module will be called ibmasr. 245 + 246 config WAFER_WDT 247 tristate "ICP Wafer 5823 Single Board Computer Watchdog" 248 depends on WATCHDOG && X86 ··· 242 243 To compile this driver as a module, choose M here: the 244 module will be called wafer5823wdt. 245 + 246 + config I6300ESB_WDT 247 + tristate "Intel 6300ESB Timer/Watchdog" 248 + depends on WATCHDOG && X86 && PCI 249 + ---help--- 250 + Hardware driver for the watchdog timer built into the Intel 251 + 6300ESB controller hub. 252 + 253 + To compile this driver as a module, choose M here: the 254 + module will be called i6300esb. 255 256 config I8XX_TCO 257 tristate "Intel i8xx TCO Timer/Watchdog" ··· 298 You can compile this driver directly into the kernel, or use 299 it as a module. The module will be called sbc60xxwdt. 300 301 + config SBC8360_WDT 302 + tristate "SBC8360 Watchdog Timer" 303 + depends on WATCHDOG && X86 304 + ---help--- 305 + 306 + This is the driver for the hardware watchdog on the SBC8360 Single 307 + Board Computer produced by Axiomtek Co., Ltd. (www.axiomtek.com). 308 + 309 + To compile this driver as a module, choose M here: the 310 + module will be called sbc8360.ko. 311 + 312 + Most people will say N. 313 + 314 config CPU5_WDT 315 tristate "SMA CPU5 Watchdog" 316 depends on WATCHDOG && X86 ··· 336 337 Most people will say N. 338 339 + config W83977F_WDT 340 + tristate "W83977F (PCM-5335) Watchdog Timer" 341 + depends on WATCHDOG && X86 342 + ---help--- 343 + This is the driver for the hardware watchdog on the W83977F I/O chip 344 + as used in AAEON's PCM-5335 SBC (and likely others). This 345 + watchdog simply watches your kernel to make sure it doesn't freeze, 346 + and if it does, it reboots your computer after a certain amount of 347 + time. 348 + 349 + To compile this driver as a module, choose M here: the 350 + module will be called w83977f_wdt. 351 + 352 config MACHZ_WDT 353 tristate "ZF MachZ Watchdog" 354 depends on WATCHDOG && X86 ··· 355 tristate "MPC8xx Watchdog Timer" 356 depends on WATCHDOG && 8xx 357 358 + config MV64X60_WDT 359 + tristate "MV64X60 (Marvell Discovery) Watchdog Timer" 360 + depends on WATCHDOG && MV64X60 361 + 362 config BOOKE_WDT 363 tristate "PowerPC Book-E Watchdog Timer" 364 depends on WATCHDOG && (BOOKE || 4xx) 365 ---help--- 366 Please see Documentation/watchdog/watchdog-api.txt for 367 more information. 368 + 369 + # PPC64 Architecture 370 + 371 + config WATCHDOG_RTAS 372 + tristate "RTAS watchdog" 373 + depends on WATCHDOG && PPC_RTAS 374 + help 375 + This driver adds watchdog support for the RTAS watchdog. 376 + 377 + To compile this driver as a module, choose M here. The module 378 + will be called wdrtas. 379 380 # MIPS Architecture 381 ··· 429 Say Y here to support the hardware watchdog capability on Sun RIO 430 machines. The watchdog timeout period is normally one minute but 431 can be changed with a boot-time parameter. 432 433 # 434 # ISA-based Watchdog Cards
+6 -1
drivers/char/watchdog/Makefile
··· 39 obj-$(CONFIG_SC520_WDT) += sc520_wdt.o 40 obj-$(CONFIG_EUROTECH_WDT) += eurotechwdt.o 41 obj-$(CONFIG_IB700_WDT) += ib700wdt.o 42 obj-$(CONFIG_WAFER_WDT) += wafer5823wdt.o 43 obj-$(CONFIG_I8XX_TCO) += i8xx_tco.o 44 obj-$(CONFIG_SC1200_WDT) += sc1200wdt.o 45 obj-$(CONFIG_SCx200_WDT) += scx200_wdt.o 46 obj-$(CONFIG_60XX_WDT) += sbc60xxwdt.o 47 obj-$(CONFIG_CPU5_WDT) += cpu5wdt.o 48 obj-$(CONFIG_W83627HF_WDT) += w83627hf_wdt.o 49 obj-$(CONFIG_W83877F_WDT) += w83877f_wdt.o 50 obj-$(CONFIG_MACHZ_WDT) += machzwd.o 51 52 # PowerPC Architecture 53 obj-$(CONFIG_8xx_WDT) += mpc8xx_wdt.o 54 55 # PPC64 Architecture 56 obj-$(CONFIG_WATCHDOG_RTAS) += wdrtas.o 57 - obj-$(CONFIG_BOOKE_WDT) += booke_wdt.o 58 59 # MIPS Architecture 60 obj-$(CONFIG_INDYDOG) += indydog.o
··· 39 obj-$(CONFIG_SC520_WDT) += sc520_wdt.o 40 obj-$(CONFIG_EUROTECH_WDT) += eurotechwdt.o 41 obj-$(CONFIG_IB700_WDT) += ib700wdt.o 42 + obj-$(CONFIG_IBMASR) += ibmasr.o 43 obj-$(CONFIG_WAFER_WDT) += wafer5823wdt.o 44 + obj-$(CONFIG_I6300ESB_WDT) += i6300esb.o 45 obj-$(CONFIG_I8XX_TCO) += i8xx_tco.o 46 obj-$(CONFIG_SC1200_WDT) += sc1200wdt.o 47 obj-$(CONFIG_SCx200_WDT) += scx200_wdt.o 48 obj-$(CONFIG_60XX_WDT) += sbc60xxwdt.o 49 + obj-$(CONFIG_SBC8360_WDT) += sbc8360.o 50 obj-$(CONFIG_CPU5_WDT) += cpu5wdt.o 51 obj-$(CONFIG_W83627HF_WDT) += w83627hf_wdt.o 52 obj-$(CONFIG_W83877F_WDT) += w83877f_wdt.o 53 + obj-$(CONFIG_W83977F_WDT) += w83977f_wdt.o 54 obj-$(CONFIG_MACHZ_WDT) += machzwd.o 55 56 # PowerPC Architecture 57 obj-$(CONFIG_8xx_WDT) += mpc8xx_wdt.o 58 + obj-$(CONFIG_MV64X60_WDT) += mv64x60_wdt.o 59 + obj-$(CONFIG_BOOKE_WDT) += booke_wdt.o 60 61 # PPC64 Architecture 62 obj-$(CONFIG_WATCHDOG_RTAS) += wdrtas.o 63 64 # MIPS Architecture 65 obj-$(CONFIG_INDYDOG) += indydog.o
+527
drivers/char/watchdog/i6300esb.c
···
··· 1 + /* 2 + * i6300esb: Watchdog timer driver for Intel 6300ESB chipset 3 + * 4 + * (c) Copyright 2004 Google Inc. 5 + * (c) Copyright 2005 David H�rdeman <david@2gen.com> 6 + * 7 + * This program is free software; you can redistribute it and/or 8 + * modify it under the terms of the GNU General Public License 9 + * as published by the Free Software Foundation; either version 10 + * 2 of the License, or (at your option) any later version. 11 + * 12 + * based on i810-tco.c which is in turn based on softdog.c 13 + * 14 + * The timer is implemented in the following I/O controller hubs: 15 + * (See the intel documentation on http://developer.intel.com.) 16 + * 6300ESB chip : document number 300641-003 17 + * 18 + * 2004YYZZ Ross Biro 19 + * Initial version 0.01 20 + * 2004YYZZ Ross Biro 21 + * Version 0.02 22 + * 20050210 David H�rdeman <david@2gen.com> 23 + * Ported driver to kernel 2.6 24 + */ 25 + 26 + /* 27 + * Includes, defines, variables, module parameters, ... 28 + */ 29 + 30 + #include <linux/module.h> 31 + #include <linux/types.h> 32 + #include <linux/kernel.h> 33 + #include <linux/fs.h> 34 + #include <linux/mm.h> 35 + #include <linux/miscdevice.h> 36 + #include <linux/watchdog.h> 37 + #include <linux/reboot.h> 38 + #include <linux/init.h> 39 + #include <linux/pci.h> 40 + #include <linux/ioport.h> 41 + 42 + #include <asm/uaccess.h> 43 + #include <asm/io.h> 44 + 45 + /* Module and version information */ 46 + #define ESB_VERSION "0.03" 47 + #define ESB_MODULE_NAME "i6300ESB timer" 48 + #define ESB_DRIVER_NAME ESB_MODULE_NAME ", v" ESB_VERSION 49 + #define PFX ESB_MODULE_NAME ": " 50 + 51 + /* PCI configuration registers */ 52 + #define ESB_CONFIG_REG 0x60 /* Config register */ 53 + #define ESB_LOCK_REG 0x68 /* WDT lock register */ 54 + 55 + /* Memory mapped registers */ 56 + #define ESB_TIMER1_REG BASEADDR + 0x00 /* Timer1 value after each reset */ 57 + #define ESB_TIMER2_REG BASEADDR + 0x04 /* Timer2 value after each reset */ 58 + #define ESB_GINTSR_REG BASEADDR + 0x08 /* General Interrupt Status Register */ 59 + #define ESB_RELOAD_REG BASEADDR + 0x0c /* Reload register */ 60 + 61 + /* Lock register bits */ 62 + #define ESB_WDT_FUNC ( 0x01 << 2 ) /* Watchdog functionality */ 63 + #define ESB_WDT_ENABLE ( 0x01 << 1 ) /* Enable WDT */ 64 + #define ESB_WDT_LOCK ( 0x01 << 0 ) /* Lock (nowayout) */ 65 + 66 + /* Config register bits */ 67 + #define ESB_WDT_REBOOT ( 0x01 << 5 ) /* Enable reboot on timeout */ 68 + #define ESB_WDT_FREQ ( 0x01 << 2 ) /* Decrement frequency */ 69 + #define ESB_WDT_INTTYPE ( 0x11 << 0 ) /* Interrupt type on timer1 timeout */ 70 + 71 + /* Reload register bits */ 72 + #define ESB_WDT_RELOAD ( 0x01 << 8 ) /* prevent timeout */ 73 + 74 + /* Magic constants */ 75 + #define ESB_UNLOCK1 0x80 /* Step 1 to unlock reset registers */ 76 + #define ESB_UNLOCK2 0x86 /* Step 2 to unlock reset registers */ 77 + 78 + /* internal variables */ 79 + static void __iomem *BASEADDR; 80 + static spinlock_t esb_lock; /* Guards the hardware */ 81 + static unsigned long timer_alive; 82 + static struct pci_dev *esb_pci; 83 + static unsigned short triggered; /* The status of the watchdog upon boot */ 84 + static char esb_expect_close; 85 + 86 + /* module parameters */ 87 + #define WATCHDOG_HEARTBEAT 30 /* 30 sec default heartbeat (1<heartbeat<2*1023) */ 88 + static int heartbeat = WATCHDOG_HEARTBEAT; /* in seconds */ 89 + module_param(heartbeat, int, 0); 90 + MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (1<heartbeat<2046, default=" __MODULE_STRING(WATCHDOG_HEARTBEAT) ")"); 91 + 92 + static int nowayout = WATCHDOG_NOWAYOUT; 93 + module_param(nowayout, int, 0); 94 + MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); 95 + 96 + /* 97 + * Some i6300ESB specific functions 98 + */ 99 + 100 + /* 101 + * Prepare for reloading the timer by unlocking the proper registers. 102 + * This is performed by first writing 0x80 followed by 0x86 to the 103 + * reload register. After this the appropriate registers can be written 104 + * to once before they need to be unlocked again. 105 + */ 106 + static inline void esb_unlock_registers(void) { 107 + writeb(ESB_UNLOCK1, ESB_RELOAD_REG); 108 + writeb(ESB_UNLOCK2, ESB_RELOAD_REG); 109 + } 110 + 111 + static void esb_timer_start(void) 112 + { 113 + u8 val; 114 + 115 + /* Enable or Enable + Lock? */ 116 + val = 0x02 | (nowayout ? 0x01 : 0x00); 117 + 118 + pci_write_config_byte(esb_pci, ESB_LOCK_REG, val); 119 + } 120 + 121 + static int esb_timer_stop(void) 122 + { 123 + u8 val; 124 + 125 + spin_lock(&esb_lock); 126 + /* First, reset timers as suggested by the docs */ 127 + esb_unlock_registers(); 128 + writew(ESB_WDT_RELOAD, ESB_RELOAD_REG); 129 + /* Then disable the WDT */ 130 + pci_write_config_byte(esb_pci, ESB_LOCK_REG, 0x0); 131 + pci_read_config_byte(esb_pci, ESB_LOCK_REG, &val); 132 + spin_unlock(&esb_lock); 133 + 134 + /* Returns 0 if the timer was disabled, non-zero otherwise */ 135 + return (val & 0x01); 136 + } 137 + 138 + static void esb_timer_keepalive(void) 139 + { 140 + spin_lock(&esb_lock); 141 + esb_unlock_registers(); 142 + writew(ESB_WDT_RELOAD, ESB_RELOAD_REG); 143 + /* FIXME: Do we need to flush anything here? */ 144 + spin_unlock(&esb_lock); 145 + } 146 + 147 + static int esb_timer_set_heartbeat(int time) 148 + { 149 + u32 val; 150 + 151 + if (time < 0x1 || time > (2 * 0x03ff)) 152 + return -EINVAL; 153 + 154 + spin_lock(&esb_lock); 155 + 156 + /* We shift by 9, so if we are passed a value of 1 sec, 157 + * val will be 1 << 9 = 512, then write that to two 158 + * timers => 2 * 512 = 1024 (which is decremented at 1KHz) 159 + */ 160 + val = time << 9; 161 + 162 + /* Write timer 1 */ 163 + esb_unlock_registers(); 164 + writel(val, ESB_TIMER1_REG); 165 + 166 + /* Write timer 2 */ 167 + esb_unlock_registers(); 168 + writel(val, ESB_TIMER2_REG); 169 + 170 + /* Reload */ 171 + esb_unlock_registers(); 172 + writew(ESB_WDT_RELOAD, ESB_RELOAD_REG); 173 + 174 + /* FIXME: Do we need to flush everything out? */ 175 + 176 + /* Done */ 177 + heartbeat = time; 178 + spin_unlock(&esb_lock); 179 + return 0; 180 + } 181 + 182 + static int esb_timer_read (void) 183 + { 184 + u32 count; 185 + 186 + /* This isn't documented, and doesn't take into 187 + * acount which stage is running, but it looks 188 + * like a 20 bit count down, so we might as well report it. 189 + */ 190 + pci_read_config_dword(esb_pci, 0x64, &count); 191 + return (int)count; 192 + } 193 + 194 + /* 195 + * /dev/watchdog handling 196 + */ 197 + 198 + static int esb_open (struct inode *inode, struct file *file) 199 + { 200 + /* /dev/watchdog can only be opened once */ 201 + if (test_and_set_bit(0, &timer_alive)) 202 + return -EBUSY; 203 + 204 + /* Reload and activate timer */ 205 + esb_timer_keepalive (); 206 + esb_timer_start (); 207 + 208 + return nonseekable_open(inode, file); 209 + } 210 + 211 + static int esb_release (struct inode *inode, struct file *file) 212 + { 213 + /* Shut off the timer. */ 214 + if (esb_expect_close == 42) { 215 + esb_timer_stop (); 216 + } else { 217 + printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n"); 218 + esb_timer_keepalive (); 219 + } 220 + clear_bit(0, &timer_alive); 221 + esb_expect_close = 0; 222 + return 0; 223 + } 224 + 225 + static ssize_t esb_write (struct file *file, const char __user *data, 226 + size_t len, loff_t * ppos) 227 + { 228 + /* See if we got the magic character 'V' and reload the timer */ 229 + if (len) { 230 + if (!nowayout) { 231 + size_t i; 232 + 233 + /* note: just in case someone wrote the magic character 234 + * five months ago... */ 235 + esb_expect_close = 0; 236 + 237 + /* scan to see whether or not we got the magic character */ 238 + for (i = 0; i != len; i++) { 239 + char c; 240 + if(get_user(c, data+i)) 241 + return -EFAULT; 242 + if (c == 'V') 243 + esb_expect_close = 42; 244 + } 245 + } 246 + 247 + /* someone wrote to us, we should reload the timer */ 248 + esb_timer_keepalive (); 249 + } 250 + return len; 251 + } 252 + 253 + static int esb_ioctl (struct inode *inode, struct file *file, 254 + unsigned int cmd, unsigned long arg) 255 + { 256 + int new_options, retval = -EINVAL; 257 + int new_heartbeat; 258 + void __user *argp = (void __user *)arg; 259 + int __user *p = argp; 260 + static struct watchdog_info ident = { 261 + .options = WDIOF_SETTIMEOUT | 262 + WDIOF_KEEPALIVEPING | 263 + WDIOF_MAGICCLOSE, 264 + .firmware_version = 0, 265 + .identity = ESB_MODULE_NAME, 266 + }; 267 + 268 + switch (cmd) { 269 + case WDIOC_GETSUPPORT: 270 + return copy_to_user(argp, &ident, 271 + sizeof (ident)) ? -EFAULT : 0; 272 + 273 + case WDIOC_GETSTATUS: 274 + return put_user (esb_timer_read(), p); 275 + 276 + case WDIOC_GETBOOTSTATUS: 277 + return put_user (triggered, p); 278 + 279 + case WDIOC_KEEPALIVE: 280 + esb_timer_keepalive (); 281 + return 0; 282 + 283 + case WDIOC_SETOPTIONS: 284 + { 285 + if (get_user (new_options, p)) 286 + return -EFAULT; 287 + 288 + if (new_options & WDIOS_DISABLECARD) { 289 + esb_timer_stop (); 290 + retval = 0; 291 + } 292 + 293 + if (new_options & WDIOS_ENABLECARD) { 294 + esb_timer_keepalive (); 295 + esb_timer_start (); 296 + retval = 0; 297 + } 298 + 299 + return retval; 300 + } 301 + 302 + case WDIOC_SETTIMEOUT: 303 + { 304 + if (get_user(new_heartbeat, p)) 305 + return -EFAULT; 306 + 307 + if (esb_timer_set_heartbeat(new_heartbeat)) 308 + return -EINVAL; 309 + 310 + esb_timer_keepalive (); 311 + /* Fall */ 312 + } 313 + 314 + case WDIOC_GETTIMEOUT: 315 + return put_user(heartbeat, p); 316 + 317 + default: 318 + return -ENOIOCTLCMD; 319 + } 320 + } 321 + 322 + /* 323 + * Notify system 324 + */ 325 + 326 + static int esb_notify_sys (struct notifier_block *this, unsigned long code, void *unused) 327 + { 328 + if (code==SYS_DOWN || code==SYS_HALT) { 329 + /* Turn the WDT off */ 330 + esb_timer_stop (); 331 + } 332 + 333 + return NOTIFY_DONE; 334 + } 335 + 336 + /* 337 + * Kernel Interfaces 338 + */ 339 + 340 + static struct file_operations esb_fops = { 341 + .owner = THIS_MODULE, 342 + .llseek = no_llseek, 343 + .write = esb_write, 344 + .ioctl = esb_ioctl, 345 + .open = esb_open, 346 + .release = esb_release, 347 + }; 348 + 349 + static struct miscdevice esb_miscdev = { 350 + .minor = WATCHDOG_MINOR, 351 + .name = "watchdog", 352 + .fops = &esb_fops, 353 + }; 354 + 355 + static struct notifier_block esb_notifier = { 356 + .notifier_call = esb_notify_sys, 357 + }; 358 + 359 + /* 360 + * Data for PCI driver interface 361 + * 362 + * This data only exists for exporting the supported 363 + * PCI ids via MODULE_DEVICE_TABLE. We do not actually 364 + * register a pci_driver, because someone else might one day 365 + * want to register another driver on the same PCI id. 366 + */ 367 + static struct pci_device_id esb_pci_tbl[] = { 368 + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_9), }, 369 + { 0, }, /* End of list */ 370 + }; 371 + MODULE_DEVICE_TABLE (pci, esb_pci_tbl); 372 + 373 + /* 374 + * Init & exit routines 375 + */ 376 + 377 + static unsigned char __init esb_getdevice (void) 378 + { 379 + u8 val1; 380 + unsigned short val2; 381 + 382 + struct pci_dev *dev = NULL; 383 + /* 384 + * Find the PCI device 385 + */ 386 + 387 + for_each_pci_dev(dev) { 388 + if (pci_match_id(esb_pci_tbl, dev)) { 389 + esb_pci = dev; 390 + break; 391 + } 392 + } 393 + 394 + if (esb_pci) { 395 + if (pci_enable_device(esb_pci)) { 396 + printk (KERN_ERR PFX "failed to enable device\n"); 397 + goto err_devput; 398 + } 399 + 400 + if (pci_request_region(esb_pci, 0, ESB_MODULE_NAME)) { 401 + printk (KERN_ERR PFX "failed to request region\n"); 402 + goto err_disable; 403 + } 404 + 405 + BASEADDR = ioremap(pci_resource_start(esb_pci, 0), 406 + pci_resource_len(esb_pci, 0)); 407 + if (BASEADDR == NULL) { 408 + /* Something's wrong here, BASEADDR has to be set */ 409 + printk (KERN_ERR PFX "failed to get BASEADDR\n"); 410 + goto err_release; 411 + } 412 + 413 + /* 414 + * The watchdog has two timers, it can be setup so that the 415 + * expiry of timer1 results in an interrupt and the expiry of 416 + * timer2 results in a reboot. We set it to not generate 417 + * any interrupts as there is not much we can do with it 418 + * right now. 419 + * 420 + * We also enable reboots and set the timer frequency to 421 + * the PCI clock divided by 2^15 (approx 1KHz). 422 + */ 423 + pci_write_config_word(esb_pci, ESB_CONFIG_REG, 0x0003); 424 + 425 + /* Check that the WDT isn't already locked */ 426 + pci_read_config_byte(esb_pci, ESB_LOCK_REG, &val1); 427 + if (val1 & ESB_WDT_LOCK) 428 + printk (KERN_WARNING PFX "nowayout already set\n"); 429 + 430 + /* Set the timer to watchdog mode and disable it for now */ 431 + pci_write_config_byte(esb_pci, ESB_LOCK_REG, 0x00); 432 + 433 + /* Check if the watchdog was previously triggered */ 434 + esb_unlock_registers(); 435 + val2 = readw(ESB_RELOAD_REG); 436 + triggered = (val2 & (0x01 << 9) >> 9); 437 + 438 + /* Reset trigger flag and timers */ 439 + esb_unlock_registers(); 440 + writew((0x11 << 8), ESB_RELOAD_REG); 441 + 442 + /* Done */ 443 + return 1; 444 + 445 + err_release: 446 + pci_release_region(esb_pci, 0); 447 + err_disable: 448 + pci_disable_device(esb_pci); 449 + err_devput: 450 + pci_dev_put(esb_pci); 451 + } 452 + return 0; 453 + } 454 + 455 + static int __init watchdog_init (void) 456 + { 457 + int ret; 458 + 459 + spin_lock_init(&esb_lock); 460 + 461 + /* Check whether or not the hardware watchdog is there */ 462 + if (!esb_getdevice () || esb_pci == NULL) 463 + return -ENODEV; 464 + 465 + /* Check that the heartbeat value is within it's range ; if not reset to the default */ 466 + if (esb_timer_set_heartbeat (heartbeat)) { 467 + esb_timer_set_heartbeat (WATCHDOG_HEARTBEAT); 468 + printk(KERN_INFO PFX "heartbeat value must be 1<heartbeat<2046, using %d\n", 469 + heartbeat); 470 + } 471 + 472 + ret = register_reboot_notifier(&esb_notifier); 473 + if (ret != 0) { 474 + printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", 475 + ret); 476 + goto err_unmap; 477 + } 478 + 479 + ret = misc_register(&esb_miscdev); 480 + if (ret != 0) { 481 + printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", 482 + WATCHDOG_MINOR, ret); 483 + goto err_notifier; 484 + } 485 + 486 + esb_timer_stop (); 487 + 488 + printk (KERN_INFO PFX "initialized (0x%p). heartbeat=%d sec (nowayout=%d)\n", 489 + BASEADDR, heartbeat, nowayout); 490 + 491 + return 0; 492 + 493 + err_notifier: 494 + unregister_reboot_notifier(&esb_notifier); 495 + err_unmap: 496 + iounmap(BASEADDR); 497 + /* err_release: */ 498 + pci_release_region(esb_pci, 0); 499 + /* err_disable: */ 500 + pci_disable_device(esb_pci); 501 + /* err_devput: */ 502 + pci_dev_put(esb_pci); 503 + return ret; 504 + } 505 + 506 + static void __exit watchdog_cleanup (void) 507 + { 508 + /* Stop the timer before we leave */ 509 + if (!nowayout) 510 + esb_timer_stop (); 511 + 512 + /* Deregister */ 513 + misc_deregister(&esb_miscdev); 514 + unregister_reboot_notifier(&esb_notifier); 515 + iounmap(BASEADDR); 516 + pci_release_region(esb_pci, 0); 517 + pci_disable_device(esb_pci); 518 + pci_dev_put(esb_pci); 519 + } 520 + 521 + module_init(watchdog_init); 522 + module_exit(watchdog_cleanup); 523 + 524 + MODULE_AUTHOR("Ross Biro and David H�rdeman"); 525 + MODULE_DESCRIPTION("Watchdog driver for Intel 6300ESB chipsets"); 526 + MODULE_LICENSE("GPL"); 527 + MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
+405
drivers/char/watchdog/ibmasr.c
···
··· 1 + /* 2 + * IBM Automatic Server Restart driver. 3 + * 4 + * Copyright (c) 2005 Andrey Panin <pazke@donpac.ru> 5 + * 6 + * Based on driver written by Pete Reynolds. 7 + * Copyright (c) IBM Corporation, 1998-2004. 8 + * 9 + * This software may be used and distributed according to the terms 10 + * of the GNU Public License, incorporated herein by reference. 11 + */ 12 + 13 + #include <linux/config.h> 14 + #include <linux/fs.h> 15 + #include <linux/kernel.h> 16 + #include <linux/slab.h> 17 + #include <linux/module.h> 18 + #include <linux/pci.h> 19 + #include <linux/timer.h> 20 + #include <linux/miscdevice.h> 21 + #include <linux/watchdog.h> 22 + #include <linux/dmi.h> 23 + 24 + #include <asm/io.h> 25 + #include <asm/uaccess.h> 26 + 27 + 28 + enum { 29 + ASMTYPE_UNKNOWN, 30 + ASMTYPE_TOPAZ, 31 + ASMTYPE_JASPER, 32 + ASMTYPE_PEARL, 33 + ASMTYPE_JUNIPER, 34 + ASMTYPE_SPRUCE, 35 + }; 36 + 37 + #define PFX "ibmasr: " 38 + 39 + #define TOPAZ_ASR_REG_OFFSET 4 40 + #define TOPAZ_ASR_TOGGLE 0x40 41 + #define TOPAZ_ASR_DISABLE 0x80 42 + 43 + /* PEARL ASR S/W REGISTER SUPERIO PORT ADDRESSES */ 44 + #define PEARL_BASE 0xe04 45 + #define PEARL_WRITE 0xe06 46 + #define PEARL_READ 0xe07 47 + 48 + #define PEARL_ASR_DISABLE_MASK 0x80 /* bit 7: disable = 1, enable = 0 */ 49 + #define PEARL_ASR_TOGGLE_MASK 0x40 /* bit 6: 0, then 1, then 0 */ 50 + 51 + /* JASPER OFFSET FROM SIO BASE ADDR TO ASR S/W REGISTERS. */ 52 + #define JASPER_ASR_REG_OFFSET 0x38 53 + 54 + #define JASPER_ASR_DISABLE_MASK 0x01 /* bit 0: disable = 1, enable = 0 */ 55 + #define JASPER_ASR_TOGGLE_MASK 0x02 /* bit 1: 0, then 1, then 0 */ 56 + 57 + #define JUNIPER_BASE_ADDRESS 0x54b /* Base address of Juniper ASR */ 58 + #define JUNIPER_ASR_DISABLE_MASK 0x01 /* bit 0: disable = 1 enable = 0 */ 59 + #define JUNIPER_ASR_TOGGLE_MASK 0x02 /* bit 1: 0, then 1, then 0 */ 60 + 61 + #define SPRUCE_BASE_ADDRESS 0x118e /* Base address of Spruce ASR */ 62 + #define SPRUCE_ASR_DISABLE_MASK 0x01 /* bit 1: disable = 1 enable = 0 */ 63 + #define SPRUCE_ASR_TOGGLE_MASK 0x02 /* bit 0: 0, then 1, then 0 */ 64 + 65 + 66 + static int nowayout = WATCHDOG_NOWAYOUT; 67 + 68 + static unsigned long asr_is_open; 69 + static char asr_expect_close; 70 + 71 + static unsigned int asr_type, asr_base, asr_length; 72 + static unsigned int asr_read_addr, asr_write_addr; 73 + static unsigned char asr_toggle_mask, asr_disable_mask; 74 + 75 + static void asr_toggle(void) 76 + { 77 + unsigned char reg = inb(asr_read_addr); 78 + 79 + outb(reg & ~asr_toggle_mask, asr_write_addr); 80 + reg = inb(asr_read_addr); 81 + 82 + outb(reg | asr_toggle_mask, asr_write_addr); 83 + reg = inb(asr_read_addr); 84 + 85 + outb(reg & ~asr_toggle_mask, asr_write_addr); 86 + reg = inb(asr_read_addr); 87 + } 88 + 89 + static void asr_enable(void) 90 + { 91 + unsigned char reg; 92 + 93 + if (asr_type == ASMTYPE_TOPAZ) { 94 + /* asr_write_addr == asr_read_addr */ 95 + reg = inb(asr_read_addr); 96 + outb(reg & ~(TOPAZ_ASR_TOGGLE | TOPAZ_ASR_DISABLE), 97 + asr_read_addr); 98 + } else { 99 + /* 100 + * First make sure the hardware timer is reset by toggling 101 + * ASR hardware timer line. 102 + */ 103 + asr_toggle(); 104 + 105 + reg = inb(asr_read_addr); 106 + outb(reg & ~asr_disable_mask, asr_write_addr); 107 + } 108 + reg = inb(asr_read_addr); 109 + } 110 + 111 + static void asr_disable(void) 112 + { 113 + unsigned char reg = inb(asr_read_addr); 114 + 115 + if (asr_type == ASMTYPE_TOPAZ) 116 + /* asr_write_addr == asr_read_addr */ 117 + outb(reg | TOPAZ_ASR_TOGGLE | TOPAZ_ASR_DISABLE, 118 + asr_read_addr); 119 + else { 120 + outb(reg | asr_toggle_mask, asr_write_addr); 121 + reg = inb(asr_read_addr); 122 + 123 + outb(reg | asr_disable_mask, asr_write_addr); 124 + } 125 + reg = inb(asr_read_addr); 126 + } 127 + 128 + static int __init asr_get_base_address(void) 129 + { 130 + unsigned char low, high; 131 + const char *type = ""; 132 + 133 + asr_length = 1; 134 + 135 + switch (asr_type) { 136 + case ASMTYPE_TOPAZ: 137 + /* SELECT SuperIO CHIP FOR QUERYING (WRITE 0x07 TO BOTH 0x2E and 0x2F) */ 138 + outb(0x07, 0x2e); 139 + outb(0x07, 0x2f); 140 + 141 + /* SELECT AND READ THE HIGH-NIBBLE OF THE GPIO BASE ADDRESS */ 142 + outb(0x60, 0x2e); 143 + high = inb(0x2f); 144 + 145 + /* SELECT AND READ THE LOW-NIBBLE OF THE GPIO BASE ADDRESS */ 146 + outb(0x61, 0x2e); 147 + low = inb(0x2f); 148 + 149 + asr_base = (high << 16) | low; 150 + asr_read_addr = asr_write_addr = 151 + asr_base + TOPAZ_ASR_REG_OFFSET; 152 + asr_length = 5; 153 + 154 + break; 155 + 156 + case ASMTYPE_JASPER: 157 + type = "Jaspers "; 158 + 159 + /* FIXME: need to use pci_config_lock here, but it's not exported */ 160 + 161 + /* spin_lock_irqsave(&pci_config_lock, flags);*/ 162 + 163 + /* Select the SuperIO chip in the PCI I/O port register */ 164 + outl(0x8000f858, 0xcf8); 165 + 166 + /* 167 + * Read the base address for the SuperIO chip. 168 + * Only the lower 16 bits are valid, but the address is word 169 + * aligned so the last bit must be masked off. 170 + */ 171 + asr_base = inl(0xcfc) & 0xfffe; 172 + 173 + /* spin_unlock_irqrestore(&pci_config_lock, flags);*/ 174 + 175 + asr_read_addr = asr_write_addr = 176 + asr_base + JASPER_ASR_REG_OFFSET; 177 + asr_toggle_mask = JASPER_ASR_TOGGLE_MASK; 178 + asr_disable_mask = JASPER_ASR_DISABLE_MASK; 179 + asr_length = JASPER_ASR_REG_OFFSET + 1; 180 + 181 + break; 182 + 183 + case ASMTYPE_PEARL: 184 + type = "Pearls "; 185 + asr_base = PEARL_BASE; 186 + asr_read_addr = PEARL_READ; 187 + asr_write_addr = PEARL_WRITE; 188 + asr_toggle_mask = PEARL_ASR_TOGGLE_MASK; 189 + asr_disable_mask = PEARL_ASR_DISABLE_MASK; 190 + asr_length = 4; 191 + break; 192 + 193 + case ASMTYPE_JUNIPER: 194 + type = "Junipers "; 195 + asr_base = JUNIPER_BASE_ADDRESS; 196 + asr_read_addr = asr_write_addr = asr_base; 197 + asr_toggle_mask = JUNIPER_ASR_TOGGLE_MASK; 198 + asr_disable_mask = JUNIPER_ASR_DISABLE_MASK; 199 + break; 200 + 201 + case ASMTYPE_SPRUCE: 202 + type = "Spruce's "; 203 + asr_base = SPRUCE_BASE_ADDRESS; 204 + asr_read_addr = asr_write_addr = asr_base; 205 + asr_toggle_mask = SPRUCE_ASR_TOGGLE_MASK; 206 + asr_disable_mask = SPRUCE_ASR_DISABLE_MASK; 207 + break; 208 + } 209 + 210 + if (!request_region(asr_base, asr_length, "ibmasr")) { 211 + printk(KERN_ERR PFX "address %#x already in use\n", 212 + asr_base); 213 + return -EBUSY; 214 + } 215 + 216 + printk(KERN_INFO PFX "found %sASR @ addr %#x\n", type, asr_base); 217 + 218 + return 0; 219 + } 220 + 221 + 222 + static ssize_t asr_write(struct file *file, const char __user *buf, 223 + size_t count, loff_t *ppos) 224 + { 225 + if (count) { 226 + if (!nowayout) { 227 + size_t i; 228 + 229 + /* In case it was set long ago */ 230 + asr_expect_close = 0; 231 + 232 + for (i = 0; i != count; i++) { 233 + char c; 234 + if (get_user(c, buf + i)) 235 + return -EFAULT; 236 + if (c == 'V') 237 + asr_expect_close = 42; 238 + } 239 + } 240 + asr_toggle(); 241 + } 242 + return count; 243 + } 244 + 245 + static int asr_ioctl(struct inode *inode, struct file *file, 246 + unsigned int cmd, unsigned long arg) 247 + { 248 + static const struct watchdog_info ident = { 249 + .options = WDIOF_KEEPALIVEPING | 250 + WDIOF_MAGICCLOSE, 251 + .identity = "IBM ASR" 252 + }; 253 + void __user *argp = (void __user *)arg; 254 + int __user *p = argp; 255 + int heartbeat; 256 + 257 + switch (cmd) { 258 + case WDIOC_GETSUPPORT: 259 + return copy_to_user(argp, &ident, sizeof(ident)) ? 260 + -EFAULT : 0; 261 + 262 + case WDIOC_GETSTATUS: 263 + case WDIOC_GETBOOTSTATUS: 264 + return put_user(0, p); 265 + 266 + case WDIOC_KEEPALIVE: 267 + asr_toggle(); 268 + return 0; 269 + 270 + /* 271 + * The hardware has a fixed timeout value, so no WDIOC_SETTIMEOUT 272 + * and WDIOC_GETTIMEOUT always returns 256. 273 + */ 274 + case WDIOC_GETTIMEOUT: 275 + heartbeat = 256; 276 + return put_user(heartbeat, p); 277 + 278 + case WDIOC_SETOPTIONS: { 279 + int new_options, retval = -EINVAL; 280 + 281 + if (get_user(new_options, p)) 282 + return -EFAULT; 283 + 284 + if (new_options & WDIOS_DISABLECARD) { 285 + asr_disable(); 286 + retval = 0; 287 + } 288 + 289 + if (new_options & WDIOS_ENABLECARD) { 290 + asr_enable(); 291 + asr_toggle(); 292 + retval = 0; 293 + } 294 + 295 + return retval; 296 + } 297 + } 298 + 299 + return -ENOIOCTLCMD; 300 + } 301 + 302 + static int asr_open(struct inode *inode, struct file *file) 303 + { 304 + if(test_and_set_bit(0, &asr_is_open)) 305 + return -EBUSY; 306 + 307 + asr_toggle(); 308 + asr_enable(); 309 + 310 + return nonseekable_open(inode, file); 311 + } 312 + 313 + static int asr_release(struct inode *inode, struct file *file) 314 + { 315 + if (asr_expect_close == 42) 316 + asr_disable(); 317 + else { 318 + printk(KERN_CRIT PFX "unexpected close, not stopping watchdog!\n"); 319 + asr_toggle(); 320 + } 321 + clear_bit(0, &asr_is_open); 322 + asr_expect_close = 0; 323 + return 0; 324 + } 325 + 326 + static struct file_operations asr_fops = { 327 + .owner = THIS_MODULE, 328 + .llseek = no_llseek, 329 + .write = asr_write, 330 + .ioctl = asr_ioctl, 331 + .open = asr_open, 332 + .release = asr_release, 333 + }; 334 + 335 + static struct miscdevice asr_miscdev = { 336 + .minor = WATCHDOG_MINOR, 337 + .name = "watchdog", 338 + .fops = &asr_fops, 339 + }; 340 + 341 + 342 + struct ibmasr_id { 343 + const char *desc; 344 + int type; 345 + }; 346 + 347 + static struct ibmasr_id __initdata ibmasr_id_table[] = { 348 + { "IBM Automatic Server Restart - eserver xSeries 220", ASMTYPE_TOPAZ }, 349 + { "IBM Automatic Server Restart - Machine Type 8673", ASMTYPE_PEARL }, 350 + { "IBM Automatic Server Restart - Machine Type 8480", ASMTYPE_JASPER }, 351 + { "IBM Automatic Server Restart - Machine Type 8482", ASMTYPE_JUNIPER }, 352 + { "IBM Automatic Server Restart - Machine Type 8648", ASMTYPE_SPRUCE }, 353 + { NULL } 354 + }; 355 + 356 + static int __init ibmasr_init(void) 357 + { 358 + struct ibmasr_id *id; 359 + int rc; 360 + 361 + for (id = ibmasr_id_table; id->desc; id++) { 362 + if (dmi_find_device(DMI_DEV_TYPE_OTHER, id->desc, NULL)) { 363 + asr_type = id->type; 364 + break; 365 + } 366 + } 367 + 368 + if (!asr_type) 369 + return -ENODEV; 370 + 371 + rc = misc_register(&asr_miscdev); 372 + if (rc < 0) { 373 + printk(KERN_ERR PFX "failed to register misc device\n"); 374 + return rc; 375 + } 376 + 377 + rc = asr_get_base_address(); 378 + if (rc) { 379 + misc_deregister(&asr_miscdev); 380 + return rc; 381 + } 382 + 383 + return 0; 384 + } 385 + 386 + static void __exit ibmasr_exit(void) 387 + { 388 + if (!nowayout) 389 + asr_disable(); 390 + 391 + misc_deregister(&asr_miscdev); 392 + 393 + release_region(asr_base, asr_length); 394 + } 395 + 396 + module_init(ibmasr_init); 397 + module_exit(ibmasr_exit); 398 + 399 + module_param(nowayout, int, 0); 400 + MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); 401 + 402 + MODULE_DESCRIPTION("IBM Automatic Server Restart driver"); 403 + MODULE_AUTHOR("Andrey Panin"); 404 + MODULE_LICENSE("GPL"); 405 + MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
+252
drivers/char/watchdog/mv64x60_wdt.c
···
··· 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 <asm/mv64x60.h> 26 + #include <asm/uaccess.h> 27 + #include <asm/io.h> 28 + 29 + /* MV64x60 WDC (config) register access definitions */ 30 + #define MV64x60_WDC_CTL1_MASK (3 << 24) 31 + #define MV64x60_WDC_CTL1(val) ((val & 3) << 24) 32 + #define MV64x60_WDC_CTL2_MASK (3 << 26) 33 + #define MV64x60_WDC_CTL2(val) ((val & 3) << 26) 34 + 35 + /* Flags bits */ 36 + #define MV64x60_WDOG_FLAG_OPENED 0 37 + #define MV64x60_WDOG_FLAG_ENABLED 1 38 + 39 + static unsigned long wdt_flags; 40 + static int wdt_status; 41 + static void __iomem *mv64x60_regs; 42 + static int mv64x60_wdt_timeout; 43 + 44 + static void mv64x60_wdt_reg_write(u32 val) 45 + { 46 + /* Allow write only to CTL1 / CTL2 fields, retaining values in 47 + * other fields. 48 + */ 49 + u32 data = readl(mv64x60_regs + MV64x60_WDT_WDC); 50 + data &= ~(MV64x60_WDC_CTL1_MASK | MV64x60_WDC_CTL2_MASK); 51 + data |= val; 52 + writel(data, mv64x60_regs + MV64x60_WDT_WDC); 53 + } 54 + 55 + static void mv64x60_wdt_service(void) 56 + { 57 + /* Write 01 followed by 10 to CTL2 */ 58 + mv64x60_wdt_reg_write(MV64x60_WDC_CTL2(0x01)); 59 + mv64x60_wdt_reg_write(MV64x60_WDC_CTL2(0x02)); 60 + } 61 + 62 + static void mv64x60_wdt_handler_disable(void) 63 + { 64 + if (test_and_clear_bit(MV64x60_WDOG_FLAG_ENABLED, &wdt_flags)) { 65 + /* Write 01 followed by 10 to CTL1 */ 66 + mv64x60_wdt_reg_write(MV64x60_WDC_CTL1(0x01)); 67 + mv64x60_wdt_reg_write(MV64x60_WDC_CTL1(0x02)); 68 + printk(KERN_NOTICE "mv64x60_wdt: watchdog deactivated\n"); 69 + } 70 + } 71 + 72 + static void mv64x60_wdt_handler_enable(void) 73 + { 74 + if (!test_and_set_bit(MV64x60_WDOG_FLAG_ENABLED, &wdt_flags)) { 75 + /* Write 01 followed by 10 to CTL1 */ 76 + mv64x60_wdt_reg_write(MV64x60_WDC_CTL1(0x01)); 77 + mv64x60_wdt_reg_write(MV64x60_WDC_CTL1(0x02)); 78 + printk(KERN_NOTICE "mv64x60_wdt: watchdog activated\n"); 79 + } 80 + } 81 + 82 + static int mv64x60_wdt_open(struct inode *inode, struct file *file) 83 + { 84 + if (test_and_set_bit(MV64x60_WDOG_FLAG_OPENED, &wdt_flags)) 85 + return -EBUSY; 86 + 87 + mv64x60_wdt_service(); 88 + mv64x60_wdt_handler_enable(); 89 + 90 + return 0; 91 + } 92 + 93 + static int mv64x60_wdt_release(struct inode *inode, struct file *file) 94 + { 95 + mv64x60_wdt_service(); 96 + 97 + #if !defined(CONFIG_WATCHDOG_NOWAYOUT) 98 + mv64x60_wdt_handler_disable(); 99 + #endif 100 + 101 + clear_bit(MV64x60_WDOG_FLAG_OPENED, &wdt_flags); 102 + 103 + return 0; 104 + } 105 + 106 + static ssize_t mv64x60_wdt_write(struct file *file, const char *data, 107 + size_t len, loff_t * ppos) 108 + { 109 + if (*ppos != file->f_pos) 110 + return -ESPIPE; 111 + 112 + if (len) 113 + mv64x60_wdt_service(); 114 + 115 + return len; 116 + } 117 + 118 + static int mv64x60_wdt_ioctl(struct inode *inode, struct file *file, 119 + unsigned int cmd, unsigned long arg) 120 + { 121 + int timeout; 122 + static struct watchdog_info info = { 123 + .options = WDIOF_KEEPALIVEPING, 124 + .firmware_version = 0, 125 + .identity = "MV64x60 watchdog", 126 + }; 127 + 128 + switch (cmd) { 129 + case WDIOC_GETSUPPORT: 130 + if (copy_to_user((void *)arg, &info, sizeof(info))) 131 + return -EFAULT; 132 + break; 133 + 134 + case WDIOC_GETSTATUS: 135 + case WDIOC_GETBOOTSTATUS: 136 + if (put_user(wdt_status, (int *)arg)) 137 + return -EFAULT; 138 + wdt_status &= ~WDIOF_KEEPALIVEPING; 139 + break; 140 + 141 + case WDIOC_GETTEMP: 142 + return -EOPNOTSUPP; 143 + 144 + case WDIOC_SETOPTIONS: 145 + return -EOPNOTSUPP; 146 + 147 + case WDIOC_KEEPALIVE: 148 + mv64x60_wdt_service(); 149 + wdt_status |= WDIOF_KEEPALIVEPING; 150 + break; 151 + 152 + case WDIOC_SETTIMEOUT: 153 + return -EOPNOTSUPP; 154 + 155 + case WDIOC_GETTIMEOUT: 156 + timeout = mv64x60_wdt_timeout * HZ; 157 + if (put_user(timeout, (int *)arg)) 158 + return -EFAULT; 159 + break; 160 + 161 + default: 162 + return -ENOIOCTLCMD; 163 + } 164 + 165 + return 0; 166 + } 167 + 168 + static struct file_operations mv64x60_wdt_fops = { 169 + .owner = THIS_MODULE, 170 + .llseek = no_llseek, 171 + .write = mv64x60_wdt_write, 172 + .ioctl = mv64x60_wdt_ioctl, 173 + .open = mv64x60_wdt_open, 174 + .release = mv64x60_wdt_release, 175 + }; 176 + 177 + static struct miscdevice mv64x60_wdt_miscdev = { 178 + .minor = WATCHDOG_MINOR, 179 + .name = "watchdog", 180 + .fops = &mv64x60_wdt_fops, 181 + }; 182 + 183 + static int __devinit mv64x60_wdt_probe(struct device *dev) 184 + { 185 + struct platform_device *pd = to_platform_device(dev); 186 + struct mv64x60_wdt_pdata *pdata = pd->dev.platform_data; 187 + int bus_clk = 133; 188 + 189 + mv64x60_wdt_timeout = 10; 190 + if (pdata) { 191 + mv64x60_wdt_timeout = pdata->timeout; 192 + bus_clk = pdata->bus_clk; 193 + } 194 + 195 + mv64x60_regs = mv64x60_get_bridge_vbase(); 196 + 197 + writel((mv64x60_wdt_timeout * (bus_clk * 1000000)) >> 8, 198 + mv64x60_regs + MV64x60_WDT_WDC); 199 + 200 + return misc_register(&mv64x60_wdt_miscdev); 201 + } 202 + 203 + static int __devexit mv64x60_wdt_remove(struct device *dev) 204 + { 205 + misc_deregister(&mv64x60_wdt_miscdev); 206 + 207 + mv64x60_wdt_service(); 208 + mv64x60_wdt_handler_disable(); 209 + 210 + return 0; 211 + } 212 + 213 + static struct device_driver mv64x60_wdt_driver = { 214 + .name = MV64x60_WDT_NAME, 215 + .bus = &platform_bus_type, 216 + .probe = mv64x60_wdt_probe, 217 + .remove = __devexit_p(mv64x60_wdt_remove), 218 + }; 219 + 220 + static struct platform_device *mv64x60_wdt_dev; 221 + 222 + static int __init mv64x60_wdt_init(void) 223 + { 224 + int ret; 225 + 226 + printk(KERN_INFO "MV64x60 watchdog driver\n"); 227 + 228 + mv64x60_wdt_dev = platform_device_register_simple(MV64x60_WDT_NAME, 229 + -1, NULL, 0); 230 + if (IS_ERR(mv64x60_wdt_dev)) { 231 + ret = PTR_ERR(mv64x60_wdt_dev); 232 + goto out; 233 + } 234 + 235 + ret = driver_register(&mv64x60_wdt_driver); 236 + out: 237 + return ret; 238 + } 239 + 240 + static void __exit mv64x60_wdt_exit(void) 241 + { 242 + driver_unregister(&mv64x60_wdt_driver); 243 + platform_device_unregister(mv64x60_wdt_dev); 244 + } 245 + 246 + module_init(mv64x60_wdt_init); 247 + module_exit(mv64x60_wdt_exit); 248 + 249 + MODULE_AUTHOR("James Chapman <jchapman@katalix.com>"); 250 + MODULE_DESCRIPTION("MV64x60 watchdog driver"); 251 + MODULE_LICENSE("GPL"); 252 + MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
+23 -19
drivers/char/watchdog/pcwd_pci.c
··· 29 * Includes, defines, variables, module parameters, ... 30 */ 31 32 - #include <linux/config.h> 33 - #include <linux/module.h> 34 - #include <linux/moduleparam.h> 35 - #include <linux/types.h> 36 - #include <linux/delay.h> 37 - #include <linux/miscdevice.h> 38 - #include <linux/watchdog.h> 39 - #include <linux/notifier.h> 40 - #include <linux/reboot.h> 41 - #include <linux/init.h> 42 - #include <linux/fs.h> 43 - #include <linux/pci.h> 44 - #include <linux/ioport.h> 45 - #include <linux/spinlock.h> 46 47 - #include <asm/uaccess.h> 48 - #include <asm/io.h> 49 50 /* Module and version information */ 51 #define WATCHDOG_VERSION "1.01" 52 - #define WATCHDOG_DATE "15 Mar 2005" 53 #define WATCHDOG_DRIVER_NAME "PCI-PC Watchdog" 54 #define WATCHDOG_NAME "pcwd_pci" 55 #define PFX WATCHDOG_NAME ": " ··· 337 return -EFAULT; 338 339 if (new_options & WDIOS_DISABLECARD) { 340 - pcipcwd_stop(); 341 retval = 0; 342 } 343 344 if (new_options & WDIOS_ENABLECARD) { 345 - pcipcwd_start(); 346 retval = 0; 347 } 348
··· 29 * Includes, defines, variables, module parameters, ... 30 */ 31 32 + #include <linux/config.h> /* For CONFIG_WATCHDOG_NOWAYOUT/... */ 33 + #include <linux/module.h> /* For module specific items */ 34 + #include <linux/moduleparam.h> /* For new moduleparam's */ 35 + #include <linux/types.h> /* For standard types (like size_t) */ 36 + #include <linux/errno.h> /* For the -ENODEV/... values */ 37 + #include <linux/kernel.h> /* For printk/panic/... */ 38 + #include <linux/delay.h> /* For mdelay function */ 39 + #include <linux/miscdevice.h> /* For MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR) */ 40 + #include <linux/watchdog.h> /* For the watchdog specific items */ 41 + #include <linux/notifier.h> /* For notifier support */ 42 + #include <linux/reboot.h> /* For reboot_notifier stuff */ 43 + #include <linux/init.h> /* For __init/__exit/... */ 44 + #include <linux/fs.h> /* For file operations */ 45 + #include <linux/pci.h> /* For pci functions */ 46 + #include <linux/ioport.h> /* For io-port access */ 47 + #include <linux/spinlock.h> /* For spin_lock/spin_unlock/... */ 48 49 + #include <asm/uaccess.h> /* For copy_to_user/put_user/... */ 50 + #include <asm/io.h> /* For inb/outb/... */ 51 52 /* Module and version information */ 53 #define WATCHDOG_VERSION "1.01" 54 + #define WATCHDOG_DATE "02 Sep 2005" 55 #define WATCHDOG_DRIVER_NAME "PCI-PC Watchdog" 56 #define WATCHDOG_NAME "pcwd_pci" 57 #define PFX WATCHDOG_NAME ": " ··· 335 return -EFAULT; 336 337 if (new_options & WDIOS_DISABLECARD) { 338 + if (pcipcwd_stop()) 339 + return -EIO; 340 retval = 0; 341 } 342 343 if (new_options & WDIOS_ENABLECARD) { 344 + if (pcipcwd_start()) 345 + return -EIO; 346 retval = 0; 347 } 348
+1 -1
drivers/char/watchdog/s3c2410_wdt.c
··· 464 static unsigned long wtcon_save; 465 static unsigned long wtdat_save; 466 467 - static int s3c2410wdt_suspend(struct device *dev, u32 state, u32 level) 468 { 469 if (level == SUSPEND_POWER_DOWN) { 470 /* Save watchdog state, and turn it off. */
··· 464 static unsigned long wtcon_save; 465 static unsigned long wtdat_save; 466 467 + static int s3c2410wdt_suspend(struct device *dev, pm_message_t state, u32 level) 468 { 469 if (level == SUSPEND_POWER_DOWN) { 470 /* Save watchdog state, and turn it off. */
+414
drivers/char/watchdog/sbc8360.c
···
··· 1 + /* 2 + * SBC8360 Watchdog driver 3 + * 4 + * (c) Copyright 2005 Webcon, Inc. 5 + * 6 + * Based on ib700wdt.c, which is based on advantechwdt.c which is based 7 + * on acquirewdt.c which is based on wdt.c. 8 + * 9 + * (c) Copyright 2001 Charles Howes <chowes@vsol.net> 10 + * 11 + * Based on advantechwdt.c which is based on acquirewdt.c which 12 + * is based on wdt.c. 13 + * 14 + * (c) Copyright 2000-2001 Marek Michalkiewicz <marekm@linux.org.pl> 15 + * 16 + * Based on acquirewdt.c which is based on wdt.c. 17 + * Original copyright messages: 18 + * 19 + * (c) Copyright 1996 Alan Cox <alan@redhat.com>, All Rights Reserved. 20 + * http://www.redhat.com 21 + * 22 + * This program is free software; you can redistribute it and/or 23 + * modify it under the terms of the GNU General Public License 24 + * as published by the Free Software Foundation; either version 25 + * 2 of the License, or (at your option) any later version. 26 + * 27 + * Neither Alan Cox nor CymruNet Ltd. admit liability nor provide 28 + * warranty for any of this software. This material is provided 29 + * "AS-IS" and at no charge. 30 + * 31 + * (c) Copyright 1995 Alan Cox <alan@redhat.com> 32 + * 33 + * 14-Dec-2001 Matt Domsch <Matt_Domsch@dell.com> 34 + * Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT 35 + * Added timeout module option to override default 36 + * 37 + */ 38 + 39 + #include <linux/config.h> 40 + #include <linux/module.h> 41 + #include <linux/types.h> 42 + #include <linux/miscdevice.h> 43 + #include <linux/watchdog.h> 44 + #include <linux/ioport.h> 45 + #include <linux/delay.h> 46 + #include <linux/notifier.h> 47 + #include <linux/fs.h> 48 + #include <linux/reboot.h> 49 + #include <linux/init.h> 50 + #include <linux/spinlock.h> 51 + #include <linux/moduleparam.h> 52 + 53 + #include <asm/io.h> 54 + #include <asm/uaccess.h> 55 + #include <asm/system.h> 56 + 57 + static unsigned long sbc8360_is_open; 58 + static spinlock_t sbc8360_lock; 59 + static char expect_close; 60 + 61 + #define PFX "sbc8360: " 62 + 63 + /* 64 + * 65 + * Watchdog Timer Configuration 66 + * 67 + * The function of the watchdog timer is to reset the system automatically 68 + * and is defined at I/O port 0120H and 0121H. To enable the watchdog timer 69 + * and allow the system to reset, write appropriate values from the table 70 + * below to I/O port 0120H and 0121H. To disable the timer, write a zero 71 + * value to I/O port 0121H for the system to stop the watchdog function. 72 + * 73 + * The following describes how the timer should be programmed (according to 74 + * the vendor documentation) 75 + * 76 + * Enabling Watchdog: 77 + * MOV AX,000AH (enable, phase I) 78 + * MOV DX,0120H 79 + * OUT DX,AX 80 + * MOV AX,000BH (enable, phase II) 81 + * MOV DX,0120H 82 + * OUT DX,AX 83 + * MOV AX,000nH (set multiplier n, from 1-4) 84 + * MOV DX,0120H 85 + * OUT DX,AX 86 + * MOV AX,000mH (set base timer m, from 0-F) 87 + * MOV DX,0121H 88 + * OUT DX,AX 89 + * 90 + * Reset timer: 91 + * MOV AX,000mH (same as set base timer, above) 92 + * MOV DX,0121H 93 + * OUT DX,AX 94 + * 95 + * Disabling Watchdog: 96 + * MOV AX,0000H (a zero value) 97 + * MOV DX,0120H 98 + * OUT DX,AX 99 + * 100 + * Watchdog timeout configuration values: 101 + * N 102 + * M | 1 2 3 4 103 + * --|---------------------------------- 104 + * 0 | 0.5s 5s 50s 100s 105 + * 1 | 1s 10s 100s 200s 106 + * 2 | 1.5s 15s 150s 300s 107 + * 3 | 2s 20s 200s 400s 108 + * 4 | 2.5s 25s 250s 500s 109 + * 5 | 3s 30s 300s 600s 110 + * 6 | 3.5s 35s 350s 700s 111 + * 7 | 4s 40s 400s 800s 112 + * 8 | 4.5s 45s 450s 900s 113 + * 9 | 5s 50s 500s 1000s 114 + * A | 5.5s 55s 550s 1100s 115 + * B | 6s 60s 600s 1200s 116 + * C | 6.5s 65s 650s 1300s 117 + * D | 7s 70s 700s 1400s 118 + * E | 7.5s 75s 750s 1500s 119 + * F | 8s 80s 800s 1600s 120 + * 121 + * Another way to say the same things is: 122 + * For N=1, Timeout = (M+1) * 0.5s 123 + * For N=2, Timeout = (M+1) * 5s 124 + * For N=3, Timeout = (M+1) * 50s 125 + * For N=4, Timeout = (M+1) * 100s 126 + * 127 + */ 128 + 129 + static int wd_times[64][2] = { 130 + {0, 1}, /* 0 = 0.5s */ 131 + {1, 1}, /* 1 = 1s */ 132 + {2, 1}, /* 2 = 1.5s */ 133 + {3, 1}, /* 3 = 2s */ 134 + {4, 1}, /* 4 = 2.5s */ 135 + {5, 1}, /* 5 = 3s */ 136 + {6, 1}, /* 6 = 3.5s */ 137 + {7, 1}, /* 7 = 4s */ 138 + {8, 1}, /* 8 = 4.5s */ 139 + {9, 1}, /* 9 = 5s */ 140 + {0xA, 1}, /* 10 = 5.5s */ 141 + {0xB, 1}, /* 11 = 6s */ 142 + {0xC, 1}, /* 12 = 6.5s */ 143 + {0xD, 1}, /* 13 = 7s */ 144 + {0xE, 1}, /* 14 = 7.5s */ 145 + {0xF, 1}, /* 15 = 8s */ 146 + {0, 2}, /* 16 = 5s */ 147 + {1, 2}, /* 17 = 10s */ 148 + {2, 2}, /* 18 = 15s */ 149 + {3, 2}, /* 19 = 20s */ 150 + {4, 2}, /* 20 = 25s */ 151 + {5, 2}, /* 21 = 30s */ 152 + {6, 2}, /* 22 = 35s */ 153 + {7, 2}, /* 23 = 40s */ 154 + {8, 2}, /* 24 = 45s */ 155 + {9, 2}, /* 25 = 50s */ 156 + {0xA, 2}, /* 26 = 55s */ 157 + {0xB, 2}, /* 27 = 60s */ 158 + {0xC, 2}, /* 28 = 65s */ 159 + {0xD, 2}, /* 29 = 70s */ 160 + {0xE, 2}, /* 30 = 75s */ 161 + {0xF, 2}, /* 31 = 80s */ 162 + {0, 3}, /* 32 = 50s */ 163 + {1, 3}, /* 33 = 100s */ 164 + {2, 3}, /* 34 = 150s */ 165 + {3, 3}, /* 35 = 200s */ 166 + {4, 3}, /* 36 = 250s */ 167 + {5, 3}, /* 37 = 300s */ 168 + {6, 3}, /* 38 = 350s */ 169 + {7, 3}, /* 39 = 400s */ 170 + {8, 3}, /* 40 = 450s */ 171 + {9, 3}, /* 41 = 500s */ 172 + {0xA, 3}, /* 42 = 550s */ 173 + {0xB, 3}, /* 43 = 600s */ 174 + {0xC, 3}, /* 44 = 650s */ 175 + {0xD, 3}, /* 45 = 700s */ 176 + {0xE, 3}, /* 46 = 750s */ 177 + {0xF, 3}, /* 47 = 800s */ 178 + {0, 4}, /* 48 = 100s */ 179 + {1, 4}, /* 49 = 200s */ 180 + {2, 4}, /* 50 = 300s */ 181 + {3, 4}, /* 51 = 400s */ 182 + {4, 4}, /* 52 = 500s */ 183 + {5, 4}, /* 53 = 600s */ 184 + {6, 4}, /* 54 = 700s */ 185 + {7, 4}, /* 55 = 800s */ 186 + {8, 4}, /* 56 = 900s */ 187 + {9, 4}, /* 57 = 1000s */ 188 + {0xA, 4}, /* 58 = 1100s */ 189 + {0xB, 4}, /* 59 = 1200s */ 190 + {0xC, 4}, /* 60 = 1300s */ 191 + {0xD, 4}, /* 61 = 1400s */ 192 + {0xE, 4}, /* 62 = 1500s */ 193 + {0xF, 4} /* 63 = 1600s */ 194 + }; 195 + 196 + #define SBC8360_ENABLE 0x120 197 + #define SBC8360_BASETIME 0x121 198 + 199 + static int timeout = 27; 200 + static int wd_margin = 0xB; 201 + static int wd_multiplier = 2; 202 + static int nowayout = WATCHDOG_NOWAYOUT; 203 + 204 + module_param(timeout, int, 27); 205 + MODULE_PARM_DESC(timeout, "Index into timeout table (0-63) (default=27 (60s))"); 206 + module_param(nowayout, int, 0); 207 + MODULE_PARM_DESC(nowayout, 208 + "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); 209 + 210 + /* 211 + * Kernel methods. 212 + */ 213 + 214 + /* Activate and pre-configure watchdog */ 215 + static void sbc8360_activate(void) 216 + { 217 + /* Enable the watchdog */ 218 + outb(0x0A, SBC8360_ENABLE); 219 + msleep_interruptible(100); 220 + outb(0x0B, SBC8360_ENABLE); 221 + msleep_interruptible(100); 222 + /* Set timeout multiplier */ 223 + outb(wd_multiplier, SBC8360_ENABLE); 224 + msleep_interruptible(100); 225 + /* Nothing happens until first sbc8360_ping() */ 226 + } 227 + 228 + /* Kernel pings watchdog */ 229 + static void sbc8360_ping(void) 230 + { 231 + /* Write the base timer register */ 232 + outb(wd_margin, SBC8360_BASETIME); 233 + } 234 + 235 + /* Userspace pings kernel driver, or requests clean close */ 236 + static ssize_t sbc8360_write(struct file *file, const char __user * buf, 237 + size_t count, loff_t * ppos) 238 + { 239 + if (count) { 240 + if (!nowayout) { 241 + size_t i; 242 + 243 + /* In case it was set long ago */ 244 + expect_close = 0; 245 + 246 + for (i = 0; i != count; i++) { 247 + char c; 248 + if (get_user(c, buf + i)) 249 + return -EFAULT; 250 + if (c == 'V') 251 + expect_close = 42; 252 + } 253 + } 254 + sbc8360_ping(); 255 + } 256 + return count; 257 + } 258 + 259 + static int sbc8360_open(struct inode *inode, struct file *file) 260 + { 261 + spin_lock(&sbc8360_lock); 262 + if (test_and_set_bit(0, &sbc8360_is_open)) { 263 + spin_unlock(&sbc8360_lock); 264 + return -EBUSY; 265 + } 266 + if (nowayout) 267 + __module_get(THIS_MODULE); 268 + 269 + /* Activate and ping once to start the countdown */ 270 + spin_unlock(&sbc8360_lock); 271 + sbc8360_activate(); 272 + sbc8360_ping(); 273 + return nonseekable_open(inode, file); 274 + } 275 + 276 + static int sbc8360_close(struct inode *inode, struct file *file) 277 + { 278 + spin_lock(&sbc8360_lock); 279 + if (expect_close == 42) 280 + outb(0, SBC8360_ENABLE); 281 + else 282 + printk(KERN_CRIT PFX 283 + "SBC8360 device closed unexpectedly. SBC8360 will not stop!\n"); 284 + 285 + clear_bit(0, &sbc8360_is_open); 286 + expect_close = 0; 287 + spin_unlock(&sbc8360_lock); 288 + return 0; 289 + } 290 + 291 + /* 292 + * Notifier for system down 293 + */ 294 + 295 + static int sbc8360_notify_sys(struct notifier_block *this, unsigned long code, 296 + void *unused) 297 + { 298 + if (code == SYS_DOWN || code == SYS_HALT) { 299 + /* Disable the SBC8360 Watchdog */ 300 + outb(0, SBC8360_ENABLE); 301 + } 302 + return NOTIFY_DONE; 303 + } 304 + 305 + /* 306 + * Kernel Interfaces 307 + */ 308 + 309 + static struct file_operations sbc8360_fops = { 310 + .owner = THIS_MODULE, 311 + .llseek = no_llseek, 312 + .write = sbc8360_write, 313 + .open = sbc8360_open, 314 + .release = sbc8360_close, 315 + }; 316 + 317 + static struct miscdevice sbc8360_miscdev = { 318 + .minor = WATCHDOG_MINOR, 319 + .name = "watchdog", 320 + .fops = &sbc8360_fops, 321 + }; 322 + 323 + /* 324 + * The SBC8360 needs to learn about soft shutdowns in order to 325 + * turn the timebomb registers off. 326 + */ 327 + 328 + static struct notifier_block sbc8360_notifier = { 329 + .notifier_call = sbc8360_notify_sys, 330 + }; 331 + 332 + static int __init sbc8360_init(void) 333 + { 334 + int res; 335 + unsigned long int mseconds = 60000; 336 + 337 + spin_lock_init(&sbc8360_lock); 338 + res = misc_register(&sbc8360_miscdev); 339 + if (res) { 340 + printk(KERN_ERR PFX "failed to register misc device\n"); 341 + goto out_nomisc; 342 + } 343 + 344 + if (!request_region(SBC8360_ENABLE, 1, "SBC8360")) { 345 + printk(KERN_ERR PFX "ENABLE method I/O %X is not available.\n", 346 + SBC8360_ENABLE); 347 + res = -EIO; 348 + goto out_noenablereg; 349 + } 350 + if (!request_region(SBC8360_BASETIME, 1, "SBC8360")) { 351 + printk(KERN_ERR PFX 352 + "BASETIME method I/O %X is not available.\n", 353 + SBC8360_BASETIME); 354 + res = -EIO; 355 + goto out_nobasetimereg; 356 + } 357 + 358 + res = register_reboot_notifier(&sbc8360_notifier); 359 + if (res) { 360 + printk(KERN_ERR PFX "Failed to register reboot notifier.\n"); 361 + goto out_noreboot; 362 + } 363 + 364 + if (timeout < 0 || timeout > 63) { 365 + printk(KERN_ERR PFX "Invalid timeout index (must be 0-63).\n"); 366 + res = -EINVAL; 367 + goto out_noreboot; 368 + } 369 + 370 + wd_margin = wd_times[timeout][0]; 371 + wd_multiplier = wd_times[timeout][1]; 372 + 373 + if (wd_multiplier == 1) 374 + mseconds = (wd_margin + 1) * 500; 375 + else if (wd_multiplier == 2) 376 + mseconds = (wd_margin + 1) * 5000; 377 + else if (wd_multiplier == 3) 378 + mseconds = (wd_margin + 1) * 50000; 379 + else if (wd_multiplier == 4) 380 + mseconds = (wd_margin + 1) * 100000; 381 + 382 + /* My kingdom for the ability to print "0.5 seconds" in the kernel! */ 383 + printk(KERN_INFO PFX "Timeout set at %ld ms.\n", mseconds); 384 + 385 + return 0; 386 + 387 + out_noreboot: 388 + release_region(SBC8360_ENABLE, 1); 389 + release_region(SBC8360_BASETIME, 1); 390 + out_noenablereg: 391 + out_nobasetimereg: 392 + misc_deregister(&sbc8360_miscdev); 393 + out_nomisc: 394 + return res; 395 + } 396 + 397 + static void __exit sbc8360_exit(void) 398 + { 399 + misc_deregister(&sbc8360_miscdev); 400 + unregister_reboot_notifier(&sbc8360_notifier); 401 + release_region(SBC8360_ENABLE, 1); 402 + release_region(SBC8360_BASETIME, 1); 403 + } 404 + 405 + module_init(sbc8360_init); 406 + module_exit(sbc8360_exit); 407 + 408 + MODULE_AUTHOR("Ian E. Morgan <imorgan@webcon.ca>"); 409 + MODULE_DESCRIPTION("SBC8360 watchdog driver"); 410 + MODULE_LICENSE("GPL"); 411 + MODULE_VERSION("1.0"); 412 + MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); 413 + 414 + /* end of sbc8360.c */
+543
drivers/char/watchdog/w83977f_wdt.c
···
··· 1 + /* 2 + * W83977F Watchdog Timer Driver for Winbond W83977F I/O Chip 3 + * 4 + * (c) Copyright 2005 Jose Goncalves <jose.goncalves@inov.pt> 5 + * 6 + * Based on w83877f_wdt.c by Scott Jennings, 7 + * and wdt977.c by Woody Suwalski 8 + * 9 + * ----------------------- 10 + * 11 + * This program is free software; you can redistribute it and/or 12 + * modify it under the terms of the GNU General Public License 13 + * as published by the Free Software Foundation; either version 14 + * 2 of the License, or (at your option) any later version. 15 + * 16 + */ 17 + 18 + #include <linux/module.h> 19 + #include <linux/moduleparam.h> 20 + #include <linux/config.h> 21 + #include <linux/types.h> 22 + #include <linux/kernel.h> 23 + #include <linux/fs.h> 24 + #include <linux/miscdevice.h> 25 + #include <linux/init.h> 26 + #include <linux/ioport.h> 27 + #include <linux/watchdog.h> 28 + #include <linux/notifier.h> 29 + #include <linux/reboot.h> 30 + 31 + #include <asm/io.h> 32 + #include <asm/system.h> 33 + #include <asm/uaccess.h> 34 + 35 + #define WATCHDOG_VERSION "1.00" 36 + #define WATCHDOG_NAME "W83977F WDT" 37 + #define PFX WATCHDOG_NAME ": " 38 + #define DRIVER_VERSION WATCHDOG_NAME " driver, v" WATCHDOG_VERSION "\n" 39 + 40 + #define IO_INDEX_PORT 0x3F0 41 + #define IO_DATA_PORT (IO_INDEX_PORT+1) 42 + 43 + #define UNLOCK_DATA 0x87 44 + #define LOCK_DATA 0xAA 45 + #define DEVICE_REGISTER 0x07 46 + 47 + #define DEFAULT_TIMEOUT 45 /* default timeout in seconds */ 48 + 49 + static int timeout = DEFAULT_TIMEOUT; 50 + static int timeoutW; /* timeout in watchdog counter units */ 51 + static unsigned long timer_alive; 52 + static int testmode; 53 + static char expect_close; 54 + static spinlock_t spinlock; 55 + 56 + module_param(timeout, int, 0); 57 + MODULE_PARM_DESC(timeout,"Watchdog timeout in seconds (15..7635), default=" __MODULE_STRING(DEFAULT_TIMEOUT) ")"); 58 + module_param(testmode, int, 0); 59 + MODULE_PARM_DESC(testmode,"Watchdog testmode (1 = no reboot), default=0"); 60 + 61 + static int nowayout = WATCHDOG_NOWAYOUT; 62 + module_param(nowayout, int, 0); 63 + MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); 64 + 65 + /* 66 + * Start the watchdog 67 + */ 68 + 69 + static int wdt_start(void) 70 + { 71 + unsigned long flags; 72 + 73 + spin_lock_irqsave(&spinlock, flags); 74 + 75 + /* Unlock the SuperIO chip */ 76 + outb_p(UNLOCK_DATA,IO_INDEX_PORT); 77 + outb_p(UNLOCK_DATA,IO_INDEX_PORT); 78 + 79 + /* 80 + * Select device Aux2 (device=8) to set watchdog regs F2, F3 and F4. 81 + * F2 has the timeout in watchdog counter units. 82 + * F3 is set to enable watchdog LED blink at timeout. 83 + * F4 is used to just clear the TIMEOUT'ed state (bit 0). 84 + */ 85 + outb_p(DEVICE_REGISTER,IO_INDEX_PORT); 86 + outb_p(0x08,IO_DATA_PORT); 87 + outb_p(0xF2,IO_INDEX_PORT); 88 + outb_p(timeoutW,IO_DATA_PORT); 89 + outb_p(0xF3,IO_INDEX_PORT); 90 + outb_p(0x08,IO_DATA_PORT); 91 + outb_p(0xF4,IO_INDEX_PORT); 92 + outb_p(0x00,IO_DATA_PORT); 93 + 94 + /* Set device Aux2 active */ 95 + outb_p(0x30,IO_INDEX_PORT); 96 + outb_p(0x01,IO_DATA_PORT); 97 + 98 + /* 99 + * Select device Aux1 (dev=7) to set GP16 as the watchdog output 100 + * (in reg E6) and GP13 as the watchdog LED output (in reg E3). 101 + * Map GP16 at pin 119. 102 + * In test mode watch the bit 0 on F4 to indicate "triggered" or 103 + * check watchdog LED on SBC. 104 + */ 105 + outb_p(DEVICE_REGISTER,IO_INDEX_PORT); 106 + outb_p(0x07,IO_DATA_PORT); 107 + if (!testmode) 108 + { 109 + unsigned pin_map; 110 + 111 + outb_p(0xE6,IO_INDEX_PORT); 112 + outb_p(0x0A,IO_DATA_PORT); 113 + outb_p(0x2C,IO_INDEX_PORT); 114 + pin_map = inb_p(IO_DATA_PORT); 115 + pin_map |= 0x10; 116 + pin_map &= ~(0x20); 117 + outb_p(0x2C,IO_INDEX_PORT); 118 + outb_p(pin_map,IO_DATA_PORT); 119 + } 120 + outb_p(0xE3,IO_INDEX_PORT); 121 + outb_p(0x08,IO_DATA_PORT); 122 + 123 + /* Set device Aux1 active */ 124 + outb_p(0x30,IO_INDEX_PORT); 125 + outb_p(0x01,IO_DATA_PORT); 126 + 127 + /* Lock the SuperIO chip */ 128 + outb_p(LOCK_DATA,IO_INDEX_PORT); 129 + 130 + spin_unlock_irqrestore(&spinlock, flags); 131 + 132 + printk(KERN_INFO PFX "activated.\n"); 133 + 134 + return 0; 135 + } 136 + 137 + /* 138 + * Stop the watchdog 139 + */ 140 + 141 + static int wdt_stop(void) 142 + { 143 + unsigned long flags; 144 + 145 + spin_lock_irqsave(&spinlock, flags); 146 + 147 + /* Unlock the SuperIO chip */ 148 + outb_p(UNLOCK_DATA,IO_INDEX_PORT); 149 + outb_p(UNLOCK_DATA,IO_INDEX_PORT); 150 + 151 + /* 152 + * Select device Aux2 (device=8) to set watchdog regs F2, F3 and F4. 153 + * F2 is reset to its default value (watchdog timer disabled). 154 + * F3 is reset to its default state. 155 + * F4 clears the TIMEOUT'ed state (bit 0) - back to default. 156 + */ 157 + outb_p(DEVICE_REGISTER,IO_INDEX_PORT); 158 + outb_p(0x08,IO_DATA_PORT); 159 + outb_p(0xF2,IO_INDEX_PORT); 160 + outb_p(0xFF,IO_DATA_PORT); 161 + outb_p(0xF3,IO_INDEX_PORT); 162 + outb_p(0x00,IO_DATA_PORT); 163 + outb_p(0xF4,IO_INDEX_PORT); 164 + outb_p(0x00,IO_DATA_PORT); 165 + outb_p(0xF2,IO_INDEX_PORT); 166 + outb_p(0x00,IO_DATA_PORT); 167 + 168 + /* 169 + * Select device Aux1 (dev=7) to set GP16 (in reg E6) and 170 + * Gp13 (in reg E3) as inputs. 171 + */ 172 + outb_p(DEVICE_REGISTER,IO_INDEX_PORT); 173 + outb_p(0x07,IO_DATA_PORT); 174 + if (!testmode) 175 + { 176 + outb_p(0xE6,IO_INDEX_PORT); 177 + outb_p(0x01,IO_DATA_PORT); 178 + } 179 + outb_p(0xE3,IO_INDEX_PORT); 180 + outb_p(0x01,IO_DATA_PORT); 181 + 182 + /* Lock the SuperIO chip */ 183 + outb_p(LOCK_DATA,IO_INDEX_PORT); 184 + 185 + spin_unlock_irqrestore(&spinlock, flags); 186 + 187 + printk(KERN_INFO PFX "shutdown.\n"); 188 + 189 + return 0; 190 + } 191 + 192 + /* 193 + * Send a keepalive ping to the watchdog 194 + * This is done by simply re-writing the timeout to reg. 0xF2 195 + */ 196 + 197 + static int wdt_keepalive(void) 198 + { 199 + unsigned long flags; 200 + 201 + spin_lock_irqsave(&spinlock, flags); 202 + 203 + /* Unlock the SuperIO chip */ 204 + outb_p(UNLOCK_DATA,IO_INDEX_PORT); 205 + outb_p(UNLOCK_DATA,IO_INDEX_PORT); 206 + 207 + /* Select device Aux2 (device=8) to kick watchdog reg F2 */ 208 + outb_p(DEVICE_REGISTER,IO_INDEX_PORT); 209 + outb_p(0x08,IO_DATA_PORT); 210 + outb_p(0xF2,IO_INDEX_PORT); 211 + outb_p(timeoutW,IO_DATA_PORT); 212 + 213 + /* Lock the SuperIO chip */ 214 + outb_p(LOCK_DATA,IO_INDEX_PORT); 215 + 216 + spin_unlock_irqrestore(&spinlock, flags); 217 + 218 + return 0; 219 + } 220 + 221 + /* 222 + * Set the watchdog timeout value 223 + */ 224 + 225 + static int wdt_set_timeout(int t) 226 + { 227 + int tmrval; 228 + 229 + /* 230 + * Convert seconds to watchdog counter time units, rounding up. 231 + * On PCM-5335 watchdog units are 30 seconds/step with 15 sec startup 232 + * value. This information is supplied in the PCM-5335 manual and was 233 + * checked by me on a real board. This is a bit strange because W83977f 234 + * datasheet says counter unit is in minutes! 235 + */ 236 + if (t < 15) 237 + return -EINVAL; 238 + 239 + tmrval = ((t + 15) + 29) / 30; 240 + 241 + if (tmrval > 255) 242 + return -EINVAL; 243 + 244 + /* 245 + * timeout is the timeout in seconds, 246 + * timeoutW is the timeout in watchdog counter units. 247 + */ 248 + timeoutW = tmrval; 249 + timeout = (timeoutW * 30) - 15; 250 + return 0; 251 + } 252 + 253 + /* 254 + * Get the watchdog status 255 + */ 256 + 257 + static int wdt_get_status(int *status) 258 + { 259 + int new_status; 260 + unsigned long flags; 261 + 262 + spin_lock_irqsave(&spinlock, flags); 263 + 264 + /* Unlock the SuperIO chip */ 265 + outb_p(UNLOCK_DATA,IO_INDEX_PORT); 266 + outb_p(UNLOCK_DATA,IO_INDEX_PORT); 267 + 268 + /* Select device Aux2 (device=8) to read watchdog reg F4 */ 269 + outb_p(DEVICE_REGISTER,IO_INDEX_PORT); 270 + outb_p(0x08,IO_DATA_PORT); 271 + outb_p(0xF4,IO_INDEX_PORT); 272 + new_status = inb_p(IO_DATA_PORT); 273 + 274 + /* Lock the SuperIO chip */ 275 + outb_p(LOCK_DATA,IO_INDEX_PORT); 276 + 277 + spin_unlock_irqrestore(&spinlock, flags); 278 + 279 + *status = 0; 280 + if (new_status & 1) 281 + *status |= WDIOF_CARDRESET; 282 + 283 + return 0; 284 + } 285 + 286 + 287 + /* 288 + * /dev/watchdog handling 289 + */ 290 + 291 + static int wdt_open(struct inode *inode, struct file *file) 292 + { 293 + /* If the watchdog is alive we don't need to start it again */ 294 + if( test_and_set_bit(0, &timer_alive) ) 295 + return -EBUSY; 296 + 297 + if (nowayout) 298 + __module_get(THIS_MODULE); 299 + 300 + wdt_start(); 301 + return nonseekable_open(inode, file); 302 + } 303 + 304 + static int wdt_release(struct inode *inode, struct file *file) 305 + { 306 + /* 307 + * Shut off the timer. 308 + * Lock it in if it's a module and we set nowayout 309 + */ 310 + if (expect_close == 42) 311 + { 312 + wdt_stop(); 313 + clear_bit(0, &timer_alive); 314 + } else { 315 + wdt_keepalive(); 316 + printk(KERN_CRIT PFX "unexpected close, not stopping watchdog!\n"); 317 + } 318 + expect_close = 0; 319 + return 0; 320 + } 321 + 322 + /* 323 + * wdt_write: 324 + * @file: file handle to the watchdog 325 + * @buf: buffer to write (unused as data does not matter here 326 + * @count: count of bytes 327 + * @ppos: pointer to the position to write. No seeks allowed 328 + * 329 + * A write to a watchdog device is defined as a keepalive signal. Any 330 + * write of data will do, as we we don't define content meaning. 331 + */ 332 + 333 + static ssize_t wdt_write(struct file *file, const char __user *buf, 334 + size_t count, loff_t *ppos) 335 + { 336 + /* See if we got the magic character 'V' and reload the timer */ 337 + if(count) 338 + { 339 + if (!nowayout) 340 + { 341 + size_t ofs; 342 + 343 + /* note: just in case someone wrote the magic character long ago */ 344 + expect_close = 0; 345 + 346 + /* scan to see whether or not we got the magic character */ 347 + for(ofs = 0; ofs != count; ofs++) 348 + { 349 + char c; 350 + if (get_user(c, buf + ofs)) 351 + return -EFAULT; 352 + if (c == 'V') { 353 + expect_close = 42; 354 + } 355 + } 356 + } 357 + 358 + /* someone wrote to us, we should restart timer */ 359 + wdt_keepalive(); 360 + } 361 + return count; 362 + } 363 + 364 + /* 365 + * wdt_ioctl: 366 + * @inode: inode of the device 367 + * @file: file handle to the device 368 + * @cmd: watchdog command 369 + * @arg: argument pointer 370 + * 371 + * The watchdog API defines a common set of functions for all watchdogs 372 + * according to their available features. 373 + */ 374 + 375 + static struct watchdog_info ident = { 376 + .options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING, 377 + .firmware_version = 1, 378 + .identity = WATCHDOG_NAME, 379 + }; 380 + 381 + static int wdt_ioctl(struct inode *inode, struct file *file, 382 + unsigned int cmd, unsigned long arg) 383 + { 384 + int status; 385 + int new_options, retval = -EINVAL; 386 + int new_timeout; 387 + union { 388 + struct watchdog_info __user *ident; 389 + int __user *i; 390 + } uarg; 391 + 392 + uarg.i = (int __user *)arg; 393 + 394 + switch(cmd) 395 + { 396 + default: 397 + return -ENOIOCTLCMD; 398 + 399 + case WDIOC_GETSUPPORT: 400 + return copy_to_user(uarg.ident, &ident, sizeof(ident)) ? -EFAULT : 0; 401 + 402 + case WDIOC_GETSTATUS: 403 + wdt_get_status(&status); 404 + return put_user(status, uarg.i); 405 + 406 + case WDIOC_GETBOOTSTATUS: 407 + return put_user(0, uarg.i); 408 + 409 + case WDIOC_KEEPALIVE: 410 + wdt_keepalive(); 411 + return 0; 412 + 413 + case WDIOC_SETOPTIONS: 414 + if (get_user (new_options, uarg.i)) 415 + return -EFAULT; 416 + 417 + if (new_options & WDIOS_DISABLECARD) { 418 + wdt_stop(); 419 + retval = 0; 420 + } 421 + 422 + if (new_options & WDIOS_ENABLECARD) { 423 + wdt_start(); 424 + retval = 0; 425 + } 426 + 427 + return retval; 428 + 429 + case WDIOC_SETTIMEOUT: 430 + if (get_user(new_timeout, uarg.i)) 431 + return -EFAULT; 432 + 433 + if (wdt_set_timeout(new_timeout)) 434 + return -EINVAL; 435 + 436 + wdt_keepalive(); 437 + /* Fall */ 438 + 439 + case WDIOC_GETTIMEOUT: 440 + return put_user(timeout, uarg.i); 441 + 442 + } 443 + } 444 + 445 + static int wdt_notify_sys(struct notifier_block *this, unsigned long code, 446 + void *unused) 447 + { 448 + if (code==SYS_DOWN || code==SYS_HALT) 449 + wdt_stop(); 450 + return NOTIFY_DONE; 451 + } 452 + 453 + static struct file_operations wdt_fops= 454 + { 455 + .owner = THIS_MODULE, 456 + .llseek = no_llseek, 457 + .write = wdt_write, 458 + .ioctl = wdt_ioctl, 459 + .open = wdt_open, 460 + .release = wdt_release, 461 + }; 462 + 463 + static struct miscdevice wdt_miscdev= 464 + { 465 + .minor = WATCHDOG_MINOR, 466 + .name = "watchdog", 467 + .fops = &wdt_fops, 468 + }; 469 + 470 + static struct notifier_block wdt_notifier = { 471 + .notifier_call = wdt_notify_sys, 472 + }; 473 + 474 + static int __init w83977f_wdt_init(void) 475 + { 476 + int rc; 477 + 478 + printk(KERN_INFO PFX DRIVER_VERSION); 479 + 480 + spin_lock_init(&spinlock); 481 + 482 + /* 483 + * Check that the timeout value is within it's range ; 484 + * if not reset to the default 485 + */ 486 + if (wdt_set_timeout(timeout)) { 487 + wdt_set_timeout(DEFAULT_TIMEOUT); 488 + printk(KERN_INFO PFX "timeout value must be 15<=timeout<=7635, using %d\n", 489 + DEFAULT_TIMEOUT); 490 + } 491 + 492 + if (!request_region(IO_INDEX_PORT, 2, WATCHDOG_NAME)) 493 + { 494 + printk(KERN_ERR PFX "I/O address 0x%04x already in use\n", 495 + IO_INDEX_PORT); 496 + rc = -EIO; 497 + goto err_out; 498 + } 499 + 500 + rc = misc_register(&wdt_miscdev); 501 + if (rc) 502 + { 503 + printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", 504 + wdt_miscdev.minor, rc); 505 + goto err_out_region; 506 + } 507 + 508 + rc = register_reboot_notifier(&wdt_notifier); 509 + if (rc) 510 + { 511 + printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", 512 + rc); 513 + goto err_out_miscdev; 514 + } 515 + 516 + printk(KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d testmode=%d)\n", 517 + timeout, nowayout, testmode); 518 + 519 + return 0; 520 + 521 + err_out_miscdev: 522 + misc_deregister(&wdt_miscdev); 523 + err_out_region: 524 + release_region(IO_INDEX_PORT,2); 525 + err_out: 526 + return rc; 527 + } 528 + 529 + static void __exit w83977f_wdt_exit(void) 530 + { 531 + wdt_stop(); 532 + misc_deregister(&wdt_miscdev); 533 + unregister_reboot_notifier(&wdt_notifier); 534 + release_region(IO_INDEX_PORT,2); 535 + } 536 + 537 + module_init(w83977f_wdt_init); 538 + module_exit(w83977f_wdt_exit); 539 + 540 + MODULE_AUTHOR("Jose Goncalves <jose.goncalves@inov.pt>"); 541 + MODULE_DESCRIPTION("Driver for watchdog timer in W83977F I/O chip"); 542 + MODULE_LICENSE("GPL"); 543 + MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
+8
include/asm-ppc/mv64x60.h
··· 119 120 #define MV64x60_64BIT_WIN_COUNT 24 121 122 /* 123 * Define a structure that's used to pass in config information to the 124 * core routines.
··· 119 120 #define MV64x60_64BIT_WIN_COUNT 24 121 122 + /* Watchdog Platform Device, Driver Data */ 123 + #define MV64x60_WDT_NAME "wdt" 124 + 125 + struct mv64x60_wdt_pdata { 126 + int timeout; /* watchdog expiry in seconds, default 10 */ 127 + int bus_clk; /* bus clock in MHz, default 133 */ 128 + }; 129 + 130 /* 131 * Define a structure that's used to pass in config information to the 132 * core routines.