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