aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/watchdog
diff options
context:
space:
mode:
authorWim Van Sebroeck <wim@iguana.be>2009-03-25 15:16:28 -0400
committerWim Van Sebroeck <wim@iguana.be>2009-04-08 02:06:50 -0400
commitfc8a9d830fdbc72545187a42f8d71b9fa95764dd (patch)
tree0f820c9af9461d743fade19ed0709ef46f6de397 /drivers/watchdog
parent31838d9dac17dce6d68d985fd28c10d7a756dc4d (diff)
[WATCHDOG] i6300esb.c: Restructure initialization of the device
The i6300ESB watchdog should be stopped before userspace has access to the watchdog. So fix this and restructure the initialization sequence into: * See if we have a i6300 device * make sure that we have valid module parameters * Initialize the device * register the /dev/watchdog device so that userspace has access Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
Diffstat (limited to 'drivers/watchdog')
-rw-r--r--drivers/watchdog/i6300esb.c132
1 files changed, 71 insertions, 61 deletions
diff --git a/drivers/watchdog/i6300esb.c b/drivers/watchdog/i6300esb.c
index 8a0ef65a0691..7ba0b11ec525 100644
--- a/drivers/watchdog/i6300esb.c
+++ b/drivers/watchdog/i6300esb.c
@@ -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)
@@ -350,8 +350,6 @@ MODULE_DEVICE_TABLE(pci, esb_pci_tbl);
350 350
351static unsigned char __devinit esb_getdevice(void) 351static unsigned char __devinit esb_getdevice(void)
352{ 352{
353 u8 val1;
354 unsigned short val2;
355 /* 353 /*
356 * Find the PCI device 354 * Find the PCI device
357 */ 355 */
@@ -359,67 +357,79 @@ static unsigned char __devinit esb_getdevice(void)
359 esb_pci = pci_get_device(PCI_VENDOR_ID_INTEL, 357 esb_pci = pci_get_device(PCI_VENDOR_ID_INTEL,
360 PCI_DEVICE_ID_INTEL_ESB_9, NULL); 358 PCI_DEVICE_ID_INTEL_ESB_9, NULL);
361 359
362 if (esb_pci) { 360 if (!esb_pci)
363 if (pci_enable_device(esb_pci)) { 361 return 0;
364 printk(KERN_ERR PFX "failed to enable device\n");
365 goto err_devput;
366 }
367 362
368 if (pci_request_region(esb_pci, 0, ESB_MODULE_NAME)) { 363 if (pci_enable_device(esb_pci)) {
369 printk(KERN_ERR PFX "failed to request region\n"); 364 printk(KERN_ERR PFX "failed to enable device\n");
370 goto err_disable; 365 goto err_devput;
371 } 366 }
372 367
373 BASEADDR = pci_ioremap_bar(esb_pci, 0); 368 if (pci_request_region(esb_pci, 0, ESB_MODULE_NAME)) {
374 if (BASEADDR == NULL) { 369 printk(KERN_ERR PFX "failed to request region\n");
375 /* Something's wrong here, BASEADDR has to be set */ 370 goto err_disable;
376 printk(KERN_ERR PFX "failed to get BASEADDR\n"); 371 }
377 goto err_release;
378 }
379 372
380 /* 373 BASEADDR = pci_ioremap_bar(esb_pci, 0);
381 * The watchdog has two timers, it can be setup so that the 374 if (BASEADDR == NULL) {
382 * expiry of timer1 results in an interrupt and the expiry of 375 /* Something's wrong here, BASEADDR has to be set */
383 * timer2 results in a reboot. We set it to not generate 376 printk(KERN_ERR PFX "failed to get BASEADDR\n");
384 * any interrupts as there is not much we can do with it 377 goto err_release;
385 * right now. 378 }
386 * 379
387 * We also enable reboots and set the timer frequency to 380 /* Done */
388 * the PCI clock divided by 2^15 (approx 1KHz). 381 return 1;
389 */
390 pci_write_config_word(esb_pci, ESB_CONFIG_REG, 0x0003);
391
392 /* Check that the WDT isn't already locked */
393 pci_read_config_byte(esb_pci, ESB_LOCK_REG, &val1);
394 if (val1 & ESB_WDT_LOCK)
395 printk(KERN_WARNING PFX "nowayout already set\n");
396
397 /* Set the timer to watchdog mode and disable it for now */
398 pci_write_config_byte(esb_pci, ESB_LOCK_REG, 0x00);
399
400 /* Check if the watchdog was previously triggered */
401 esb_unlock_registers();
402 val2 = readw(ESB_RELOAD_REG);
403 if (val2 & ESB_WDT_TIMEOUT)
404 triggered = WDIOF_CARDRESET;
405
406 /* Reset trigger flag and timers */
407 esb_unlock_registers();
408 writew((ESB_WDT_TIMEOUT | ESB_WDT_RELOAD), ESB_RELOAD_REG);
409
410 /* Done */
411 return 1;
412 382
413err_release: 383err_release:
414 pci_release_region(esb_pci, 0); 384 pci_release_region(esb_pci, 0);
415err_disable: 385err_disable:
416 pci_disable_device(esb_pci); 386 pci_disable_device(esb_pci);
417err_devput: 387err_devput:
418 pci_dev_put(esb_pci); 388 pci_dev_put(esb_pci);
419 }
420 return 0; 389 return 0;
421} 390}
422 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
423static int __devinit esb_probe(struct platform_device *dev) 433static int __devinit esb_probe(struct platform_device *dev)
424{ 434{
425 int ret; 435 int ret;
@@ -430,13 +440,17 @@ static int __devinit esb_probe(struct platform_device *dev)
430 440
431 /* Check that the heartbeat value is within it's range; 441 /* Check that the heartbeat value is within it's range;
432 if not reset to the default */ 442 if not reset to the default */
433 if (esb_timer_set_heartbeat(heartbeat)) { 443 if (heartbeat < 0x1 || heartbeat > 2 * 0x03ff) {
434 esb_timer_set_heartbeat(WATCHDOG_HEARTBEAT); 444 heartbeat = WATCHDOG_HEARTBEAT;
435 printk(KERN_INFO PFX 445 printk(KERN_INFO PFX
436 "heartbeat value must be 1<heartbeat<2046, using %d\n", 446 "heartbeat value must be 1<heartbeat<2046, using %d\n",
437 heartbeat); 447 heartbeat);
438 } 448 }
439 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 */
440 ret = misc_register(&esb_miscdev); 454 ret = misc_register(&esb_miscdev);
441 if (ret != 0) { 455 if (ret != 0) {
442 printk(KERN_ERR PFX 456 printk(KERN_ERR PFX
@@ -444,7 +458,6 @@ static int __devinit esb_probe(struct platform_device *dev)
444 WATCHDOG_MINOR, ret); 458 WATCHDOG_MINOR, ret);
445 goto err_unmap; 459 goto err_unmap;
446 } 460 }
447 esb_timer_stop();
448 printk(KERN_INFO PFX 461 printk(KERN_INFO PFX
449 "initialized (0x%p). heartbeat=%d sec (nowayout=%d)\n", 462 "initialized (0x%p). heartbeat=%d sec (nowayout=%d)\n",
450 BASEADDR, heartbeat, nowayout); 463 BASEADDR, heartbeat, nowayout);
@@ -452,11 +465,8 @@ static int __devinit esb_probe(struct platform_device *dev)
452 465
453err_unmap: 466err_unmap:
454 iounmap(BASEADDR); 467 iounmap(BASEADDR);
455/* err_release: */
456 pci_release_region(esb_pci, 0); 468 pci_release_region(esb_pci, 0);
457/* err_disable: */
458 pci_disable_device(esb_pci); 469 pci_disable_device(esb_pci);
459/* err_devput: */
460 pci_dev_put(esb_pci); 470 pci_dev_put(esb_pci);
461 return ret; 471 return ret;
462} 472}