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

watchdog: Intel SCU Watchdog Timer Driver for Moorestown and Medfield platforms.

This submission includes:
- Fix to intel_scu_write() to start watchdog timer the on the
first write, and refresh on subsequent writes.
This enables Open, write, write, ... usage model.
- Moves boot parameter checks from intel_scu_open() to
intel_scu_watchdog_init(), so driver init will fail if these
parameters are out of bounds.
- Adds check for whether process waiting in wait_event_interruptible()
received a signal while it was waiting.
- Other small error handling changes.

Removed the read() method for now as that wass a non-standard behaviour.

Signed-off-by: Donald Johnson <donald.k.johnson@intel.com>
Signed-off-by: Shuduo Sang <shuduo.sang@intel.com>
Signed-off-by: Alan Cox <alan@linux.intel.com>
Signed-off-by: Wim Van Sebroeck <wim@iguana.be>

authored by

Donald Johnson and committed by
Wim Van Sebroeck
57539c1c 742e4b63

+649
+10
drivers/watchdog/Kconfig
··· 533 533 To compile this driver as a module, choose M here: the 534 534 module will be called i6300esb. 535 535 536 + config INTEL_SCU_WATCHDOG 537 + bool "Intel SCU Watchdog for Mobile Platforms" 538 + depends on WATCHDOG 539 + depends on INTEL_SCU_IPC 540 + ---help--- 541 + Hardware driver for the watchdog time built into the Intel SCU 542 + for Intel Mobile Platforms. 543 + 544 + To compile this driver as a module, choose M here. 545 + 536 546 config ITCO_WDT 537 547 tristate "Intel TCO Timer/Watchdog" 538 548 depends on (X86 || IA64) && PCI
+1
drivers/watchdog/Makefile
··· 102 102 obj-$(CONFIG_W83977F_WDT) += w83977f_wdt.o 103 103 obj-$(CONFIG_MACHZ_WDT) += machzwd.o 104 104 obj-$(CONFIG_SBC_EPX_C3_WATCHDOG) += sbc_epx_c3.o 105 + obj-$(CONFIG_INTEL_SCU_WATCHDOG) += intel_scu_watchdog.o 105 106 106 107 # M32R Architecture 107 108
+572
drivers/watchdog/intel_scu_watchdog.c
··· 1 + /* 2 + * Intel_SCU 0.2: An Intel SCU IOH Based Watchdog Device 3 + * for Intel part #(s): 4 + * - AF82MP20 PCH 5 + * 6 + * Copyright (C) 2009-2010 Intel Corporation. All rights reserved. 7 + * 8 + * This program is free software; you can redistribute it and/or 9 + * modify it under the terms of version 2 of the GNU General 10 + * Public License as published by the Free Software Foundation. 11 + * 12 + * This program is distributed in the hope that it will be 13 + * useful, but WITHOUT ANY WARRANTY; without even the implied 14 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 15 + * PURPOSE. See the GNU General Public License for more details. 16 + * You should have received a copy of the GNU General Public 17 + * License along with this program; if not, write to the Free 18 + * Software Foundation, Inc., 59 Temple Place - Suite 330, 19 + * Boston, MA 02111-1307, USA. 20 + * The full GNU General Public License is included in this 21 + * distribution in the file called COPYING. 22 + * 23 + */ 24 + 25 + #include <linux/compiler.h> 26 + #include <linux/module.h> 27 + #include <linux/kernel.h> 28 + #include <linux/moduleparam.h> 29 + #include <linux/types.h> 30 + #include <linux/miscdevice.h> 31 + #include <linux/watchdog.h> 32 + #include <linux/fs.h> 33 + #include <linux/notifier.h> 34 + #include <linux/reboot.h> 35 + #include <linux/init.h> 36 + #include <linux/jiffies.h> 37 + #include <linux/uaccess.h> 38 + #include <linux/slab.h> 39 + #include <linux/io.h> 40 + #include <linux/interrupt.h> 41 + #include <linux/delay.h> 42 + #include <linux/sched.h> 43 + #include <linux/signal.h> 44 + #include <linux/sfi.h> 45 + #include <linux/types.h> 46 + #include <asm/irq.h> 47 + #include <asm/atomic.h> 48 + #include <asm/intel_scu_ipc.h> 49 + #include <asm/apb_timer.h> 50 + #include <asm/mrst.h> 51 + 52 + #include "intel_scu_watchdog.h" 53 + 54 + /* Bounds number of times we will retry loading time count */ 55 + /* This retry is a work around for a silicon bug. */ 56 + #define MAX_RETRY 16 57 + 58 + #define IPC_SET_WATCHDOG_TIMER 0xF8 59 + 60 + static int timer_margin = DEFAULT_SOFT_TO_HARD_MARGIN; 61 + module_param(timer_margin, int, 0); 62 + MODULE_PARM_DESC(timer_margin, 63 + "Watchdog timer margin" 64 + "Time between interrupt and resetting the system" 65 + "The range is from 1 to 160" 66 + "This is the time for all keep alives to arrive"); 67 + 68 + static int timer_set = DEFAULT_TIME; 69 + module_param(timer_set, int, 0); 70 + MODULE_PARM_DESC(timer_set, 71 + "Default Watchdog timer setting" 72 + "Complete cycle time" 73 + "The range is from 1 to 170" 74 + "This is the time for all keep alives to arrive"); 75 + 76 + /* After watchdog device is closed, check force_boot. If: 77 + * force_boot == 0, then force boot on next watchdog interrupt after close, 78 + * force_boot == 1, then force boot immediately when device is closed. 79 + */ 80 + static int force_boot; 81 + module_param(force_boot, int, 0); 82 + MODULE_PARM_DESC(force_boot, 83 + "A value of 1 means that the driver will reboot" 84 + "the system immediately if the /dev/watchdog device is closed" 85 + "A value of 0 means that when /dev/watchdog device is closed" 86 + "the watchdog timer will be refreshed for one more interval" 87 + "of length: timer_set. At the end of this interval, the" 88 + "watchdog timer will reset the system." 89 + ); 90 + 91 + /* there is only one device in the system now; this can be made into 92 + * an array in the future if we have more than one device */ 93 + 94 + static struct intel_scu_watchdog_dev watchdog_device; 95 + 96 + /* Forces restart, if force_reboot is set */ 97 + static void watchdog_fire(void) 98 + { 99 + if (force_boot) { 100 + printk(KERN_CRIT PFX "Initiating system reboot.\n"); 101 + emergency_restart(); 102 + printk(KERN_CRIT PFX "Reboot didn't ?????\n"); 103 + } 104 + 105 + else { 106 + printk(KERN_CRIT PFX "Immediate Reboot Disabled\n"); 107 + printk(KERN_CRIT PFX 108 + "System will reset when watchdog timer times out!\n"); 109 + } 110 + } 111 + 112 + static int check_timer_margin(int new_margin) 113 + { 114 + if ((new_margin < MIN_TIME_CYCLE) || 115 + (new_margin > MAX_TIME - timer_set)) { 116 + pr_debug("Watchdog timer: value of new_margin %d is out of the range %d to %d\n", 117 + new_margin, MIN_TIME_CYCLE, MAX_TIME - timer_set); 118 + return -EINVAL; 119 + } 120 + return 0; 121 + } 122 + 123 + /* 124 + * IPC operations 125 + */ 126 + static int watchdog_set_ipc(int soft_threshold, int threshold) 127 + { 128 + u32 *ipc_wbuf; 129 + u8 cbuf[16] = { '\0' }; 130 + int ipc_ret = 0; 131 + 132 + ipc_wbuf = (u32 *)&cbuf; 133 + ipc_wbuf[0] = soft_threshold; 134 + ipc_wbuf[1] = threshold; 135 + 136 + ipc_ret = intel_scu_ipc_command( 137 + IPC_SET_WATCHDOG_TIMER, 138 + 0, 139 + ipc_wbuf, 140 + 2, 141 + NULL, 142 + 0); 143 + 144 + if (ipc_ret != 0) 145 + pr_err("Error setting SCU watchdog timer: %x\n", ipc_ret); 146 + 147 + return ipc_ret; 148 + }; 149 + 150 + /* 151 + * Intel_SCU operations 152 + */ 153 + 154 + /* timer interrupt handler */ 155 + static irqreturn_t watchdog_timer_interrupt(int irq, void *dev_id) 156 + { 157 + int int_status; 158 + int_status = ioread32(watchdog_device.timer_interrupt_status_addr); 159 + 160 + pr_debug("Watchdog timer: irq, int_status: %x\n", int_status); 161 + 162 + if (int_status != 0) 163 + return IRQ_NONE; 164 + 165 + /* has the timer been started? If not, then this is spurious */ 166 + if (watchdog_device.timer_started == 0) { 167 + pr_debug("Watchdog timer: spurious interrupt received\n"); 168 + return IRQ_HANDLED; 169 + } 170 + 171 + /* temporarily disable the timer */ 172 + iowrite32(0x00000002, watchdog_device.timer_control_addr); 173 + 174 + /* set the timer to the threshold */ 175 + iowrite32(watchdog_device.threshold, 176 + watchdog_device.timer_load_count_addr); 177 + 178 + /* allow the timer to run */ 179 + iowrite32(0x00000003, watchdog_device.timer_control_addr); 180 + 181 + return IRQ_HANDLED; 182 + } 183 + 184 + static int intel_scu_keepalive(void) 185 + { 186 + 187 + /* read eoi register - clears interrupt */ 188 + ioread32(watchdog_device.timer_clear_interrupt_addr); 189 + 190 + /* temporarily disable the timer */ 191 + iowrite32(0x00000002, watchdog_device.timer_control_addr); 192 + 193 + /* set the timer to the soft_threshold */ 194 + iowrite32(watchdog_device.soft_threshold, 195 + watchdog_device.timer_load_count_addr); 196 + 197 + /* allow the timer to run */ 198 + iowrite32(0x00000003, watchdog_device.timer_control_addr); 199 + 200 + return 0; 201 + } 202 + 203 + static int intel_scu_stop(void) 204 + { 205 + iowrite32(0, watchdog_device.timer_control_addr); 206 + return 0; 207 + } 208 + 209 + static int intel_scu_set_heartbeat(u32 t) 210 + { 211 + int ipc_ret; 212 + int retry_count; 213 + u32 soft_value; 214 + u32 hw_pre_value; 215 + u32 hw_value; 216 + 217 + watchdog_device.timer_set = t; 218 + watchdog_device.threshold = 219 + timer_margin * watchdog_device.timer_tbl_ptr->freq_hz; 220 + watchdog_device.soft_threshold = 221 + (watchdog_device.timer_set - timer_margin) 222 + * watchdog_device.timer_tbl_ptr->freq_hz; 223 + 224 + pr_debug("Watchdog timer: set_heartbeat: timer freq is %d\n", 225 + watchdog_device.timer_tbl_ptr->freq_hz); 226 + pr_debug("Watchdog timer: set_heartbeat: timer_set is %x (hex)\n", 227 + watchdog_device.timer_set); 228 + pr_debug("Watchdog timer: set_hearbeat: timer_margin is %x (hex)\n", 229 + timer_margin); 230 + pr_debug("Watchdog timer: set_heartbeat: threshold is %x (hex)\n", 231 + watchdog_device.threshold); 232 + pr_debug("Watchdog timer: set_heartbeat: soft_threshold is %x (hex)\n", 233 + watchdog_device.soft_threshold); 234 + 235 + /* Adjust thresholds by FREQ_ADJUSTMENT factor, to make the */ 236 + /* watchdog timing come out right. */ 237 + watchdog_device.threshold = 238 + watchdog_device.threshold / FREQ_ADJUSTMENT; 239 + watchdog_device.soft_threshold = 240 + watchdog_device.soft_threshold / FREQ_ADJUSTMENT; 241 + 242 + /* temporarily disable the timer */ 243 + iowrite32(0x00000002, watchdog_device.timer_control_addr); 244 + 245 + /* send the threshold and soft_threshold via IPC to the processor */ 246 + ipc_ret = watchdog_set_ipc(watchdog_device.soft_threshold, 247 + watchdog_device.threshold); 248 + 249 + if (ipc_ret != 0) { 250 + /* Make sure the watchdog timer is stopped */ 251 + intel_scu_stop(); 252 + return ipc_ret; 253 + } 254 + 255 + /* Soft Threshold set loop. Early versions of silicon did */ 256 + /* not always set this count correctly. This loop checks */ 257 + /* the value and retries if it was not set correctly. */ 258 + 259 + retry_count = 0; 260 + soft_value = watchdog_device.soft_threshold & 0xFFFF0000; 261 + do { 262 + 263 + /* Make sure timer is stopped */ 264 + intel_scu_stop(); 265 + 266 + if (MAX_RETRY < retry_count++) { 267 + /* Unable to set timer value */ 268 + pr_err("Watchdog timer: Unable to set timer\n"); 269 + return -ENODEV; 270 + } 271 + 272 + /* set the timer to the soft threshold */ 273 + iowrite32(watchdog_device.soft_threshold, 274 + watchdog_device.timer_load_count_addr); 275 + 276 + /* read count value before starting timer */ 277 + hw_pre_value = ioread32(watchdog_device.timer_load_count_addr); 278 + hw_pre_value = hw_pre_value & 0xFFFF0000; 279 + 280 + /* Start the timer */ 281 + iowrite32(0x00000003, watchdog_device.timer_control_addr); 282 + 283 + /* read the value the time loaded into its count reg */ 284 + hw_value = ioread32(watchdog_device.timer_load_count_addr); 285 + hw_value = hw_value & 0xFFFF0000; 286 + 287 + 288 + } while (soft_value != hw_value); 289 + 290 + watchdog_device.timer_started = 1; 291 + 292 + return 0; 293 + } 294 + 295 + /* 296 + * /dev/watchdog handling 297 + */ 298 + 299 + static int intel_scu_open(struct inode *inode, struct file *file) 300 + { 301 + 302 + /* Set flag to indicate that watchdog device is open */ 303 + if (test_and_set_bit(0, &watchdog_device.driver_open)) 304 + return -EBUSY; 305 + 306 + /* Check for reopen of driver. Reopens are not allowed */ 307 + if (watchdog_device.driver_closed) 308 + return -EPERM; 309 + 310 + return nonseekable_open(inode, file); 311 + } 312 + 313 + static int intel_scu_release(struct inode *inode, struct file *file) 314 + { 315 + /* 316 + * This watchdog should not be closed, after the timer 317 + * is started with the WDIPC_SETTIMEOUT ioctl 318 + * If force_boot is set watchdog_fire() will cause an 319 + * immediate reset. If force_boot is not set, the watchdog 320 + * timer is refreshed for one more interval. At the end 321 + * of that interval, the watchdog timer will reset the system. 322 + */ 323 + 324 + if (!test_and_clear_bit(0, &watchdog_device.driver_open)) { 325 + pr_debug("Watchdog timer: intel_scu_release, without open\n"); 326 + return -ENOTTY; 327 + } 328 + 329 + if (!watchdog_device.timer_started) { 330 + /* Just close, since timer has not been started */ 331 + pr_debug("Watchdog timer: closed, without starting timer\n"); 332 + return 0; 333 + } 334 + 335 + printk(KERN_CRIT PFX 336 + "Unexpected close of /dev/watchdog!\n"); 337 + 338 + /* Since the timer was started, prevent future reopens */ 339 + watchdog_device.driver_closed = 1; 340 + 341 + /* Refresh the timer for one more interval */ 342 + intel_scu_keepalive(); 343 + 344 + /* Reboot system (if force_boot is set) */ 345 + watchdog_fire(); 346 + 347 + /* We should only reach this point if force_boot is not set */ 348 + return 0; 349 + } 350 + 351 + static ssize_t intel_scu_write(struct file *file, 352 + char const *data, 353 + size_t len, 354 + loff_t *ppos) 355 + { 356 + 357 + if (watchdog_device.timer_started) 358 + /* Watchdog already started, keep it alive */ 359 + intel_scu_keepalive(); 360 + else 361 + /* Start watchdog with timer value set by init */ 362 + intel_scu_set_heartbeat(watchdog_device.timer_set); 363 + 364 + return len; 365 + } 366 + 367 + static long intel_scu_ioctl(struct file *file, 368 + unsigned int cmd, 369 + unsigned long arg) 370 + { 371 + void __user *argp = (void __user *)arg; 372 + u32 __user *p = argp; 373 + u32 new_margin; 374 + 375 + 376 + static const struct watchdog_info ident = { 377 + .options = WDIOF_SETTIMEOUT 378 + | WDIOF_KEEPALIVEPING, 379 + .firmware_version = 0, /* @todo Get from SCU via 380 + ipc_get_scu_fw_version()? */ 381 + .identity = "Intel_SCU IOH Watchdog" /* len < 32 */ 382 + }; 383 + 384 + switch (cmd) { 385 + case WDIOC_GETSUPPORT: 386 + return copy_to_user(argp, 387 + &ident, 388 + sizeof(ident)) ? -EFAULT : 0; 389 + case WDIOC_GETSTATUS: 390 + case WDIOC_GETBOOTSTATUS: 391 + return put_user(0, p); 392 + case WDIOC_KEEPALIVE: 393 + intel_scu_keepalive(); 394 + 395 + return 0; 396 + case WDIOC_SETTIMEOUT: 397 + if (get_user(new_margin, p)) 398 + return -EFAULT; 399 + 400 + if (check_timer_margin(new_margin)) 401 + return -EINVAL; 402 + 403 + if (intel_scu_set_heartbeat(new_margin)) 404 + return -EINVAL; 405 + return 0; 406 + case WDIOC_GETTIMEOUT: 407 + return put_user(watchdog_device.soft_threshold, p); 408 + 409 + default: 410 + return -ENOTTY; 411 + } 412 + } 413 + 414 + /* 415 + * Notifier for system down 416 + */ 417 + static int intel_scu_notify_sys(struct notifier_block *this, 418 + unsigned long code, 419 + void *another_unused) 420 + { 421 + if (code == SYS_DOWN || code == SYS_HALT) 422 + /* Turn off the watchdog timer. */ 423 + intel_scu_stop(); 424 + return NOTIFY_DONE; 425 + } 426 + 427 + /* 428 + * Kernel Interfaces 429 + */ 430 + static const struct file_operations intel_scu_fops = { 431 + .owner = THIS_MODULE, 432 + .llseek = no_llseek, 433 + .write = intel_scu_write, 434 + .unlocked_ioctl = intel_scu_ioctl, 435 + .open = intel_scu_open, 436 + .release = intel_scu_release, 437 + }; 438 + 439 + static int __init intel_scu_watchdog_init(void) 440 + { 441 + int ret; 442 + u32 __iomem *tmp_addr; 443 + 444 + /* 445 + * We don't really need to check this as the SFI timer get will fail 446 + * but if we do so we can exit with a clearer reason and no noise. 447 + * 448 + * If it isn't an intel MID device then it doesn't have this watchdog 449 + */ 450 + if (!mrst_identify_cpu()) 451 + return -ENODEV; 452 + 453 + /* Check boot parameters to verify that their initial values */ 454 + /* are in range. */ 455 + /* Check value of timer_set boot parameter */ 456 + if ((timer_set < MIN_TIME_CYCLE) || 457 + (timer_set > MAX_TIME - MIN_TIME_CYCLE)) { 458 + pr_err("Watchdog timer: value of timer_set %x (hex) " 459 + "is out of range from %x to %x (hex)\n", 460 + timer_set, MIN_TIME_CYCLE, MAX_TIME - MIN_TIME_CYCLE); 461 + return -EINVAL; 462 + } 463 + 464 + /* Check value of timer_margin boot parameter */ 465 + if (check_timer_margin(timer_margin)) 466 + return -EINVAL; 467 + 468 + watchdog_device.timer_tbl_ptr = sfi_get_mtmr(sfi_mtimer_num-1); 469 + 470 + if (watchdog_device.timer_tbl_ptr == NULL) { 471 + pr_debug("Watchdog timer - Intel SCU watchdog: timer is not available\n"); 472 + return -ENODEV; 473 + } 474 + /* make sure the timer exists */ 475 + if (watchdog_device.timer_tbl_ptr->phys_addr == 0) { 476 + pr_debug("Watchdog timer - Intel SCU watchdog - timer %d does not have valid physical memory\n", 477 + sfi_mtimer_num); 478 + return -ENODEV; 479 + } 480 + 481 + if (watchdog_device.timer_tbl_ptr->irq == 0) { 482 + pr_debug("Watchdog timer: timer %d invalid irq\n", 483 + sfi_mtimer_num); 484 + return -ENODEV; 485 + } 486 + 487 + tmp_addr = ioremap_nocache(watchdog_device.timer_tbl_ptr->phys_addr, 488 + 20); 489 + 490 + if (tmp_addr == NULL) { 491 + pr_debug("Watchdog timer: timer unable to ioremap\n"); 492 + return -ENOMEM; 493 + } 494 + 495 + watchdog_device.timer_load_count_addr = tmp_addr++; 496 + watchdog_device.timer_current_value_addr = tmp_addr++; 497 + watchdog_device.timer_control_addr = tmp_addr++; 498 + watchdog_device.timer_clear_interrupt_addr = tmp_addr++; 499 + watchdog_device.timer_interrupt_status_addr = tmp_addr++; 500 + 501 + /* Set the default time values in device structure */ 502 + 503 + watchdog_device.timer_set = timer_set; 504 + watchdog_device.threshold = 505 + timer_margin * watchdog_device.timer_tbl_ptr->freq_hz; 506 + watchdog_device.soft_threshold = 507 + (watchdog_device.timer_set - timer_margin) 508 + * watchdog_device.timer_tbl_ptr->freq_hz; 509 + 510 + 511 + watchdog_device.intel_scu_notifier.notifier_call = 512 + intel_scu_notify_sys; 513 + 514 + ret = register_reboot_notifier(&watchdog_device.intel_scu_notifier); 515 + if (ret) { 516 + pr_err("Watchdog timer: cannot register notifier %d)\n", ret); 517 + goto register_reboot_error; 518 + } 519 + 520 + watchdog_device.miscdev.minor = WATCHDOG_MINOR; 521 + watchdog_device.miscdev.name = "watchdog"; 522 + watchdog_device.miscdev.fops = &intel_scu_fops; 523 + 524 + ret = misc_register(&watchdog_device.miscdev); 525 + if (ret) { 526 + pr_err("Watchdog timer: cannot register miscdev %d err =%d\n", 527 + WATCHDOG_MINOR, ret); 528 + goto misc_register_error; 529 + } 530 + 531 + ret = request_irq((unsigned int)watchdog_device.timer_tbl_ptr->irq, 532 + watchdog_timer_interrupt, 533 + IRQF_SHARED, "watchdog", 534 + &watchdog_device.timer_load_count_addr); 535 + if (ret) { 536 + pr_err("Watchdog timer: error requesting irq %d\n", ret); 537 + goto request_irq_error; 538 + } 539 + /* Make sure timer is disabled before returning */ 540 + intel_scu_stop(); 541 + return 0; 542 + 543 + /* error cleanup */ 544 + 545 + request_irq_error: 546 + misc_deregister(&watchdog_device.miscdev); 547 + misc_register_error: 548 + unregister_reboot_notifier(&watchdog_device.intel_scu_notifier); 549 + register_reboot_error: 550 + intel_scu_stop(); 551 + iounmap(watchdog_device.timer_load_count_addr); 552 + return ret; 553 + } 554 + 555 + static void __exit intel_scu_watchdog_exit(void) 556 + { 557 + 558 + misc_deregister(&watchdog_device.miscdev); 559 + unregister_reboot_notifier(&watchdog_device.intel_scu_notifier); 560 + /* disable the timer */ 561 + iowrite32(0x00000002, watchdog_device.timer_control_addr); 562 + iounmap(watchdog_device.timer_load_count_addr); 563 + } 564 + 565 + late_initcall(intel_scu_watchdog_init); 566 + module_exit(intel_scu_watchdog_exit); 567 + 568 + MODULE_AUTHOR("Intel Corporation"); 569 + MODULE_DESCRIPTION("Intel SCU Watchdog Device Driver"); 570 + MODULE_LICENSE("GPL"); 571 + MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); 572 + MODULE_VERSION(WDT_VER);
+66
drivers/watchdog/intel_scu_watchdog.h
··· 1 + /* 2 + * Intel_SCU 0.2: An Intel SCU IOH Based Watchdog Device 3 + * for Intel part #(s): 4 + * - AF82MP20 PCH 5 + * 6 + * Copyright (C) 2009-2010 Intel Corporation. All rights reserved. 7 + * 8 + * This program is free software; you can redistribute it and/or 9 + * modify it under the terms of version 2 of the GNU General 10 + * Public License as published by the Free Software Foundation. 11 + * 12 + * This program is distributed in the hope that it will be 13 + * useful, but WITHOUT ANY WARRANTY; without even the implied 14 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 15 + * PURPOSE. See the GNU General Public License for more details. 16 + * You should have received a copy of the GNU General Public 17 + * License along with this program; if not, write to the Free 18 + * Software Foundation, Inc., 59 Temple Place - Suite 330, 19 + * Boston, MA 02111-1307, USA. 20 + * The full GNU General Public License is included in this 21 + * distribution in the file called COPYING. 22 + * 23 + */ 24 + 25 + #ifndef __INTEL_SCU_WATCHDOG_H 26 + #define __INTEL_SCU_WATCHDOG_H 27 + 28 + #define PFX "Intel_SCU: " 29 + #define WDT_VER "0.3" 30 + 31 + /* minimum time between interrupts */ 32 + #define MIN_TIME_CYCLE 1 33 + 34 + /* Time from warning to reboot is 2 seconds */ 35 + #define DEFAULT_SOFT_TO_HARD_MARGIN 2 36 + 37 + #define MAX_TIME 170 38 + 39 + #define DEFAULT_TIME 5 40 + 41 + #define MAX_SOFT_TO_HARD_MARGIN (MAX_TIME-MIN_TIME_CYCLE) 42 + 43 + /* Ajustment to clock tick frequency to make timing come out right */ 44 + #define FREQ_ADJUSTMENT 8 45 + 46 + struct intel_scu_watchdog_dev { 47 + ulong driver_open; 48 + ulong driver_closed; 49 + u32 timer_started; 50 + u32 timer_set; 51 + u32 threshold; 52 + u32 soft_threshold; 53 + u32 __iomem *timer_load_count_addr; 54 + u32 __iomem *timer_current_value_addr; 55 + u32 __iomem *timer_control_addr; 56 + u32 __iomem *timer_clear_interrupt_addr; 57 + u32 __iomem *timer_interrupt_status_addr; 58 + struct sfi_timer_table_entry *timer_tbl_ptr; 59 + struct notifier_block intel_scu_notifier; 60 + struct miscdevice miscdev; 61 + }; 62 + 63 + extern int sfi_mtimer_num; 64 + 65 + /* extern struct sfi_timer_table_entry *sfi_get_mtmr(int hint); */ 66 + #endif /* __INTEL_SCU_WATCHDOG_H */