Commit 00b1533f authored by Dave Jones's avatar Dave Jones

[WATCHDOG] amd7xx_tco updates from Zwane, and nuke EXPORT_NO_SYMBOLS

parent c7650146
/* /*
* AMD 766/768 TCO Timer Driver * AMD 766/768 TCO Timer Driver
* (c) Copyright 2002 Zwane Mwaikambo <zwane@commfireservices.com> * (c) Copyright 2002 Zwane Mwaikambo <zwane@holomorphy.com>
* All Rights Reserved. * All Rights Reserved.
* *
* Parts from; * Parts from;
...@@ -34,35 +34,48 @@ ...@@ -34,35 +34,48 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/pci.h> #include <linux/pci.h>
#define AMDTCO_MODULE_VER "build 20020601" #define AMDTCO_MODULE_VER "build 20021116"
#define AMDTCO_MODULE_NAME "amd7xx_tco" #define AMDTCO_MODULE_NAME "amd7xx_tco"
#define PFX AMDTCO_MODULE_NAME ": " #define PFX AMDTCO_MODULE_NAME ": "
#define MAX_TIMEOUT 38 /* max of 38 seconds */ #define MAX_TIMEOUT 38 /* max of 38 seconds, although the system will only
* reset itself after the second timeout */
/* pmbase registers */ /* pmbase registers */
#define GLOBAL_SMI_REG 0x2a
#define TCO_EN (1 << 1) /* bit 1 in global SMI register */
#define TCO_RELOAD_REG 0x40 /* bits 0-5 are current count, 6-7 are reserved */ #define TCO_RELOAD_REG 0x40 /* bits 0-5 are current count, 6-7 are reserved */
#define TCO_INITVAL_REG 0x41 /* bits 0-5 are value to load, 6-7 are reserved */ #define TCO_INITVAL_REG 0x41 /* bits 0-5 are value to load, 6-7 are reserved */
#define TCO_TIMEOUT_MASK 0x3f #define TCO_TIMEOUT_MASK 0x3f
#define TCO_STATUS1_REG 0x44
#define TCO_STATUS2_REG 0x46 #define TCO_STATUS2_REG 0x46
#define NDTO_STS2 (1 << 1) /* we're interested in the second timeout */ #define NDTO_STS2 (1 << 1) /* we're interested in the second timeout */
#define BOOT_STS (1 << 2) /* will be set if NDTO_STS2 was set before reboot */ #define BOOT_STS (1 << 2) /* will be set if NDTO_STS2 was set before reboot */
#define TCO_CTRL1_REG 0x48 #define TCO_CTRL1_REG 0x48
#define TCO_HALT (1 << 11) #define TCO_HALT (1 << 11)
#define NO_REBOOT (1 << 10) /* in DevB:3x48 */
static char banner[] __initdata = KERN_INFO PFX AMDTCO_MODULE_VER; static char banner[] __initdata = KERN_INFO PFX AMDTCO_MODULE_VER "\n";
static int timeout = 38; static int timeout = MAX_TIMEOUT;
static u32 pmbase; /* PMxx I/O base */ static u32 pmbase; /* PMxx I/O base */
static struct pci_dev *dev; static struct pci_dev *dev;
static struct semaphore open_sem; static struct semaphore open_sem;
spinlock_t amdtco_lock; /* only for device access */ static spinlock_t amdtco_lock; /* only for device access */
static int expect_close = 0; static int expect_close = 0;
MODULE_PARM(timeout, "i"); MODULE_PARM(timeout, "i");
MODULE_PARM_DESC(timeout, "range is 0-38 seconds, default is 38"); MODULE_PARM_DESC(timeout, "range is 0-38 seconds, default is 38");
static inline u8 seconds_to_ticks(int seconds)
{
/* the internal timer is stored as ticks which decrement
* every 0.6 seconds */
return (seconds * 10) / 6;
}
static inline int ticks_to_seconds(u8 ticks)
{
return (ticks * 6) / 10;
}
static inline int amdtco_status(void) static inline int amdtco_status(void)
{ {
u16 reg; u16 reg;
...@@ -81,28 +94,19 @@ static inline int amdtco_status(void) ...@@ -81,28 +94,19 @@ static inline int amdtco_status(void)
static inline void amdtco_ping(void) static inline void amdtco_ping(void)
{ {
u8 reg; outb(1, pmbase+TCO_RELOAD_REG);
spin_lock(&amdtco_lock);
reg = inb(pmbase+TCO_RELOAD_REG);
outb(1 | reg, pmbase+TCO_RELOAD_REG);
spin_unlock(&amdtco_lock);
} }
static inline int amdtco_gettimeout(void) static inline int amdtco_gettimeout(void)
{ {
return inb(TCO_RELOAD_REG) & TCO_TIMEOUT_MASK; u8 reg = inb(pmbase+TCO_RELOAD_REG) & TCO_TIMEOUT_MASK;
return ticks_to_seconds(reg);
} }
static inline void amdtco_settimeout(unsigned int timeout) static inline void amdtco_settimeout(unsigned int timeout)
{ {
u8 reg; u8 reg = seconds_to_ticks(timeout) & TCO_TIMEOUT_MASK;
spin_lock(&amdtco_lock);
reg = inb(pmbase+TCO_INITVAL_REG);
reg |= timeout & TCO_TIMEOUT_MASK;
outb(reg, pmbase+TCO_INITVAL_REG); outb(reg, pmbase+TCO_INITVAL_REG);
spin_unlock(&amdtco_lock);
} }
static inline void amdtco_global_enable(void) static inline void amdtco_global_enable(void)
...@@ -110,9 +114,12 @@ static inline void amdtco_global_enable(void) ...@@ -110,9 +114,12 @@ static inline void amdtco_global_enable(void)
u16 reg; u16 reg;
spin_lock(&amdtco_lock); spin_lock(&amdtco_lock);
reg = inw(pmbase+GLOBAL_SMI_REG);
reg |= TCO_EN; /* clear NO_REBOOT on DevB:3x48 p97 */
outw(reg, pmbase+GLOBAL_SMI_REG); pci_read_config_word(dev, 0x48, &reg);
reg &= ~NO_REBOOT;
pci_write_config_word(dev, 0x48, reg);
spin_unlock(&amdtco_lock); spin_unlock(&amdtco_lock);
} }
...@@ -146,10 +153,12 @@ static int amdtco_fop_open(struct inode *inode, struct file *file) ...@@ -146,10 +153,12 @@ static int amdtco_fop_open(struct inode *inode, struct file *file)
if (timeout > MAX_TIMEOUT) if (timeout > MAX_TIMEOUT)
timeout = MAX_TIMEOUT; timeout = MAX_TIMEOUT;
amdtco_disable();
amdtco_settimeout(timeout); amdtco_settimeout(timeout);
amdtco_global_enable(); amdtco_global_enable();
amdtco_enable();
amdtco_ping(); amdtco_ping();
printk(KERN_INFO PFX "Watchdog enabled, timeout = %d/%d seconds", printk(KERN_INFO PFX "Watchdog enabled, timeout = %ds of %ds\n",
amdtco_gettimeout(), timeout); amdtco_gettimeout(), timeout);
return 0; return 0;
...@@ -198,7 +207,7 @@ static int amdtco_fop_ioctl(struct inode *inode, struct file *file, unsigned int ...@@ -198,7 +207,7 @@ static int amdtco_fop_ioctl(struct inode *inode, struct file *file, unsigned int
case WDIOC_GETTIMEOUT: case WDIOC_GETTIMEOUT:
return put_user(amdtco_gettimeout(), (int *)arg); return put_user(amdtco_gettimeout(), (int *)arg);
case WDIOC_SETOPTIONS: case WDIOC_SETOPTIONS:
if (copy_from_user(&tmp, (int *)arg, sizeof tmp)) if (copy_from_user(&tmp, (int *)arg, sizeof tmp))
return -EFAULT; return -EFAULT;
...@@ -221,7 +230,7 @@ static int amdtco_fop_release(struct inode *inode, struct file *file) ...@@ -221,7 +230,7 @@ static int amdtco_fop_release(struct inode *inode, struct file *file)
printk(KERN_INFO PFX "Watchdog disabled\n"); printk(KERN_INFO PFX "Watchdog disabled\n");
} else { } else {
amdtco_ping(); amdtco_ping();
printk(KERN_CRIT PFX "Unexpected close!, timeout in %d seconds)\n", timeout); printk(KERN_CRIT PFX "Unexpected close!, timeout in %d seconds\n", timeout);
} }
up(&open_sem); up(&open_sem);
...@@ -249,10 +258,9 @@ static ssize_t amdtco_fop_write(struct file *file, const char *data, size_t len, ...@@ -249,10 +258,9 @@ static ssize_t amdtco_fop_write(struct file *file, const char *data, size_t len,
} }
#endif #endif
amdtco_ping(); amdtco_ping();
return len;
} }
return 0; return len;
} }
...@@ -357,6 +365,9 @@ static int __init amdtco_setup(char *str) ...@@ -357,6 +365,9 @@ static int __init amdtco_setup(char *str)
if (ints[0] > 0) if (ints[0] > 0)
timeout = ints[1]; timeout = ints[1];
if (!timeout || timeout > MAX_TIMEOUT)
timeout = MAX_TIMEOUT;
return 1; return 1;
} }
...@@ -366,8 +377,7 @@ __setup("amd7xx_tco=", amdtco_setup); ...@@ -366,8 +377,7 @@ __setup("amd7xx_tco=", amdtco_setup);
module_init(amdtco_init); module_init(amdtco_init);
module_exit(amdtco_exit); module_exit(amdtco_exit);
MODULE_AUTHOR("Zwane Mwaikambo <zwane@commfireservices.com>"); MODULE_AUTHOR("Zwane Mwaikambo <zwane@holomorphy.com>");
MODULE_DESCRIPTION("AMD 766/768 TCO Timer Driver"); MODULE_DESCRIPTION("AMD 766/768 TCO Timer Driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
EXPORT_NO_SYMBOLS;
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