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 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 31 32 #include <linux/module.h> 33 #include <linux/types.h> 34 #include <linux/kernel.h> 35 #include <linux/fs.h> 36 #include <linux/mm.h> 37 #include <linux/miscdevice.h> 38 #include <linux/watchdog.h> 39 #include <linux/init.h> 40 #include <linux/pci.h> 41 #include <linux/ioport.h> 42 #include <linux/uaccess.h> 43 #include <linux/io.h> 44 45 /* Module and version information */ 46 #define ESB_VERSION "0.05" 47 #define ESB_MODULE_NAME "i6300ESB timer" 48 #define ESB_DRIVER_NAME ESB_MODULE_NAME ", v" ESB_VERSION 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 (0x03 << 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 */ 79 static void __iomem *BASEADDR; 80 static DEFINE_SPINLOCK(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 /* We can only use 1 card due to the /dev/watchdog restriction */ 87 static int cards_found; 88 89 /* module parameters */ 90 /* 30 sec default heartbeat (1 < heartbeat < 2*1023) */ 91 #define WATCHDOG_HEARTBEAT 30 92 static int heartbeat = WATCHDOG_HEARTBEAT; /* in seconds */ 93 module_param(heartbeat, int, 0); 94 MODULE_PARM_DESC(heartbeat, 95 "Watchdog heartbeat in seconds. (1<heartbeat<2046, default=" 96 __MODULE_STRING(WATCHDOG_HEARTBEAT) ")"); 97 98 static bool nowayout = WATCHDOG_NOWAYOUT; 99 module_param(nowayout, bool, 0); 100 MODULE_PARM_DESC(nowayout, 101 "Watchdog cannot be stopped once started (default=" 102 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 103 104 /* 105 * Some i6300ESB specific functions 106 */ 107 108 /* 109 * Prepare for reloading the timer by unlocking the proper registers. 110 * This is performed by first writing 0x80 followed by 0x86 to the 111 * reload register. After this the appropriate registers can be written 112 * to once before they need to be unlocked again. 113 */ 114 static inline void esb_unlock_registers(void) 115 { 116 writew(ESB_UNLOCK1, ESB_RELOAD_REG); 117 writew(ESB_UNLOCK2, ESB_RELOAD_REG); 118 } 119 120 static int esb_timer_start(void) 121 { 122 u8 val; 123 124 spin_lock(&esb_lock); 125 esb_unlock_registers(); 126 writew(ESB_WDT_RELOAD, ESB_RELOAD_REG); 127 /* Enable or Enable + Lock? */ 128 val = ESB_WDT_ENABLE | (nowayout ? ESB_WDT_LOCK : 0x00); 129 pci_write_config_byte(esb_pci, ESB_LOCK_REG, val); 130 spin_unlock(&esb_lock); 131 return 0; 132 } 133 134 static int esb_timer_stop(void) 135 { 136 u8 val; 137 138 spin_lock(&esb_lock); 139 /* First, reset timers as suggested by the docs */ 140 esb_unlock_registers(); 141 writew(ESB_WDT_RELOAD, ESB_RELOAD_REG); 142 /* Then disable the WDT */ 143 pci_write_config_byte(esb_pci, ESB_LOCK_REG, 0x0); 144 pci_read_config_byte(esb_pci, ESB_LOCK_REG, &val); 145 spin_unlock(&esb_lock); 146 147 /* Returns 0 if the timer was disabled, non-zero otherwise */ 148 return val & ESB_WDT_ENABLE; 149 } 150 151 static void esb_timer_keepalive(void) 152 { 153 spin_lock(&esb_lock); 154 esb_unlock_registers(); 155 writew(ESB_WDT_RELOAD, ESB_RELOAD_REG); 156 /* FIXME: Do we need to flush anything here? */ 157 spin_unlock(&esb_lock); 158 } 159 160 static int esb_timer_set_heartbeat(int time) 161 { 162 u32 val; 163 164 if (time < 0x1 || time > (2 * 0x03ff)) 165 return -EINVAL; 166 167 spin_lock(&esb_lock); 168 169 /* We shift by 9, so if we are passed a value of 1 sec, 170 * val will be 1 << 9 = 512, then write that to two 171 * timers => 2 * 512 = 1024 (which is decremented at 1KHz) 172 */ 173 val = time << 9; 174 175 /* Write timer 1 */ 176 esb_unlock_registers(); 177 writel(val, ESB_TIMER1_REG); 178 179 /* Write timer 2 */ 180 esb_unlock_registers(); 181 writel(val, ESB_TIMER2_REG); 182 183 /* Reload */ 184 esb_unlock_registers(); 185 writew(ESB_WDT_RELOAD, ESB_RELOAD_REG); 186 187 /* FIXME: Do we need to flush everything out? */ 188 189 /* Done */ 190 heartbeat = time; 191 spin_unlock(&esb_lock); 192 return 0; 193 } 194 195 /* 196 * /dev/watchdog handling 197 */ 198 199 static int esb_open(struct inode *inode, struct file *file) 200 { 201 /* /dev/watchdog can only be opened once */ 202 if (test_and_set_bit(0, &timer_alive)) 203 return -EBUSY; 204 205 /* Reload and activate timer */ 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 pr_crit("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 238 * magic character */ 239 for (i = 0; i != len; i++) { 240 char c; 241 if (get_user(c, data + i)) 242 return -EFAULT; 243 if (c == 'V') 244 esb_expect_close = 42; 245 } 246 } 247 248 /* someone wrote to us, we should reload the timer */ 249 esb_timer_keepalive(); 250 } 251 return len; 252 } 253 254 static long esb_ioctl(struct file *file, 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 const 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(0, p); 275 276 case WDIOC_GETBOOTSTATUS: 277 return put_user(triggered, p); 278 279 case WDIOC_SETOPTIONS: 280 { 281 if (get_user(new_options, p)) 282 return -EFAULT; 283 284 if (new_options & WDIOS_DISABLECARD) { 285 esb_timer_stop(); 286 retval = 0; 287 } 288 289 if (new_options & WDIOS_ENABLECARD) { 290 esb_timer_start(); 291 retval = 0; 292 } 293 return retval; 294 } 295 case WDIOC_KEEPALIVE: 296 esb_timer_keepalive(); 297 return 0; 298 299 case WDIOC_SETTIMEOUT: 300 { 301 if (get_user(new_heartbeat, p)) 302 return -EFAULT; 303 if (esb_timer_set_heartbeat(new_heartbeat)) 304 return -EINVAL; 305 esb_timer_keepalive(); 306 /* Fall */ 307 } 308 case WDIOC_GETTIMEOUT: 309 return put_user(heartbeat, p); 310 default: 311 return -ENOTTY; 312 } 313 } 314 315 /* 316 * Kernel Interfaces 317 */ 318 319 static const struct file_operations esb_fops = { 320 .owner = THIS_MODULE, 321 .llseek = no_llseek, 322 .write = esb_write, 323 .unlocked_ioctl = esb_ioctl, 324 .open = esb_open, 325 .release = esb_release, 326 }; 327 328 static struct miscdevice esb_miscdev = { 329 .minor = WATCHDOG_MINOR, 330 .name = "watchdog", 331 .fops = &esb_fops, 332 }; 333 334 /* 335 * Data for PCI driver interface 336 */ 337 static DEFINE_PCI_DEVICE_TABLE(esb_pci_tbl) = { 338 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_9), }, 339 { 0, }, /* End of list */ 340 }; 341 MODULE_DEVICE_TABLE(pci, esb_pci_tbl); 342 343 /* 344 * Init & exit routines 345 */ 346 347 static unsigned char esb_getdevice(struct pci_dev *pdev) 348 { 349 if (pci_enable_device(pdev)) { 350 pr_err("failed to enable device\n"); 351 goto err_devput; 352 } 353 354 if (pci_request_region(pdev, 0, ESB_MODULE_NAME)) { 355 pr_err("failed to request region\n"); 356 goto err_disable; 357 } 358 359 BASEADDR = pci_ioremap_bar(pdev, 0); 360 if (BASEADDR == NULL) { 361 /* Something's wrong here, BASEADDR has to be set */ 362 pr_err("failed to get BASEADDR\n"); 363 goto err_release; 364 } 365 366 /* Done */ 367 esb_pci = pdev; 368 return 1; 369 370 err_release: 371 pci_release_region(pdev, 0); 372 err_disable: 373 pci_disable_device(pdev); 374 err_devput: 375 return 0; 376 } 377 378 static void esb_initdevice(void) 379 { 380 u8 val1; 381 u16 val2; 382 383 /* 384 * Config register: 385 * Bit 5 : 0 = Enable WDT_OUTPUT 386 * Bit 2 : 0 = set the timer frequency to the PCI clock 387 * divided by 2^15 (approx 1KHz). 388 * Bits 1:0 : 11 = WDT_INT_TYPE Disabled. 389 * The watchdog has two timers, it can be setup so that the 390 * expiry of timer1 results in an interrupt and the expiry of 391 * timer2 results in a reboot. We set it to not generate 392 * any interrupts as there is not much we can do with it 393 * right now. 394 */ 395 pci_write_config_word(esb_pci, ESB_CONFIG_REG, 0x0003); 396 397 /* Check that the WDT isn't already locked */ 398 pci_read_config_byte(esb_pci, ESB_LOCK_REG, &val1); 399 if (val1 & ESB_WDT_LOCK) 400 pr_warn("nowayout already set\n"); 401 402 /* Set the timer to watchdog mode and disable it for now */ 403 pci_write_config_byte(esb_pci, ESB_LOCK_REG, 0x00); 404 405 /* Check if the watchdog was previously triggered */ 406 esb_unlock_registers(); 407 val2 = readw(ESB_RELOAD_REG); 408 if (val2 & ESB_WDT_TIMEOUT) 409 triggered = WDIOF_CARDRESET; 410 411 /* Reset WDT_TIMEOUT flag and timers */ 412 esb_unlock_registers(); 413 writew((ESB_WDT_TIMEOUT | ESB_WDT_RELOAD), ESB_RELOAD_REG); 414 415 /* And set the correct timeout value */ 416 esb_timer_set_heartbeat(heartbeat); 417 } 418 419 static int esb_probe(struct pci_dev *pdev, 420 const struct pci_device_id *ent) 421 { 422 int ret; 423 424 cards_found++; 425 if (cards_found == 1) 426 pr_info("Intel 6300ESB WatchDog Timer Driver v%s\n", 427 ESB_VERSION); 428 429 if (cards_found > 1) { 430 pr_err("This driver only supports 1 device\n"); 431 return -ENODEV; 432 } 433 434 /* Check whether or not the hardware watchdog is there */ 435 if (!esb_getdevice(pdev) || esb_pci == NULL) 436 return -ENODEV; 437 438 /* Check that the heartbeat value is within it's range; 439 if not reset to the default */ 440 if (heartbeat < 0x1 || heartbeat > 2 * 0x03ff) { 441 heartbeat = WATCHDOG_HEARTBEAT; 442 pr_info("heartbeat value must be 1<heartbeat<2046, using %d\n", 443 heartbeat); 444 } 445 446 /* Initialize the watchdog and make sure it does not run */ 447 esb_initdevice(); 448 449 /* Register the watchdog so that userspace has access to it */ 450 ret = misc_register(&esb_miscdev); 451 if (ret != 0) { 452 pr_err("cannot register miscdev on minor=%d (err=%d)\n", 453 WATCHDOG_MINOR, ret); 454 goto err_unmap; 455 } 456 pr_info("initialized (0x%p). heartbeat=%d sec (nowayout=%d)\n", 457 BASEADDR, heartbeat, nowayout); 458 return 0; 459 460 err_unmap: 461 iounmap(BASEADDR); 462 pci_release_region(esb_pci, 0); 463 pci_disable_device(esb_pci); 464 esb_pci = NULL; 465 return ret; 466 } 467 468 static void esb_remove(struct pci_dev *pdev) 469 { 470 /* Stop the timer before we leave */ 471 if (!nowayout) 472 esb_timer_stop(); 473 474 /* Deregister */ 475 misc_deregister(&esb_miscdev); 476 iounmap(BASEADDR); 477 pci_release_region(esb_pci, 0); 478 pci_disable_device(esb_pci); 479 esb_pci = NULL; 480 } 481 482 static void esb_shutdown(struct pci_dev *pdev) 483 { 484 esb_timer_stop(); 485 } 486 487 static struct pci_driver esb_driver = { 488 .name = ESB_MODULE_NAME, 489 .id_table = esb_pci_tbl, 490 .probe = esb_probe, 491 .remove = esb_remove, 492 .shutdown = esb_shutdown, 493 }; 494 495 module_pci_driver(esb_driver); 496 497 MODULE_AUTHOR("Ross Biro and David Härdeman"); 498 MODULE_DESCRIPTION("Watchdog driver for Intel 6300ESB chipsets"); 499 MODULE_LICENSE("GPL"); 500 MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); 501