Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.31 542 lines 14 kB view raw
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-004 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/platform_device.h> 38#include <linux/init.h> 39#include <linux/pci.h> 40#include <linux/ioport.h> 41#include <linux/uaccess.h> 42#include <linux/io.h> 43 44/* Module and version information */ 45#define ESB_VERSION "0.04" 46#define ESB_MODULE_NAME "i6300ESB timer" 47#define ESB_DRIVER_NAME ESB_MODULE_NAME ", v" ESB_VERSION 48#define PFX ESB_MODULE_NAME ": " 49 50/* PCI configuration registers */ 51#define ESB_CONFIG_REG 0x60 /* Config register */ 52#define ESB_LOCK_REG 0x68 /* WDT lock register */ 53 54/* Memory mapped registers */ 55#define ESB_TIMER1_REG (BASEADDR + 0x00)/* Timer1 value after each reset */ 56#define ESB_TIMER2_REG (BASEADDR + 0x04)/* Timer2 value after each reset */ 57#define ESB_GINTSR_REG (BASEADDR + 0x08)/* General Interrupt Status Register */ 58#define ESB_RELOAD_REG (BASEADDR + 0x0c)/* Reload register */ 59 60/* Lock register bits */ 61#define ESB_WDT_FUNC (0x01 << 2) /* Watchdog functionality */ 62#define ESB_WDT_ENABLE (0x01 << 1) /* Enable WDT */ 63#define ESB_WDT_LOCK (0x01 << 0) /* Lock (nowayout) */ 64 65/* Config register bits */ 66#define ESB_WDT_REBOOT (0x01 << 5) /* Enable reboot on timeout */ 67#define ESB_WDT_FREQ (0x01 << 2) /* Decrement frequency */ 68#define ESB_WDT_INTTYPE (0x11 << 0) /* Interrupt type on timer1 timeout */ 69 70/* Reload register bits */ 71#define ESB_WDT_TIMEOUT (0x01 << 9) /* Watchdog timed out */ 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 */ 79static void __iomem *BASEADDR; 80static DEFINE_SPINLOCK(esb_lock); /* Guards the hardware */ 81static unsigned long timer_alive; 82static struct pci_dev *esb_pci; 83static unsigned short triggered; /* The status of the watchdog upon boot */ 84static char esb_expect_close; 85static struct platform_device *esb_platform_device; 86 87/* module parameters */ 88/* 30 sec default heartbeat (1 < heartbeat < 2*1023) */ 89#define WATCHDOG_HEARTBEAT 30 90static int heartbeat = WATCHDOG_HEARTBEAT; /* in seconds */ 91module_param(heartbeat, int, 0); 92MODULE_PARM_DESC(heartbeat, 93 "Watchdog heartbeat in seconds. (1<heartbeat<2046, default=" 94 __MODULE_STRING(WATCHDOG_HEARTBEAT) ")"); 95 96static int nowayout = WATCHDOG_NOWAYOUT; 97module_param(nowayout, int, 0); 98MODULE_PARM_DESC(nowayout, 99 "Watchdog cannot be stopped once started (default=" 100 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 101 102/* 103 * Some i6300ESB specific functions 104 */ 105 106/* 107 * Prepare for reloading the timer by unlocking the proper registers. 108 * This is performed by first writing 0x80 followed by 0x86 to the 109 * reload register. After this the appropriate registers can be written 110 * to once before they need to be unlocked again. 111 */ 112static inline void esb_unlock_registers(void) 113{ 114 writeb(ESB_UNLOCK1, ESB_RELOAD_REG); 115 writeb(ESB_UNLOCK2, ESB_RELOAD_REG); 116} 117 118static int esb_timer_start(void) 119{ 120 u8 val; 121 122 spin_lock(&esb_lock); 123 esb_unlock_registers(); 124 writew(ESB_WDT_RELOAD, ESB_RELOAD_REG); 125 /* Enable or Enable + Lock? */ 126 val = ESB_WDT_ENABLE | (nowayout ? ESB_WDT_LOCK : 0x00); 127 pci_write_config_byte(esb_pci, ESB_LOCK_REG, val); 128 spin_unlock(&esb_lock); 129 return 0; 130} 131 132static int esb_timer_stop(void) 133{ 134 u8 val; 135 136 spin_lock(&esb_lock); 137 /* First, reset timers as suggested by the docs */ 138 esb_unlock_registers(); 139 writew(ESB_WDT_RELOAD, ESB_RELOAD_REG); 140 /* Then disable the WDT */ 141 pci_write_config_byte(esb_pci, ESB_LOCK_REG, 0x0); 142 pci_read_config_byte(esb_pci, ESB_LOCK_REG, &val); 143 spin_unlock(&esb_lock); 144 145 /* Returns 0 if the timer was disabled, non-zero otherwise */ 146 return val & ESB_WDT_ENABLE; 147} 148 149static void esb_timer_keepalive(void) 150{ 151 spin_lock(&esb_lock); 152 esb_unlock_registers(); 153 writew(ESB_WDT_RELOAD, ESB_RELOAD_REG); 154 /* FIXME: Do we need to flush anything here? */ 155 spin_unlock(&esb_lock); 156} 157 158static int esb_timer_set_heartbeat(int time) 159{ 160 u32 val; 161 162 if (time < 0x1 || time > (2 * 0x03ff)) 163 return -EINVAL; 164 165 spin_lock(&esb_lock); 166 167 /* We shift by 9, so if we are passed a value of 1 sec, 168 * val will be 1 << 9 = 512, then write that to two 169 * timers => 2 * 512 = 1024 (which is decremented at 1KHz) 170 */ 171 val = time << 9; 172 173 /* Write timer 1 */ 174 esb_unlock_registers(); 175 writel(val, ESB_TIMER1_REG); 176 177 /* Write timer 2 */ 178 esb_unlock_registers(); 179 writel(val, ESB_TIMER2_REG); 180 181 /* Reload */ 182 esb_unlock_registers(); 183 writew(ESB_WDT_RELOAD, ESB_RELOAD_REG); 184 185 /* FIXME: Do we need to flush everything out? */ 186 187 /* Done */ 188 heartbeat = time; 189 spin_unlock(&esb_lock); 190 return 0; 191} 192 193/* 194 * /dev/watchdog handling 195 */ 196 197static int esb_open(struct inode *inode, struct file *file) 198{ 199 /* /dev/watchdog can only be opened once */ 200 if (test_and_set_bit(0, &timer_alive)) 201 return -EBUSY; 202 203 /* Reload and activate timer */ 204 esb_timer_start(); 205 206 return nonseekable_open(inode, file); 207} 208 209static int esb_release(struct inode *inode, struct file *file) 210{ 211 /* Shut off the timer. */ 212 if (esb_expect_close == 42) 213 esb_timer_stop(); 214 else { 215 printk(KERN_CRIT PFX 216 "Unexpected close, not stopping watchdog!\n"); 217 esb_timer_keepalive(); 218 } 219 clear_bit(0, &timer_alive); 220 esb_expect_close = 0; 221 return 0; 222} 223 224static ssize_t esb_write(struct file *file, const char __user *data, 225 size_t len, loff_t *ppos) 226{ 227 /* See if we got the magic character 'V' and reload the timer */ 228 if (len) { 229 if (!nowayout) { 230 size_t i; 231 232 /* note: just in case someone wrote the magic character 233 * five months ago... */ 234 esb_expect_close = 0; 235 236 /* scan to see whether or not we got the 237 * 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 253static long esb_ioctl(struct file *file, unsigned int cmd, unsigned long arg) 254{ 255 int new_options, retval = -EINVAL; 256 int new_heartbeat; 257 void __user *argp = (void __user *)arg; 258 int __user *p = argp; 259 static struct watchdog_info ident = { 260 .options = WDIOF_SETTIMEOUT | 261 WDIOF_KEEPALIVEPING | 262 WDIOF_MAGICCLOSE, 263 .firmware_version = 0, 264 .identity = ESB_MODULE_NAME, 265 }; 266 267 switch (cmd) { 268 case WDIOC_GETSUPPORT: 269 return copy_to_user(argp, &ident, 270 sizeof(ident)) ? -EFAULT : 0; 271 272 case WDIOC_GETSTATUS: 273 return put_user(0, p); 274 275 case WDIOC_GETBOOTSTATUS: 276 return put_user(triggered, p); 277 278 case WDIOC_SETOPTIONS: 279 { 280 if (get_user(new_options, p)) 281 return -EFAULT; 282 283 if (new_options & WDIOS_DISABLECARD) { 284 esb_timer_stop(); 285 retval = 0; 286 } 287 288 if (new_options & WDIOS_ENABLECARD) { 289 esb_timer_start(); 290 retval = 0; 291 } 292 return retval; 293 } 294 case WDIOC_KEEPALIVE: 295 esb_timer_keepalive(); 296 return 0; 297 298 case WDIOC_SETTIMEOUT: 299 { 300 if (get_user(new_heartbeat, p)) 301 return -EFAULT; 302 if (esb_timer_set_heartbeat(new_heartbeat)) 303 return -EINVAL; 304 esb_timer_keepalive(); 305 /* Fall */ 306 } 307 case WDIOC_GETTIMEOUT: 308 return put_user(heartbeat, p); 309 default: 310 return -ENOTTY; 311 } 312} 313 314/* 315 * Kernel Interfaces 316 */ 317 318static const struct file_operations esb_fops = { 319 .owner = THIS_MODULE, 320 .llseek = no_llseek, 321 .write = esb_write, 322 .unlocked_ioctl = esb_ioctl, 323 .open = esb_open, 324 .release = esb_release, 325}; 326 327static struct miscdevice esb_miscdev = { 328 .minor = WATCHDOG_MINOR, 329 .name = "watchdog", 330 .fops = &esb_fops, 331}; 332 333/* 334 * Data for PCI driver interface 335 * 336 * This data only exists for exporting the supported 337 * PCI ids via MODULE_DEVICE_TABLE. We do not actually 338 * register a pci_driver, because someone else might one day 339 * want to register another driver on the same PCI id. 340 */ 341static struct pci_device_id esb_pci_tbl[] = { 342 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_9), }, 343 { 0, }, /* End of list */ 344}; 345MODULE_DEVICE_TABLE(pci, esb_pci_tbl); 346 347/* 348 * Init & exit routines 349 */ 350 351static unsigned char __devinit esb_getdevice(void) 352{ 353 /* 354 * Find the PCI device 355 */ 356 357 esb_pci = pci_get_device(PCI_VENDOR_ID_INTEL, 358 PCI_DEVICE_ID_INTEL_ESB_9, NULL); 359 360 if (!esb_pci) 361 return 0; 362 363 if (pci_enable_device(esb_pci)) { 364 printk(KERN_ERR PFX "failed to enable device\n"); 365 goto err_devput; 366 } 367 368 if (pci_request_region(esb_pci, 0, ESB_MODULE_NAME)) { 369 printk(KERN_ERR PFX "failed to request region\n"); 370 goto err_disable; 371 } 372 373 BASEADDR = pci_ioremap_bar(esb_pci, 0); 374 if (BASEADDR == NULL) { 375 /* Something's wrong here, BASEADDR has to be set */ 376 printk(KERN_ERR PFX "failed to get BASEADDR\n"); 377 goto err_release; 378 } 379 380 /* Done */ 381 return 1; 382 383err_release: 384 pci_release_region(esb_pci, 0); 385err_disable: 386 pci_disable_device(esb_pci); 387err_devput: 388 pci_dev_put(esb_pci); 389 return 0; 390} 391 392static void __devinit esb_initdevice(void) 393{ 394 u8 val1; 395 u16 val2; 396 397 /* 398 * Config register: 399 * Bit 5 : 0 = Enable WDT_OUTPUT 400 * Bit 2 : 0 = set the timer frequency to the PCI clock 401 * divided by 2^15 (approx 1KHz). 402 * Bits 1:0 : 11 = WDT_INT_TYPE Disabled. 403 * The watchdog has two timers, it can be setup so that the 404 * expiry of timer1 results in an interrupt and the expiry of 405 * timer2 results in a reboot. We set it to not generate 406 * any interrupts as there is not much we can do with it 407 * right now. 408 */ 409 pci_write_config_word(esb_pci, ESB_CONFIG_REG, 0x0003); 410 411 /* Check that the WDT isn't already locked */ 412 pci_read_config_byte(esb_pci, ESB_LOCK_REG, &val1); 413 if (val1 & ESB_WDT_LOCK) 414 printk(KERN_WARNING PFX "nowayout already set\n"); 415 416 /* Set the timer to watchdog mode and disable it for now */ 417 pci_write_config_byte(esb_pci, ESB_LOCK_REG, 0x00); 418 419 /* Check if the watchdog was previously triggered */ 420 esb_unlock_registers(); 421 val2 = readw(ESB_RELOAD_REG); 422 if (val2 & ESB_WDT_TIMEOUT) 423 triggered = WDIOF_CARDRESET; 424 425 /* Reset WDT_TIMEOUT flag and timers */ 426 esb_unlock_registers(); 427 writew((ESB_WDT_TIMEOUT | ESB_WDT_RELOAD), ESB_RELOAD_REG); 428 429 /* And set the correct timeout value */ 430 esb_timer_set_heartbeat(heartbeat); 431} 432 433static int __devinit esb_probe(struct platform_device *dev) 434{ 435 int ret; 436 437 /* Check whether or not the hardware watchdog is there */ 438 if (!esb_getdevice() || esb_pci == NULL) 439 return -ENODEV; 440 441 /* Check that the heartbeat value is within it's range; 442 if not reset to the default */ 443 if (heartbeat < 0x1 || heartbeat > 2 * 0x03ff) { 444 heartbeat = WATCHDOG_HEARTBEAT; 445 printk(KERN_INFO PFX 446 "heartbeat value must be 1<heartbeat<2046, using %d\n", 447 heartbeat); 448 } 449 450 /* Initialize the watchdog and make sure it does not run */ 451 esb_initdevice(); 452 453 /* Register the watchdog so that userspace has access to it */ 454 ret = misc_register(&esb_miscdev); 455 if (ret != 0) { 456 printk(KERN_ERR PFX 457 "cannot register miscdev on minor=%d (err=%d)\n", 458 WATCHDOG_MINOR, ret); 459 goto err_unmap; 460 } 461 printk(KERN_INFO PFX 462 "initialized (0x%p). heartbeat=%d sec (nowayout=%d)\n", 463 BASEADDR, heartbeat, nowayout); 464 return 0; 465 466err_unmap: 467 iounmap(BASEADDR); 468 pci_release_region(esb_pci, 0); 469 pci_disable_device(esb_pci); 470 pci_dev_put(esb_pci); 471 return ret; 472} 473 474static int __devexit esb_remove(struct platform_device *dev) 475{ 476 /* Stop the timer before we leave */ 477 if (!nowayout) 478 esb_timer_stop(); 479 480 /* Deregister */ 481 misc_deregister(&esb_miscdev); 482 iounmap(BASEADDR); 483 pci_release_region(esb_pci, 0); 484 pci_disable_device(esb_pci); 485 pci_dev_put(esb_pci); 486 return 0; 487} 488 489static void esb_shutdown(struct platform_device *dev) 490{ 491 esb_timer_stop(); 492} 493 494static struct platform_driver esb_platform_driver = { 495 .probe = esb_probe, 496 .remove = __devexit_p(esb_remove), 497 .shutdown = esb_shutdown, 498 .driver = { 499 .owner = THIS_MODULE, 500 .name = ESB_MODULE_NAME, 501 }, 502}; 503 504static int __init watchdog_init(void) 505{ 506 int err; 507 508 printk(KERN_INFO PFX "Intel 6300ESB WatchDog Timer Driver v%s\n", 509 ESB_VERSION); 510 511 err = platform_driver_register(&esb_platform_driver); 512 if (err) 513 return err; 514 515 esb_platform_device = platform_device_register_simple(ESB_MODULE_NAME, 516 -1, NULL, 0); 517 if (IS_ERR(esb_platform_device)) { 518 err = PTR_ERR(esb_platform_device); 519 goto unreg_platform_driver; 520 } 521 522 return 0; 523 524unreg_platform_driver: 525 platform_driver_unregister(&esb_platform_driver); 526 return err; 527} 528 529static void __exit watchdog_cleanup(void) 530{ 531 platform_device_unregister(esb_platform_device); 532 platform_driver_unregister(&esb_platform_driver); 533 printk(KERN_INFO PFX "Watchdog Module Unloaded.\n"); 534} 535 536module_init(watchdog_init); 537module_exit(watchdog_cleanup); 538 539MODULE_AUTHOR("Ross Biro and David Härdeman"); 540MODULE_DESCRIPTION("Watchdog driver for Intel 6300ESB chipsets"); 541MODULE_LICENSE("GPL"); 542MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);