Commit a9deecba authored by Linus Torvalds's avatar Linus Torvalds

Merge master.kernel.org:/pub/scm/linux/kernel/git/wim/linux-2.6-watchdog

* master.kernel.org:/pub/scm/linux/kernel/git/wim/linux-2.6-watchdog:
  [WATCHDOG] MTX-1 Watchdog driver
  [WATCHDOG] s3c2410_wdt - initialize watchdog irq resource  
  [WATCHDOG] Kconfig menuconfig patch
  [WATCHDOG] pcwd.c: Port to the new device driver model
  [WATCHDOG] use mutex instead of semaphore in Berkshire USB-PC Watchdog driver
  [WATCHDOG] the scheduled removal of the i8xx_tco watchdog driver
  [WATCHDOG] Semi-typical watchdog bug re early misc_register()
  [WATCHDOG] add support for the w83627thf chipset.
parents d9de2622 04bf3b4f
...@@ -278,14 +278,6 @@ Who: Richard Purdie <rpurdie@rpsys.net> ...@@ -278,14 +278,6 @@ Who: Richard Purdie <rpurdie@rpsys.net>
--------------------------- ---------------------------
What: i8xx_tco watchdog driver
When: in 2.6.22
Why: the i8xx_tco watchdog driver has been replaced by the iTCO_wdt
watchdog driver.
Who: Wim Van Sebroeck <wim@iguana.be>
---------------------------
What: Multipath cached routing support in ipv4 What: Multipath cached routing support in ipv4
When: in 2.6.23 When: in 2.6.23
Why: Code was merged, then submitter immediately disappeared leaving Why: Code was merged, then submitter immediately disappeared leaving
......
...@@ -1718,12 +1718,6 @@ P: H. Peter Anvin ...@@ -1718,12 +1718,6 @@ P: H. Peter Anvin
M: hpa@zytor.com M: hpa@zytor.com
S: Maintained S: Maintained
i810 TCO TIMER WATCHDOG
P: Nils Faerber
M: nils@kernelconcepts.de
W: http://www.kernelconcepts.de/
S: Maintained
IA64 (Itanium) PLATFORM IA64 (Itanium) PLATFORM
P: Tony Luck P: Tony Luck
M: tony.luck@intel.com M: tony.luck@intel.com
......
This diff is collapsed.
...@@ -46,7 +46,6 @@ obj-$(CONFIG_IB700_WDT) += ib700wdt.o ...@@ -46,7 +46,6 @@ obj-$(CONFIG_IB700_WDT) += ib700wdt.o
obj-$(CONFIG_IBMASR) += ibmasr.o obj-$(CONFIG_IBMASR) += ibmasr.o
obj-$(CONFIG_WAFER_WDT) += wafer5823wdt.o obj-$(CONFIG_WAFER_WDT) += wafer5823wdt.o
obj-$(CONFIG_I6300ESB_WDT) += i6300esb.o obj-$(CONFIG_I6300ESB_WDT) += i6300esb.o
obj-$(CONFIG_I8XX_TCO) += i8xx_tco.o
obj-$(CONFIG_ITCO_WDT) += iTCO_wdt.o iTCO_vendor_support.o obj-$(CONFIG_ITCO_WDT) += iTCO_wdt.o iTCO_vendor_support.o
obj-$(CONFIG_SC1200_WDT) += sc1200wdt.o obj-$(CONFIG_SC1200_WDT) += sc1200wdt.o
obj-$(CONFIG_SCx200_WDT) += scx200_wdt.o obj-$(CONFIG_SCx200_WDT) += scx200_wdt.o
...@@ -73,6 +72,7 @@ obj-$(CONFIG_WATCHDOG_RTAS) += wdrtas.o ...@@ -73,6 +72,7 @@ obj-$(CONFIG_WATCHDOG_RTAS) += wdrtas.o
# MIPS Architecture # MIPS Architecture
obj-$(CONFIG_INDYDOG) += indydog.o obj-$(CONFIG_INDYDOG) += indydog.o
obj-$(CONFIG_WDT_MTX1) += mtx-1_wdt.o
obj-$(CONFIG_WDT_RM9K_GPI) += rm9k_wdt.o obj-$(CONFIG_WDT_RM9K_GPI) += rm9k_wdt.o
# S390 Architecture # S390 Architecture
......
...@@ -220,17 +220,17 @@ static int __devinit cpu5wdt_init(void) ...@@ -220,17 +220,17 @@ static int __devinit cpu5wdt_init(void)
if ( verbose ) if ( verbose )
printk(KERN_DEBUG PFX "port=0x%x, verbose=%i\n", port, verbose); printk(KERN_DEBUG PFX "port=0x%x, verbose=%i\n", port, verbose);
if ( (err = misc_register(&cpu5wdt_misc)) < 0 ) {
printk(KERN_ERR PFX "misc_register failed\n");
goto no_misc;
}
if ( !request_region(port, CPU5WDT_EXTENT, PFX) ) { if ( !request_region(port, CPU5WDT_EXTENT, PFX) ) {
printk(KERN_ERR PFX "request_region failed\n"); printk(KERN_ERR PFX "request_region failed\n");
err = -EBUSY; err = -EBUSY;
goto no_port; goto no_port;
} }
if ( (err = misc_register(&cpu5wdt_misc)) < 0 ) {
printk(KERN_ERR PFX "misc_register failed\n");
goto no_misc;
}
/* watchdog reboot? */ /* watchdog reboot? */
val = inb(port + CPU5WDT_STATUS_REG); val = inb(port + CPU5WDT_STATUS_REG);
val = (val >> 2) & 1; val = (val >> 2) & 1;
...@@ -250,9 +250,9 @@ static int __devinit cpu5wdt_init(void) ...@@ -250,9 +250,9 @@ static int __devinit cpu5wdt_init(void)
return 0; return 0;
no_port:
misc_deregister(&cpu5wdt_misc);
no_misc: no_misc:
release_region(port, CPU5WDT_EXTENT);
no_port:
return err; return err;
} }
......
...@@ -413,17 +413,10 @@ static int __init eurwdt_init(void) ...@@ -413,17 +413,10 @@ static int __init eurwdt_init(void)
{ {
int ret; int ret;
ret = misc_register(&eurwdt_miscdev);
if (ret) {
printk(KERN_ERR "eurwdt: can't misc_register on minor=%d\n",
WATCHDOG_MINOR);
goto out;
}
ret = request_irq(irq, eurwdt_interrupt, IRQF_DISABLED, "eurwdt", NULL); ret = request_irq(irq, eurwdt_interrupt, IRQF_DISABLED, "eurwdt", NULL);
if(ret) { if(ret) {
printk(KERN_ERR "eurwdt: IRQ %d is not free.\n", irq); printk(KERN_ERR "eurwdt: IRQ %d is not free.\n", irq);
goto outmisc; goto out;
} }
if (!request_region(io, 2, "eurwdt")) { if (!request_region(io, 2, "eurwdt")) {
...@@ -438,6 +431,13 @@ static int __init eurwdt_init(void) ...@@ -438,6 +431,13 @@ static int __init eurwdt_init(void)
goto outreg; goto outreg;
} }
ret = misc_register(&eurwdt_miscdev);
if (ret) {
printk(KERN_ERR "eurwdt: can't misc_register on minor=%d\n",
WATCHDOG_MINOR);
goto outreboot;
}
eurwdt_unlock_chip(); eurwdt_unlock_chip();
ret = 0; ret = 0;
...@@ -448,14 +448,14 @@ static int __init eurwdt_init(void) ...@@ -448,14 +448,14 @@ static int __init eurwdt_init(void)
out: out:
return ret; return ret;
outreboot:
unregister_reboot_notifier(&eurwdt_notifier);
outreg: outreg:
release_region(io, 2); release_region(io, 2);
outirq: outirq:
free_irq(irq, NULL); free_irq(irq, NULL);
outmisc:
misc_deregister(&eurwdt_miscdev);
goto out; goto out;
} }
......
This diff is collapsed.
/*
* i8xx_tco: TCO timer driver for i8xx chipsets
*
* (c) Copyright 2000 kernel concepts <nils@kernelconcepts.de>, All Rights Reserved.
* http://www.kernelconcepts.de
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*
* Neither kernel concepts nor Nils Faerber admit liability nor provide
* warranty for any of this software. This material is provided
* "AS-IS" and at no charge.
*
* (c) Copyright 2000 kernel concepts <nils@kernelconcepts.de>
* developed for
* Jentro AG, Haar/Munich (Germany)
*
* TCO timer driver for i8xx chipsets
* based on softdog.c by Alan Cox <alan@redhat.com>
*
* For history and the complete list of supported I/O Controller Hub's
* see i8xx_tco.c
*/
/*
* Some address definitions for the TCO
*/
#define TCOBASE ACPIBASE + 0x60 /* TCO base address */
#define TCO1_RLD TCOBASE + 0x00 /* TCO Timer Reload and Current Value */
#define TCO1_TMR TCOBASE + 0x01 /* TCO Timer Initial Value */
#define TCO1_DAT_IN TCOBASE + 0x02 /* TCO Data In Register */
#define TCO1_DAT_OUT TCOBASE + 0x03 /* TCO Data Out Register */
#define TCO1_STS TCOBASE + 0x04 /* TCO1 Status Register */
#define TCO2_STS TCOBASE + 0x06 /* TCO2 Status Register */
#define TCO1_CNT TCOBASE + 0x08 /* TCO1 Control Register */
#define TCO2_CNT TCOBASE + 0x0a /* TCO2 Control Register */
#define SMI_EN ACPIBASE + 0x30 /* SMI Control and Enable Register */
...@@ -367,18 +367,17 @@ static int __init ibmasr_init(void) ...@@ -367,18 +367,17 @@ static int __init ibmasr_init(void)
if (!asr_type) if (!asr_type)
return -ENODEV; return -ENODEV;
rc = asr_get_base_address();
if (rc)
return rc;
rc = misc_register(&asr_miscdev); rc = misc_register(&asr_miscdev);
if (rc < 0) { if (rc < 0) {
release_region(asr_base, asr_length);
printk(KERN_ERR PFX "failed to register misc device\n"); printk(KERN_ERR PFX "failed to register misc device\n");
return rc; return rc;
} }
rc = asr_get_base_address();
if (rc) {
misc_deregister(&asr_miscdev);
return rc;
}
return 0; return 0;
} }
......
...@@ -440,13 +440,6 @@ static int __init zf_init(void) ...@@ -440,13 +440,6 @@ static int __init zf_init(void)
spin_lock_init(&zf_lock); spin_lock_init(&zf_lock);
spin_lock_init(&zf_port_lock); spin_lock_init(&zf_port_lock);
ret = misc_register(&zf_miscdev);
if (ret){
printk(KERN_ERR "can't misc_register on minor=%d\n",
WATCHDOG_MINOR);
goto out;
}
if(!request_region(ZF_IOBASE, 3, "MachZ ZFL WDT")){ if(!request_region(ZF_IOBASE, 3, "MachZ ZFL WDT")){
printk(KERN_ERR "cannot reserve I/O ports at %d\n", printk(KERN_ERR "cannot reserve I/O ports at %d\n",
ZF_IOBASE); ZF_IOBASE);
...@@ -461,16 +454,23 @@ static int __init zf_init(void) ...@@ -461,16 +454,23 @@ static int __init zf_init(void)
goto no_reboot; goto no_reboot;
} }
ret = misc_register(&zf_miscdev);
if (ret){
printk(KERN_ERR "can't misc_register on minor=%d\n",
WATCHDOG_MINOR);
goto no_misc;
}
zf_set_status(0); zf_set_status(0);
zf_set_control(0); zf_set_control(0);
return 0; return 0;
no_misc:
unregister_reboot_notifier(&zf_notifier);
no_reboot: no_reboot:
release_region(ZF_IOBASE, 3); release_region(ZF_IOBASE, 3);
no_region: no_region:
misc_deregister(&zf_miscdev);
out:
return ret; return ret;
} }
......
/*
* Driver for the MTX-1 Watchdog.
*
* (C) Copyright 2005 4G Systems <info@4g-systems.biz>, All Rights Reserved.
* http://www.4g-systems.biz
*
* (C) Copyright 2007 OpenWrt.org, Florian Fainelli <florian@openwrt.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*
* Neither Michael Stickel nor 4G Systems admit liability nor provide
* warranty for any of this software. This material is provided
* "AS-IS" and at no charge.
*
* (c) Copyright 2005 4G Systems <info@4g-systems.biz>
*
* Release 0.01.
* Author: Michael Stickel michael.stickel@4g-systems.biz
*
* Release 0.02.
* Author: Florian Fainelli florian@openwrt.org
* use the Linux watchdog/timer APIs
*
* The Watchdog is configured to reset the MTX-1
* if it is not triggered for 100 seconds.
* It should not be triggered more often than 1.6 seconds.
*
* A timer triggers the watchdog every 5 seconds, until
* it is opened for the first time. After the first open
* it MUST be triggered every 2..95 seconds.
*/
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/timer.h>
#include <linux/completion.h>
#include <linux/jiffies.h>
#include <linux/watchdog.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/mach-au1x00/au1000.h>
#define MTX1_WDT_INTERVAL (5 * HZ)
static int ticks = 100 * HZ;
static struct {
struct completion stop;
volatile int running;
struct timer_list timer;
volatile int queue;
int default_ticks;
unsigned long inuse;
} mtx1_wdt_device;
static void mtx1_wdt_trigger(unsigned long unused)
{
u32 tmp;
if (mtx1_wdt_device.running)
ticks--;
/*
* toggle GPIO2_15
*/
tmp = au_readl(GPIO2_DIR);
tmp = (tmp & ~(1<<15)) | ((~tmp) & (1<<15));
au_writel (tmp, GPIO2_DIR);
if (mtx1_wdt_device.queue && ticks)
mod_timer(&mtx1_wdt_device.timer, jiffies + MTX1_WDT_INTERVAL);
else {
complete(&mtx1_wdt_device.stop);
}
}
static void mtx1_wdt_reset(void)
{
ticks = mtx1_wdt_device.default_ticks;
}
static void mtx1_wdt_start(void)
{
if (!mtx1_wdt_device.queue) {
mtx1_wdt_device.queue = 1;
au_writel (au_readl(GPIO2_DIR) | (u32)(1<<15), GPIO2_DIR);
mod_timer(&mtx1_wdt_device.timer, jiffies + MTX1_WDT_INTERVAL);
}
mtx1_wdt_device.running++;
}
static int mtx1_wdt_stop(void)
{
if (mtx1_wdt_device.queue) {
mtx1_wdt_device.queue = 0;
au_writel (au_readl(GPIO2_DIR) & ~((u32)(1<<15)), GPIO2_DIR);
}
ticks = mtx1_wdt_device.default_ticks;
return 0;
}
/* Filesystem functions */
static int mtx1_wdt_open(struct inode *inode, struct file *file)
{
if (test_and_set_bit(0, &mtx1_wdt_device.inuse))
return -EBUSY;
return nonseekable_open(inode, file);
}
static int mtx1_wdt_release(struct inode *inode, struct file *file)
{
clear_bit(0, &mtx1_wdt_device.inuse);
return 0;
}
static int mtx1_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
void __user *argp = (void __user *)arg;
unsigned int value;
static struct watchdog_info ident =
{
.options = WDIOF_CARDRESET,
.identity = "MTX-1 WDT",
};
switch(cmd) {
case WDIOC_KEEPALIVE:
mtx1_wdt_reset();
break;
case WDIOC_GETSTATUS:
if ( copy_to_user(argp, &value, sizeof(int)) )
return -EFAULT;
break;
case WDIOC_GETSUPPORT:
if ( copy_to_user(argp, &ident, sizeof(ident)) )
return -EFAULT;
break;
case WDIOC_SETOPTIONS:
if ( copy_from_user(&value, argp, sizeof(int)) )
return -EFAULT;
switch(value) {
case WDIOS_ENABLECARD:
mtx1_wdt_start();
break;
case WDIOS_DISABLECARD:
return mtx1_wdt_stop();
default:
return -EINVAL;
}
break;
default:
return -ENOTTY;
}
return 0;
}
static ssize_t mtx1_wdt_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
{
if (!count)
return -EIO;
mtx1_wdt_reset();
return count;
}
static struct file_operations mtx1_wdt_fops = {
.owner = THIS_MODULE,
.llseek = no_llseek,
.ioctl = mtx1_wdt_ioctl,
.open = mtx1_wdt_open,
.write = mtx1_wdt_write,
.release = mtx1_wdt_release
};
static struct miscdevice mtx1_wdt_misc = {
.minor = WATCHDOG_MINOR,
.name = "watchdog",
.fops = &mtx1_wdt_fops
};
static int __init mtx1_wdt_init(void)
{
int ret;
if ((ret = misc_register(&mtx1_wdt_misc)) < 0) {
printk(KERN_ERR " mtx-1_wdt : failed to register\n");
return ret;
}
init_completion(&mtx1_wdt_device.stop);
mtx1_wdt_device.queue = 0;
clear_bit(0, &mtx1_wdt_device.inuse);
setup_timer(&mtx1_wdt_device.timer, mtx1_wdt_trigger, 0L);
mtx1_wdt_device.default_ticks = ticks;
mtx1_wdt_start();
printk(KERN_INFO "MTX-1 Watchdog driver\n");
return 0;
}
static void __exit mtx1_wdt_exit(void)
{
if (mtx1_wdt_device.queue) {
mtx1_wdt_device.queue = 0;
wait_for_completion(&mtx1_wdt_device.stop);
}
misc_deregister(&mtx1_wdt_misc);
}
module_init(mtx1_wdt_init);
module_exit(mtx1_wdt_exit);
MODULE_AUTHOR("Michael Stickel, Florian Fainelli");
MODULE_DESCRIPTION("Driver for the MTX-1 watchdog");
MODULE_LICENSE("GPL");
This diff is collapsed.
...@@ -146,7 +146,7 @@ struct usb_pcwd_private { ...@@ -146,7 +146,7 @@ struct usb_pcwd_private {
atomic_t cmd_received; /* true if we received a report after a command */ atomic_t cmd_received; /* true if we received a report after a command */
int exists; /* Wether or not the device exists */ int exists; /* Wether or not the device exists */
struct semaphore sem; /* locks this structure */ struct mutex mtx; /* locks this structure */
}; };
static struct usb_pcwd_private *usb_pcwd_device; static struct usb_pcwd_private *usb_pcwd_device;
...@@ -635,7 +635,7 @@ static int usb_pcwd_probe(struct usb_interface *interface, const struct usb_devi ...@@ -635,7 +635,7 @@ static int usb_pcwd_probe(struct usb_interface *interface, const struct usb_devi
usb_pcwd_device = usb_pcwd; usb_pcwd_device = usb_pcwd;
init_MUTEX (&usb_pcwd->sem); mutex_init(&usb_pcwd->mtx);
usb_pcwd->udev = udev; usb_pcwd->udev = udev;
usb_pcwd->interface = interface; usb_pcwd->interface = interface;
usb_pcwd->interface_number = iface_desc->desc.bInterfaceNumber; usb_pcwd->interface_number = iface_desc->desc.bInterfaceNumber;
...@@ -763,7 +763,7 @@ static void usb_pcwd_disconnect(struct usb_interface *interface) ...@@ -763,7 +763,7 @@ static void usb_pcwd_disconnect(struct usb_interface *interface)
usb_pcwd = usb_get_intfdata (interface); usb_pcwd = usb_get_intfdata (interface);
usb_set_intfdata (interface, NULL); usb_set_intfdata (interface, NULL);
down (&usb_pcwd->sem); mutex_lock(&usb_pcwd->mtx);
/* Stop the timer before we leave */ /* Stop the timer before we leave */
if (!nowayout) if (!nowayout)
...@@ -777,7 +777,7 @@ static void usb_pcwd_disconnect(struct usb_interface *interface) ...@@ -777,7 +777,7 @@ static void usb_pcwd_disconnect(struct usb_interface *interface)
misc_deregister(&usb_pcwd_temperature_miscdev); misc_deregister(&usb_pcwd_temperature_miscdev);
unregister_reboot_notifier(&usb_pcwd_notifier); unregister_reboot_notifier(&usb_pcwd_notifier);
up (&usb_pcwd->sem); mutex_unlock(&usb_pcwd->mtx);
/* Delete the USB PCWD device */ /* Delete the USB PCWD device */
usb_pcwd_delete(usb_pcwd); usb_pcwd_delete(usb_pcwd);
......
...@@ -379,14 +379,14 @@ static int s3c2410wdt_probe(struct platform_device *pdev) ...@@ -379,14 +379,14 @@ static int s3c2410wdt_probe(struct platform_device *pdev)
DBG("probe: mapped wdt_base=%p\n", wdt_base); DBG("probe: mapped wdt_base=%p\n", wdt_base);
res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); wdt_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (res == NULL) { if (wdt_irq == NULL) {
printk(KERN_INFO PFX "failed to get irq resource\n"); printk(KERN_INFO PFX "failed to get irq resource\n");
ret = -ENOENT; ret = -ENOENT;
goto err_map; goto err_map;
} }
ret = request_irq(res->start, s3c2410wdt_irq, 0, pdev->name, pdev); ret = request_irq(wdt_irq->start, s3c2410wdt_irq, 0, pdev->name, pdev);
if (ret != 0) { if (ret != 0) {
printk(KERN_INFO PFX "failed to install irq (%d)\n", ret); printk(KERN_INFO PFX "failed to install irq (%d)\n", ret);
goto err_map; goto err_map;
......
...@@ -333,18 +333,17 @@ static int __init sbc8360_init(void) ...@@ -333,18 +333,17 @@ static int __init sbc8360_init(void)
int res; int res;
unsigned long int mseconds = 60000; unsigned long int mseconds = 60000;
spin_lock_init(&sbc8360_lock); if (timeout < 0 || timeout > 63) {
res = misc_register(&sbc8360_miscdev); printk(KERN_ERR PFX "Invalid timeout index (must be 0-63).\n");
if (res) { res = -EINVAL;
printk(KERN_ERR PFX "failed to register misc device\n"); goto out;
goto out_nomisc;
} }
if (!request_region(SBC8360_ENABLE, 1, "SBC8360")) { if (!request_region(SBC8360_ENABLE, 1, "SBC8360")) {
printk(KERN_ERR PFX "ENABLE method I/O %X is not available.\n", printk(KERN_ERR PFX "ENABLE method I/O %X is not available.\n",
SBC8360_ENABLE); SBC8360_ENABLE);
res = -EIO; res = -EIO;
goto out_noenablereg; goto out;
} }
if (!request_region(SBC8360_BASETIME, 1, "SBC8360")) { if (!request_region(SBC8360_BASETIME, 1, "SBC8360")) {
printk(KERN_ERR PFX printk(KERN_ERR PFX
...@@ -360,10 +359,11 @@ static int __init sbc8360_init(void) ...@@ -360,10 +359,11 @@ static int __init sbc8360_init(void)
goto out_noreboot; goto out_noreboot;
} }
if (timeout < 0 || timeout > 63) { spin_lock_init(&sbc8360_lock);
printk(KERN_ERR PFX "Invalid timeout index (must be 0-63).\n"); res = misc_register(&sbc8360_miscdev);
res = -EINVAL; if (res) {
goto out_noreboot; printk(KERN_ERR PFX "failed to register misc device\n");
goto out_nomisc;
} }
wd_margin = wd_times[timeout][0]; wd_margin = wd_times[timeout][0];
...@@ -383,13 +383,13 @@ static int __init sbc8360_init(void) ...@@ -383,13 +383,13 @@ static int __init sbc8360_init(void)
return 0; return 0;
out_nomisc:
unregister_reboot_notifier(&sbc8360_notifier);
out_noreboot: out_noreboot:
release_region(SBC8360_ENABLE, 1);
release_region(SBC8360_BASETIME, 1); release_region(SBC8360_BASETIME, 1);
out_noenablereg:
out_nobasetimereg: out_nobasetimereg:
misc_deregister(&sbc8360_miscdev); release_region(SBC8360_ENABLE, 1);
out_nomisc: out:
return res; return res;
} }
......
/* /*
* w83627hf WDT driver * w83627hf/thf WDT driver
*
* (c) Copyright 2007 Vlad Drukker <vlad@storewiz.com>
* added support for W83627THF.
* *
* (c) Copyright 2003 Pdraig Brady <P@draigBrady.com> * (c) Copyright 2003 Pdraig Brady <P@draigBrady.com>
* *
...@@ -39,7 +42,7 @@ ...@@ -39,7 +42,7 @@
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/system.h> #include <asm/system.h>
#define WATCHDOG_NAME "w83627hf WDT" #define WATCHDOG_NAME "w83627hf/thf WDT"
#define PFX WATCHDOG_NAME ": " #define PFX WATCHDOG_NAME ": "
#define WATCHDOG_TIMEOUT 60 /* 60 sec default timeout */ #define WATCHDOG_TIMEOUT 60 /* 60 sec default timeout */
...@@ -50,7 +53,7 @@ static spinlock_t io_lock; ...@@ -50,7 +53,7 @@ static spinlock_t io_lock;
/* You must set this - there is no sane way to probe for this board. */ /* You must set this - there is no sane way to probe for this board. */
static int wdt_io = 0x2E; static int wdt_io = 0x2E;
module_param(wdt_io, int, 0); module_param(wdt_io, int, 0);
MODULE_PARM_DESC(wdt_io, "w83627hf WDT io port (default 0x2E)"); MODULE_PARM_DESC(wdt_io, "w83627hf/thf WDT io port (default 0x2E)");
static int timeout = WATCHDOG_TIMEOUT; /* in seconds */ static int timeout = WATCHDOG_TIMEOUT; /* in seconds */
module_param(timeout, int, 0); module_param(timeout, int, 0);
...@@ -71,9 +74,19 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" _ ...@@ -71,9 +74,19 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" _
static void static void
w83627hf_select_wd_register(void) w83627hf_select_wd_register(void)
{ {
unsigned char c;
outb_p(0x87, WDT_EFER); /* Enter extended function mode */ outb_p(0x87, WDT_EFER); /* Enter extended function mode */
outb_p(0x87, WDT_EFER); /* Again according to manual */ outb_p(0x87, WDT_EFER); /* Again according to manual */
outb(0x20, WDT_EFER); /* check chip version */
c = inb(WDT_EFDR);
if (c == 0x82) { /* W83627THF */
outb_p(0x2b, WDT_EFER); /* select GPIO3 */
c = ((inb_p(WDT_EFDR) & 0xf7) | 0x04); /* select WDT0 */
outb_p(0x2b, WDT_EFER);
outb_p(c, WDT_EFDR); /* set GPIO3 to WDT0 */
}
outb_p(0x07, WDT_EFER); /* point to logical device number reg */ outb_p(0x07, WDT_EFER); /* point to logical device number reg */
outb_p(0x08, WDT_EFDR); /* select logical device 8 (GPIO2) */ outb_p(0x08, WDT_EFDR); /* select logical device 8 (GPIO2) */
outb_p(0x30, WDT_EFER); /* select CR30 */ outb_p(0x30, WDT_EFER); /* select CR30 */
...@@ -311,7 +324,7 @@ wdt_init(void) ...@@ -311,7 +324,7 @@ wdt_init(void)
spin_lock_init(&io_lock); spin_lock_init(&io_lock);
printk(KERN_INFO "WDT driver for the Winbond(TM) W83627HF Super I/O chip initialising.\n"); printk(KERN_INFO "WDT driver for the Winbond(TM) W83627HF/THF Super I/O chip initialising.\n");
if (wdt_set_heartbeat(timeout)) { if (wdt_set_heartbeat(timeout)) {
wdt_set_heartbeat(WATCHDOG_TIMEOUT); wdt_set_heartbeat(WATCHDOG_TIMEOUT);
...@@ -367,5 +380,5 @@ module_exit(wdt_exit); ...@@ -367,5 +380,5 @@ module_exit(wdt_exit);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_AUTHOR("Pdraig Brady <P@draigBrady.com>"); MODULE_AUTHOR("Pdraig Brady <P@draigBrady.com>");
MODULE_DESCRIPTION("w83627hf WDT driver"); MODULE_DESCRIPTION("w83627hf/thf WDT driver");
MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment