aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/watchdog/i6300esb.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2009-04-13 17:41:05 -0400
committerDavid S. Miller <davem@davemloft.net>2009-04-13 17:41:05 -0400
commit83400207a07584539366f6859362db6872809a12 (patch)
treefad187f8b3bebf1b387ec42ef8143e6f4e49a256 /drivers/watchdog/i6300esb.c
parent0d489ffb76de0fe804cf06a9d4d11fa7342d74b9 (diff)
parent80a04d3f2f94fb68b5df05e3ac6697130bc3467a (diff)
Merge branch 'master' of /home/davem/src/GIT/linux-2.6/
Conflicts: MAINTAINERS
Diffstat (limited to 'drivers/watchdog/i6300esb.c')
-rw-r--r--drivers/watchdog/i6300esb.c155
1 files changed, 77 insertions, 78 deletions
diff --git a/drivers/watchdog/i6300esb.c b/drivers/watchdog/i6300esb.c
index 2dbe83570d65..7ba0b11ec525 100644
--- a/drivers/watchdog/i6300esb.c
+++ b/drivers/watchdog/i6300esb.c
@@ -52,10 +52,10 @@
52#define ESB_LOCK_REG 0x68 /* WDT lock register */ 52#define ESB_LOCK_REG 0x68 /* WDT lock register */
53 53
54/* Memory mapped registers */ 54/* Memory mapped registers */
55#define ESB_TIMER1_REG BASEADDR + 0x00 /* Timer1 value after each reset */ 55#define ESB_TIMER1_REG (BASEADDR + 0x00)/* Timer1 value after each reset */
56#define ESB_TIMER2_REG BASEADDR + 0x04 /* Timer2 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 */ 57#define ESB_GINTSR_REG (BASEADDR + 0x08)/* General Interrupt Status Register */
58#define ESB_RELOAD_REG BASEADDR + 0x0c /* Reload register */ 58#define ESB_RELOAD_REG (BASEADDR + 0x0c)/* Reload register */
59 59
60/* Lock register bits */ 60/* Lock register bits */
61#define ESB_WDT_FUNC (0x01 << 2) /* Watchdog functionality */ 61#define ESB_WDT_FUNC (0x01 << 2) /* Watchdog functionality */
@@ -68,6 +68,7 @@
68#define ESB_WDT_INTTYPE (0x11 << 0) /* Interrupt type on timer1 timeout */ 68#define ESB_WDT_INTTYPE (0x11 << 0) /* Interrupt type on timer1 timeout */
69 69
70/* Reload register bits */ 70/* Reload register bits */
71#define ESB_WDT_TIMEOUT (0x01 << 9) /* Watchdog timed out */
71#define ESB_WDT_RELOAD (0x01 << 8) /* prevent timeout */ 72#define ESB_WDT_RELOAD (0x01 << 8) /* prevent timeout */
72 73
73/* Magic constants */ 74/* Magic constants */
@@ -87,7 +88,6 @@ static struct platform_device *esb_platform_device;
87/* 30 sec default heartbeat (1 < heartbeat < 2*1023) */ 88/* 30 sec default heartbeat (1 < heartbeat < 2*1023) */
88#define WATCHDOG_HEARTBEAT 30 89#define WATCHDOG_HEARTBEAT 30
89static int heartbeat = WATCHDOG_HEARTBEAT; /* in seconds */ 90static int heartbeat = WATCHDOG_HEARTBEAT; /* in seconds */
90
91module_param(heartbeat, int, 0); 91module_param(heartbeat, int, 0);
92MODULE_PARM_DESC(heartbeat, 92MODULE_PARM_DESC(heartbeat,
93 "Watchdog heartbeat in seconds. (1<heartbeat<2046, default=" 93 "Watchdog heartbeat in seconds. (1<heartbeat<2046, default="
@@ -123,7 +123,7 @@ static int esb_timer_start(void)
123 esb_unlock_registers(); 123 esb_unlock_registers();
124 writew(ESB_WDT_RELOAD, ESB_RELOAD_REG); 124 writew(ESB_WDT_RELOAD, ESB_RELOAD_REG);
125 /* Enable or Enable + Lock? */ 125 /* Enable or Enable + Lock? */
126 val = 0x02 | (nowayout ? 0x01 : 0x00); 126 val = ESB_WDT_ENABLE | (nowayout ? ESB_WDT_LOCK : 0x00);
127 pci_write_config_byte(esb_pci, ESB_LOCK_REG, val); 127 pci_write_config_byte(esb_pci, ESB_LOCK_REG, val);
128 spin_unlock(&esb_lock); 128 spin_unlock(&esb_lock);
129 return 0; 129 return 0;
@@ -143,7 +143,7 @@ static int esb_timer_stop(void)
143 spin_unlock(&esb_lock); 143 spin_unlock(&esb_lock);
144 144
145 /* Returns 0 if the timer was disabled, non-zero otherwise */ 145 /* Returns 0 if the timer was disabled, non-zero otherwise */
146 return (val & 0x01); 146 return val & ESB_WDT_ENABLE;
147} 147}
148 148
149static void esb_timer_keepalive(void) 149static void esb_timer_keepalive(void)
@@ -190,18 +190,6 @@ static int esb_timer_set_heartbeat(int time)
190 return 0; 190 return 0;
191} 191}
192 192
193static int esb_timer_read(void)
194{
195 u32 count;
196
197 /* This isn't documented, and doesn't take into
198 * acount which stage is running, but it looks
199 * like a 20 bit count down, so we might as well report it.
200 */
201 pci_read_config_dword(esb_pci, 0x64, &count);
202 return (int)count;
203}
204
205/* 193/*
206 * /dev/watchdog handling 194 * /dev/watchdog handling
207 */ 195 */
@@ -282,7 +270,7 @@ static long esb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
282 sizeof(ident)) ? -EFAULT : 0; 270 sizeof(ident)) ? -EFAULT : 0;
283 271
284 case WDIOC_GETSTATUS: 272 case WDIOC_GETSTATUS:
285 return put_user(esb_timer_read(), p); 273 return put_user(0, p);
286 274
287 case WDIOC_GETBOOTSTATUS: 275 case WDIOC_GETBOOTSTATUS:
288 return put_user(triggered, p); 276 return put_user(triggered, p);
@@ -362,8 +350,6 @@ MODULE_DEVICE_TABLE(pci, esb_pci_tbl);
362 350
363static unsigned char __devinit esb_getdevice(void) 351static unsigned char __devinit esb_getdevice(void)
364{ 352{
365 u8 val1;
366 unsigned short val2;
367 /* 353 /*
368 * Find the PCI device 354 * Find the PCI device
369 */ 355 */
@@ -371,66 +357,79 @@ static unsigned char __devinit esb_getdevice(void)
371 esb_pci = pci_get_device(PCI_VENDOR_ID_INTEL, 357 esb_pci = pci_get_device(PCI_VENDOR_ID_INTEL,
372 PCI_DEVICE_ID_INTEL_ESB_9, NULL); 358 PCI_DEVICE_ID_INTEL_ESB_9, NULL);
373 359
374 if (esb_pci) { 360 if (!esb_pci)
375 if (pci_enable_device(esb_pci)) { 361 return 0;
376 printk(KERN_ERR PFX "failed to enable device\n");
377 goto err_devput;
378 }
379 362
380 if (pci_request_region(esb_pci, 0, ESB_MODULE_NAME)) { 363 if (pci_enable_device(esb_pci)) {
381 printk(KERN_ERR PFX "failed to request region\n"); 364 printk(KERN_ERR PFX "failed to enable device\n");
382 goto err_disable; 365 goto err_devput;
383 } 366 }
384 367
385 BASEADDR = pci_ioremap_bar(esb_pci, 0); 368 if (pci_request_region(esb_pci, 0, ESB_MODULE_NAME)) {
386 if (BASEADDR == NULL) { 369 printk(KERN_ERR PFX "failed to request region\n");
387 /* Something's wrong here, BASEADDR has to be set */ 370 goto err_disable;
388 printk(KERN_ERR PFX "failed to get BASEADDR\n"); 371 }
389 goto err_release;
390 }
391 372
392 /* 373 BASEADDR = pci_ioremap_bar(esb_pci, 0);
393 * The watchdog has two timers, it can be setup so that the 374 if (BASEADDR == NULL) {
394 * expiry of timer1 results in an interrupt and the expiry of 375 /* Something's wrong here, BASEADDR has to be set */
395 * timer2 results in a reboot. We set it to not generate 376 printk(KERN_ERR PFX "failed to get BASEADDR\n");
396 * any interrupts as there is not much we can do with it 377 goto err_release;
397 * right now. 378 }
398 * 379
399 * We also enable reboots and set the timer frequency to 380 /* Done */
400 * the PCI clock divided by 2^15 (approx 1KHz). 381 return 1;
401 */
402 pci_write_config_word(esb_pci, ESB_CONFIG_REG, 0x0003);
403
404 /* Check that the WDT isn't already locked */
405 pci_read_config_byte(esb_pci, ESB_LOCK_REG, &val1);
406 if (val1 & ESB_WDT_LOCK)
407 printk(KERN_WARNING PFX "nowayout already set\n");
408
409 /* Set the timer to watchdog mode and disable it for now */
410 pci_write_config_byte(esb_pci, ESB_LOCK_REG, 0x00);
411
412 /* Check if the watchdog was previously triggered */
413 esb_unlock_registers();
414 val2 = readw(ESB_RELOAD_REG);
415 triggered = (val2 & (0x01 << 9) >> 9);
416
417 /* Reset trigger flag and timers */
418 esb_unlock_registers();
419 writew((0x11 << 8), ESB_RELOAD_REG);
420
421 /* Done */
422 return 1;
423 382
424err_release: 383err_release:
425 pci_release_region(esb_pci, 0); 384 pci_release_region(esb_pci, 0);
426err_disable: 385err_disable:
427 pci_disable_device(esb_pci); 386 pci_disable_device(esb_pci);
428err_devput: 387err_devput:
429 pci_dev_put(esb_pci); 388 pci_dev_put(esb_pci);
430 }
431 return 0; 389 return 0;
432} 390}
433 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
434static int __devinit esb_probe(struct platform_device *dev) 433static int __devinit esb_probe(struct platform_device *dev)
435{ 434{
436 int ret; 435 int ret;
@@ -441,13 +440,17 @@ static int __devinit esb_probe(struct platform_device *dev)
441 440
442 /* Check that the heartbeat value is within it's range; 441 /* Check that the heartbeat value is within it's range;
443 if not reset to the default */ 442 if not reset to the default */
444 if (esb_timer_set_heartbeat(heartbeat)) { 443 if (heartbeat < 0x1 || heartbeat > 2 * 0x03ff) {
445 esb_timer_set_heartbeat(WATCHDOG_HEARTBEAT); 444 heartbeat = WATCHDOG_HEARTBEAT;
446 printk(KERN_INFO PFX 445 printk(KERN_INFO PFX
447 "heartbeat value must be 1<heartbeat<2046, using %d\n", 446 "heartbeat value must be 1<heartbeat<2046, using %d\n",
448 heartbeat); 447 heartbeat);
449 } 448 }
450 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 */
451 ret = misc_register(&esb_miscdev); 454 ret = misc_register(&esb_miscdev);
452 if (ret != 0) { 455 if (ret != 0) {
453 printk(KERN_ERR PFX 456 printk(KERN_ERR PFX
@@ -455,7 +458,6 @@ static int __devinit esb_probe(struct platform_device *dev)
455 WATCHDOG_MINOR, ret); 458 WATCHDOG_MINOR, ret);
456 goto err_unmap; 459 goto err_unmap;
457 } 460 }
458 esb_timer_stop();
459 printk(KERN_INFO PFX 461 printk(KERN_INFO PFX
460 "initialized (0x%p). heartbeat=%d sec (nowayout=%d)\n", 462 "initialized (0x%p). heartbeat=%d sec (nowayout=%d)\n",
461 BASEADDR, heartbeat, nowayout); 463 BASEADDR, heartbeat, nowayout);
@@ -463,11 +465,8 @@ static int __devinit esb_probe(struct platform_device *dev)
463 465
464err_unmap: 466err_unmap:
465 iounmap(BASEADDR); 467 iounmap(BASEADDR);
466/* err_release: */
467 pci_release_region(esb_pci, 0); 468 pci_release_region(esb_pci, 0);
468/* err_disable: */
469 pci_disable_device(esb_pci); 469 pci_disable_device(esb_pci);
470/* err_devput: */
471 pci_dev_put(esb_pci); 470 pci_dev_put(esb_pci);
472 return ret; 471 return ret;
473} 472}