Merge branch 'for-rmk' of git://git.pengutronix.de/git/imx/linux-2.6 into devel

Conflicts:

	arch/arm/mach-at91/gpio.c
This commit is contained in:
Russell King 2009-03-13 21:44:51 +00:00 • committed by Russell King
commit 97fb44eb6b
1121 changed files with 41599 additions and 21839 deletions

View file

@ -406,7 +406,7 @@ config ITCO_WDT
---help---
Hardware driver for the intel TCO timer based watchdog devices.
These drivers are included in the Intel 82801 I/O Controller
Hub family (from ICH0 up to ICH8) and in the Intel 6300ESB
Hub family (from ICH0 up to ICH10) and in the Intel 63xxESB
controller hub.
The TCO (Total Cost of Ownership) timer is a watchdog timer

View file

@ -107,10 +107,10 @@ static int at91_wdt_close(struct inode *inode, struct file *file)
static int at91_wdt_settimeout(int new_time)
{
/*
* All counting occurs at SLOW_CLOCK / 128 = 0.256 Hz
* All counting occurs at SLOW_CLOCK / 128 = 256 Hz
*
* Since WDV is a 16-bit counter, the maximum period is
* 65536 / 0.256 = 256 seconds.
* 65536 / 256 = 256 seconds.
*/
if ((new_time <= 0) || (new_time > WDT_MAX_TIME))
return -EINVAL;

View file

@ -18,6 +18,7 @@
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/miscdevice.h>
#include <linux/module.h>

View file

@ -269,7 +269,7 @@ static int __devinit gef_wdt_probe(struct of_device *dev,
bus_clk = 133; /* in MHz */
freq = fsl_get_sys_freq();
if (freq > 0)
if (freq != -1)
bus_clk = freq;
/* Map devices registers into memory */

View file

@ -1,7 +1,7 @@
/*
* intel TCO vendor specific watchdog driver support
*
* (c) Copyright 2006-2008 Wim Van Sebroeck <wim@iguana.be>.
* (c) Copyright 2006-2009 Wim Van Sebroeck <wim@iguana.be>.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -19,7 +19,7 @@
/* Module and version information */
#define DRV_NAME "iTCO_vendor_support"
#define DRV_VERSION "1.02"
#define DRV_VERSION "1.03"
#define PFX DRV_NAME ": "
/* Includes */
@ -77,6 +77,26 @@ MODULE_PARM_DESC(vendorsupport, "iTCO vendor specific support mode, default=0 (n
* 20.6 seconds.
*/
static void supermicro_old_pre_start(unsigned long acpibase)
{
unsigned long val32;
/* Bit 13: TCO_EN -> 0 = Disables TCO logic generating an SMI# */
val32 = inl(SMI_EN);
val32 &= 0xffffdfff; /* Turn off SMI clearing watchdog */
outl(val32, SMI_EN); /* Needed to activate watchdog */
}
static void supermicro_old_pre_stop(unsigned long acpibase)
{
unsigned long val32;
/* Bit 13: TCO_EN -> 1 = Enables the TCO logic to generate SMI# */
val32 = inl(SMI_EN);
val32 |= 0x00002000; /* Turn on SMI clearing watchdog */
outl(val32, SMI_EN); /* Needed to deactivate watchdog */
}
static void supermicro_old_pre_keepalive(unsigned long acpibase)
{
/* Reload TCO Timer (done in iTCO_wdt_keepalive) + */
@ -228,14 +248,18 @@ static void supermicro_new_pre_set_heartbeat(unsigned int heartbeat)
void iTCO_vendor_pre_start(unsigned long acpibase,
unsigned int heartbeat)
{
if (vendorsupport == SUPERMICRO_NEW_BOARD)
if (vendorsupport == SUPERMICRO_OLD_BOARD)
supermicro_old_pre_start(acpibase);
else if (vendorsupport == SUPERMICRO_NEW_BOARD)
supermicro_new_pre_start(heartbeat);
}
EXPORT_SYMBOL(iTCO_vendor_pre_start);
void iTCO_vendor_pre_stop(unsigned long acpibase)
{
if (vendorsupport == SUPERMICRO_NEW_BOARD)
if (vendorsupport == SUPERMICRO_OLD_BOARD)
supermicro_old_pre_stop(acpibase);
else if (vendorsupport == SUPERMICRO_NEW_BOARD)
supermicro_new_pre_stop();
}
EXPORT_SYMBOL(iTCO_vendor_pre_stop);

View file

@ -1,7 +1,7 @@
/*
* intel TCO Watchdog Driver (Used in i82801 and i6300ESB chipsets)
* intel TCO Watchdog Driver (Used in i82801 and i63xxESB chipsets)
*
* (c) Copyright 2006-2008 Wim Van Sebroeck <wim@iguana.be>.
* (c) Copyright 2006-2009 Wim Van Sebroeck <wim@iguana.be>.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -63,7 +63,7 @@
/* Module and version information */
#define DRV_NAME "iTCO_wdt"
#define DRV_VERSION "1.04"
#define DRV_VERSION "1.05"
#define PFX DRV_NAME ": "
/* Includes */
@ -236,16 +236,16 @@ MODULE_DEVICE_TABLE(pci, iTCO_wdt_pci_tbl);
/* Address definitions for the TCO */
/* TCO base address */
#define TCOBASE iTCO_wdt_private.ACPIBASE + 0x60
#define TCOBASE iTCO_wdt_private.ACPIBASE + 0x60
/* SMI Control and Enable Register */
#define SMI_EN iTCO_wdt_private.ACPIBASE + 0x30
#define SMI_EN iTCO_wdt_private.ACPIBASE + 0x30
#define TCO_RLD TCOBASE + 0x00 /* TCO Timer Reload and Curr. Value */
#define TCOv1_TMR TCOBASE + 0x01 /* TCOv1 Timer Initial Value */
#define TCO_DAT_IN TCOBASE + 0x02 /* TCO Data In Register */
#define TCO_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 TCO_DAT_IN TCOBASE + 0x02 /* TCO Data In Register */
#define TCO_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 TCOv2_TMR TCOBASE + 0x12 /* TCOv2 Timer Initial Value */
@ -338,7 +338,6 @@ static int iTCO_wdt_unset_NO_REBOOT_bit(void)
static int iTCO_wdt_start(void)
{
unsigned int val;
unsigned long val32;
spin_lock(&iTCO_wdt_private.io_lock);
@ -351,11 +350,6 @@ static int iTCO_wdt_start(void)
return -EIO;
}
/* Bit 13: TCO_EN -> 0 = Disables TCO logic generating an SMI# */
val32 = inl(SMI_EN);
val32 &= 0xffffdfff; /* Turn off SMI clearing watchdog */
outl(val32, SMI_EN);
/* Force the timer to its reload value by writing to the TCO_RLD
register */
if (iTCO_wdt_private.iTCO_version == 2)
@ -378,7 +372,6 @@ static int iTCO_wdt_start(void)
static int iTCO_wdt_stop(void)
{
unsigned int val;
unsigned long val32;
spin_lock(&iTCO_wdt_private.io_lock);
@ -390,11 +383,6 @@ static int iTCO_wdt_stop(void)
outw(val, TCO1_CNT);
val = inw(TCO1_CNT);
/* Bit 13: TCO_EN -> 1 = Enables the TCO logic to generate SMI# */
val32 = inl(SMI_EN);
val32 |= 0x00002000;
outl(val32, SMI_EN);
/* Set the NO_REBOOT bit to prevent later reboots, just for sure */
iTCO_wdt_set_NO_REBOOT_bit();
@ -649,6 +637,7 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev,
int ret;
u32 base_address;
unsigned long RCBA;
unsigned long val32;
/*
* Find the ACPI/PM base I/O address which is the base
@ -695,6 +684,10 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev,
ret = -EIO;
goto out;
}
/* Bit 13: TCO_EN -> 0 = Disables TCO logic generating an SMI# */
val32 = inl(SMI_EN);
val32 &= 0xffffdfff; /* Turn off SMI clearing watchdog */
outl(val32, SMI_EN);
/* The TCO I/O registers reside in a 32-byte range pointed to
by the TCOBASE value */

View file

@ -21,6 +21,7 @@
#include <linux/watchdog.h>
#include <linux/io.h>
#include <linux/uaccess.h>
#include <mach/timex.h>
#include <mach/regs-timer.h>
#define WDT_DEFAULT_TIME 5 /* seconds */

View file

@ -29,6 +29,7 @@
#define WDT_EN 0x0010
#define WDT_VAL (TIMER_VIRT_BASE + 0x0024)
#define ORION5X_TCLK 166666667
#define WDT_MAX_DURATION (0xffffffff / ORION5X_TCLK)
#define WDT_IN_USE 0
#define WDT_OK_TO_CLOSE 1

View file

@ -34,104 +34,89 @@
#include <asm/time.h>
#include <asm/mach-rc32434/integ.h>
#define MAX_TIMEOUT 20
#define RC32434_WDT_INTERVAL (15 * HZ)
#define VERSION "0.2"
#define VERSION "0.4"
static struct {
struct completion stop;
int running;
struct timer_list timer;
int queue;
int default_ticks;
unsigned long inuse;
} rc32434_wdt_device;
static struct integ __iomem *wdt_reg;
static int ticks = 100 * HZ;
static int expect_close;
static int timeout;
/* Board internal clock speed in Hz,
* the watchdog timer ticks at. */
extern unsigned int idt_cpu_freq;
/* translate wtcompare value to seconds and vice versa */
#define WTCOMP2SEC(x) (x / idt_cpu_freq)
#define SEC2WTCOMP(x) (x * idt_cpu_freq)
/* Use a default timeout of 20s. This should be
* safe for CPU clock speeds up to 400MHz, as
* ((2 ^ 32) - 1) / (400MHz / 2) = 21s. */
#define WATCHDOG_TIMEOUT 20
static int timeout = WATCHDOG_TIMEOUT;
static int nowayout = WATCHDOG_NOWAYOUT;
module_param(nowayout, int, 0);
MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
__MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
/* apply or and nand masks to data read from addr and write back */
#define SET_BITS(addr, or, nand) \
writel((readl(&addr) | or) & ~nand, &addr)
static void rc32434_wdt_start(void)
{
u32 val;
u32 or, nand;
if (!rc32434_wdt_device.inuse) {
writel(0, &wdt_reg->wtcount);
/* zero the counter before enabling */
writel(0, &wdt_reg->wtcount);
val = RC32434_ERR_WRE;
writel(readl(&wdt_reg->errcs) | val, &wdt_reg->errcs);
/* don't generate a non-maskable interrupt,
* do a warm reset instead */
nand = 1 << RC32434_ERR_WNE;
or = 1 << RC32434_ERR_WRE;
val = RC32434_WTC_EN;
writel(readl(&wdt_reg->wtc) | val, &wdt_reg->wtc);
}
rc32434_wdt_device.running++;
/* reset the ERRCS timeout bit in case it's set */
nand |= 1 << RC32434_ERR_WTO;
SET_BITS(wdt_reg->errcs, or, nand);
/* reset WTC timeout bit and enable WDT */
nand = 1 << RC32434_WTC_TO;
or = 1 << RC32434_WTC_EN;
SET_BITS(wdt_reg->wtc, or, nand);
}
static void rc32434_wdt_stop(void)
{
u32 val;
/* Disable WDT */
SET_BITS(wdt_reg->wtc, 0, 1 << RC32434_WTC_EN);
}
if (rc32434_wdt_device.running) {
static int rc32434_wdt_set(int new_timeout)
{
int max_to = WTCOMP2SEC((u32)-1);
val = ~RC32434_WTC_EN;
writel(readl(&wdt_reg->wtc) & val, &wdt_reg->wtc);
val = ~RC32434_ERR_WRE;
writel(readl(&wdt_reg->errcs) & val, &wdt_reg->errcs);
rc32434_wdt_device.running = 0;
if (new_timeout < 0 || new_timeout > max_to) {
printk(KERN_ERR KBUILD_MODNAME
": timeout value must be between 0 and %d",
max_to);
return -EINVAL;
}
}
static void rc32434_wdt_set(int new_timeout)
{
u32 cmp = new_timeout * HZ;
u32 state, val;
timeout = new_timeout;
/*
* store and disable WTC
*/
state = (u32)(readl(&wdt_reg->wtc) & RC32434_WTC_EN);
val = ~RC32434_WTC_EN;
writel(readl(&wdt_reg->wtc) & val, &wdt_reg->wtc);
writel(SEC2WTCOMP(timeout), &wdt_reg->wtcompare);
writel(0, &wdt_reg->wtcount);
writel(cmp, &wdt_reg->wtcompare);
/*
* restore WTC
*/
writel(readl(&wdt_reg->wtc) | state, &wdt_reg);
return 0;
}
static void rc32434_wdt_reset(void)
static void rc32434_wdt_ping(void)
{
ticks = rc32434_wdt_device.default_ticks;
}
static void rc32434_wdt_update(unsigned long unused)
{
if (rc32434_wdt_device.running)
ticks--;
writel(0, &wdt_reg->wtcount);
if (rc32434_wdt_device.queue && ticks)
mod_timer(&rc32434_wdt_device.timer,
jiffies + RC32434_WDT_INTERVAL);
else
complete(&rc32434_wdt_device.stop);
}
static int rc32434_wdt_open(struct inode *inode, struct file *file)
@ -142,19 +127,23 @@ static int rc32434_wdt_open(struct inode *inode, struct file *file)
if (nowayout)
__module_get(THIS_MODULE);
rc32434_wdt_start();
rc32434_wdt_ping();
return nonseekable_open(inode, file);
}
static int rc32434_wdt_release(struct inode *inode, struct file *file)
{
if (expect_close && nowayout == 0) {
if (expect_close == 42) {
rc32434_wdt_stop();
printk(KERN_INFO KBUILD_MODNAME ": disabling watchdog timer\n");
module_put(THIS_MODULE);
} else
} else {
printk(KERN_CRIT KBUILD_MODNAME
": device closed unexpectedly. WDT will not stop !\n");
rc32434_wdt_ping();
}
clear_bit(0, &rc32434_wdt_device.inuse);
return 0;
}
@ -174,10 +163,10 @@ static ssize_t rc32434_wdt_write(struct file *file, const char *data,
if (get_user(c, data + i))
return -EFAULT;
if (c == 'V')
expect_close = 1;
expect_close = 42;
}
}
rc32434_wdt_update(0);
rc32434_wdt_ping();
return len;
}
return 0;
@ -197,11 +186,11 @@ static long rc32434_wdt_ioctl(struct file *file, unsigned int cmd,
};
switch (cmd) {
case WDIOC_KEEPALIVE:
rc32434_wdt_reset();
rc32434_wdt_ping();
break;
case WDIOC_GETSTATUS:
case WDIOC_GETBOOTSTATUS:
value = readl(&wdt_reg->wtcount);
value = 0;
if (copy_to_user(argp, &value, sizeof(int)))
return -EFAULT;
break;
@ -218,6 +207,7 @@ static long rc32434_wdt_ioctl(struct file *file, unsigned int cmd,
break;
case WDIOS_DISABLECARD:
rc32434_wdt_stop();
break;
default:
return -EINVAL;
}
@ -225,11 +215,9 @@ static long rc32434_wdt_ioctl(struct file *file, unsigned int cmd,
case WDIOC_SETTIMEOUT:
if (copy_from_user(&new_timeout, argp, sizeof(int)))
return -EFAULT;
if (new_timeout < 1)
if (rc32434_wdt_set(new_timeout))
return -EINVAL;
if (new_timeout > MAX_TIMEOUT)
return -EINVAL;
rc32434_wdt_set(new_timeout);
/* Fall through */
case WDIOC_GETTIMEOUT:
return copy_to_user(argp, &timeout, sizeof(int));
default:
@ -254,15 +242,15 @@ static struct miscdevice rc32434_wdt_miscdev = {
.fops = &rc32434_wdt_fops,
};
static char banner[] = KERN_INFO KBUILD_MODNAME
static char banner[] __devinitdata = KERN_INFO KBUILD_MODNAME
": Watchdog Timer version " VERSION ", timer margin: %d sec\n";
static int rc32434_wdt_probe(struct platform_device *pdev)
static int __devinit rc32434_wdt_probe(struct platform_device *pdev)
{
int ret;
struct resource *r;
r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rb500_wdt_res");
r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rb532_wdt_res");
if (!r) {
printk(KERN_ERR KBUILD_MODNAME
"failed to retrieve resources\n");
@ -277,24 +265,12 @@ static int rc32434_wdt_probe(struct platform_device *pdev)
}
ret = misc_register(&rc32434_wdt_miscdev);
if (ret < 0) {
printk(KERN_ERR KBUILD_MODNAME
"failed to register watchdog device\n");
goto unmap;
}
init_completion(&rc32434_wdt_device.stop);
rc32434_wdt_device.queue = 0;
clear_bit(0, &rc32434_wdt_device.inuse);
setup_timer(&rc32434_wdt_device.timer, rc32434_wdt_update, 0L);
rc32434_wdt_device.default_ticks = ticks;
rc32434_wdt_start();
printk(banner, timeout);
return 0;
@ -304,23 +280,17 @@ unmap:
return ret;
}
static int rc32434_wdt_remove(struct platform_device *pdev)
static int __devexit rc32434_wdt_remove(struct platform_device *pdev)
{
if (rc32434_wdt_device.queue) {
rc32434_wdt_device.queue = 0;
wait_for_completion(&rc32434_wdt_device.stop);
}
misc_deregister(&rc32434_wdt_miscdev);
iounmap(wdt_reg);
return 0;
}
static struct platform_driver rc32434_wdt = {
.probe = rc32434_wdt_probe,
.remove = rc32434_wdt_remove,
.driver = {
.remove = __devexit_p(rc32434_wdt_remove),
.driver = {
.name = "rc32434_wdt",
}
};