Skip to content

Commit

Permalink
Merge git://git.kernel.org/pub/scm/linux/kernel/git/wim/linux-2.6-wat…
Browse files Browse the repository at this point in the history
…chdog

* git://git.kernel.org/pub/scm/linux/kernel/git/wim/linux-2.6-watchdog:
  [WATCHDOG] sizeof cleanup
  [WATCHDOG] wdt_pci: fix printk and variable type
  [WATCHDOG] wdt_pci - use pci_request_region
  [WATCHDOG] ar7_wdt: Fix error handling during probe.
  [WATCHDOG] ar7_wdt: convert to become a platform driver
  [WATCHDOG] fix book E watchdog to take WDIOC_SETTIMEOUT arg in seconds
  [WATCHDOG] davinci: use clock framework for timer frequency
  [WATCHDOG] Use DIV_ROUND_UP() macro in the coh901327 WDT
  [WATCHDOG] Add support for WM831x watchdog
  [WATCHDOG] Add watchdog driver for NUC900
  [WATCHDOG] add SBC-FITPC2 watchdog driver
  • Loading branch information
Linus Torvalds committed Sep 18, 2009
2 parents 81ce31b + e04ab95 commit afa12e7
Show file tree
Hide file tree
Showing 14 changed files with 1,293 additions and 73 deletions.
38 changes: 38 additions & 0 deletions drivers/watchdog/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,13 @@ config SOFT_WATCHDOG
To compile this driver as a module, choose M here: the
module will be called softdog.

config WM831X_WATCHDOG
tristate "WM831x watchdog"
depends on MFD_WM831X
help
Support for the watchdog in the WM831x AudioPlus PMICs. When
the watchdog triggers the system will be reset.

config WM8350_WATCHDOG
tristate "WM8350 watchdog"
depends on MFD_WM8350
Expand Down Expand Up @@ -266,6 +273,15 @@ config STMP3XXX_WATCHDOG
To compile this driver as a module, choose M here: the
module will be called stmp3xxx_wdt.

config NUC900_WATCHDOG
tristate "Nuvoton NUC900 watchdog"
depends on ARCH_W90X900
help
Say Y here if to include support for the watchdog timer
for the Nuvoton NUC900 series SoCs.
To compile this driver as a module, choose M here: the
module will be called nuc900_wdt.

# AVR32 Architecture

config AT32AP700X_WDT
Expand Down Expand Up @@ -369,6 +385,28 @@ config SC520_WDT
You can compile this driver directly into the kernel, or use
it as a module. The module will be called sc520_wdt.

config SBC_FITPC2_WATCHDOG
tristate "Compulab SBC-FITPC2 watchdog"
depends on X86
---help---
This is the driver for the built-in watchdog timer on the fit-PC2
Single-board computer made by Compulab.

It`s possible to enable watchdog timer either from BIOS (F2) or from booted Linux.
When "Watchdog Timer Value" enabled one can set 31-255 s operational range.

Entering BIOS setup temporary disables watchdog operation regardless to current state,
so system will not be restarted while user in BIOS setup.

Once watchdog was enabled the system will be restarted every
"Watchdog Timer Value" period, so to prevent it user can restart or
disable the watchdog.

To compile this driver as a module, choose M here: the
module will be called sbc_fitpc2_wdt.

Most people will say N.

config EUROTECH_WDT
tristate "Eurotech CPU-1220/1410 Watchdog Timer"
depends on X86
Expand Down
3 changes: 3 additions & 0 deletions drivers/watchdog/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ obj-$(CONFIG_DAVINCI_WATCHDOG) += davinci_wdt.o
obj-$(CONFIG_ORION_WATCHDOG) += orion_wdt.o
obj-$(CONFIG_COH901327_WATCHDOG) += coh901327_wdt.o
obj-$(CONFIG_STMP3XXX_WATCHDOG) += stmp3xxx_wdt.o
obj-$(CONFIG_NUC900_WATCHDOG) += nuc900_wdt.o

# AVR32 Architecture
obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o
Expand All @@ -64,6 +65,7 @@ obj-$(CONFIG_ALIM1535_WDT) += alim1535_wdt.o
obj-$(CONFIG_ALIM7101_WDT) += alim7101_wdt.o
obj-$(CONFIG_GEODE_WDT) += geodewdt.o
obj-$(CONFIG_SC520_WDT) += sc520_wdt.o
obj-$(CONFIG_SBC_FITPC2_WATCHDOG) += sbc_fitpc2_wdt.o
obj-$(CONFIG_EUROTECH_WDT) += eurotechwdt.o
obj-$(CONFIG_IB700_WDT) += ib700wdt.o
obj-$(CONFIG_IBMASR) += ibmasr.o
Expand Down Expand Up @@ -139,5 +141,6 @@ obj-$(CONFIG_WATCHDOG_CP1XXX) += cpwd.o
# XTENSA Architecture

# Architecture Independant
obj-$(CONFIG_WM831X_WATCHDOG) += wm831x_wdt.o
obj-$(CONFIG_WM8350_WATCHDOG) += wm8350_wdt.o
obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o
107 changes: 54 additions & 53 deletions drivers/watchdog/ar7_wdt.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,8 @@
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/miscdevice.h>
#include <linux/platform_device.h>
#include <linux/watchdog.h>
#include <linux/notifier.h>
#include <linux/reboot.h>
#include <linux/fs.h>
#include <linux/ioport.h>
#include <linux/io.h>
Expand Down Expand Up @@ -76,24 +75,10 @@ static unsigned expect_close;
/* XXX currently fixed, allows max margin ~68.72 secs */
#define prescale_value 0xffff

/* Offset of the WDT registers */
static unsigned long ar7_regs_wdt;
/* Resource of the WDT registers */
static struct resource *ar7_regs_wdt;
/* Pointer to the remapped WDT IO space */
static struct ar7_wdt *ar7_wdt;
static void ar7_wdt_get_regs(void)
{
u16 chip_id = ar7_chip_id();
switch (chip_id) {
case AR7_CHIP_7100:
case AR7_CHIP_7200:
ar7_regs_wdt = AR7_REGS_WDT;
break;
default:
ar7_regs_wdt = UR8_REGS_WDT;
break;
}
}


static void ar7_wdt_kick(u32 value)
{
Expand Down Expand Up @@ -202,20 +187,6 @@ static int ar7_wdt_release(struct inode *inode, struct file *file)
return 0;
}

static int ar7_wdt_notify_sys(struct notifier_block *this,
unsigned long code, void *unused)
{
if (code == SYS_HALT || code == SYS_POWER_OFF)
if (!nowayout)
ar7_wdt_disable_wdt();

return NOTIFY_DONE;
}

static struct notifier_block ar7_wdt_notifier = {
.notifier_call = ar7_wdt_notify_sys,
};

static ssize_t ar7_wdt_write(struct file *file, const char *data,
size_t len, loff_t *ppos)
{
Expand Down Expand Up @@ -299,56 +270,86 @@ static struct miscdevice ar7_wdt_miscdev = {
.fops = &ar7_wdt_fops,
};

static int __init ar7_wdt_init(void)
static int __devinit ar7_wdt_probe(struct platform_device *pdev)
{
int rc;

spin_lock_init(&wdt_lock);

ar7_wdt_get_regs();
ar7_regs_wdt =
platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs");
if (!ar7_regs_wdt) {
printk(KERN_ERR DRVNAME ": could not get registers resource\n");
rc = -ENODEV;
goto out;
}

if (!request_mem_region(ar7_regs_wdt, sizeof(struct ar7_wdt),
LONGNAME)) {
if (!request_mem_region(ar7_regs_wdt->start,
resource_size(ar7_regs_wdt), LONGNAME)) {
printk(KERN_WARNING DRVNAME ": watchdog I/O region busy\n");
return -EBUSY;
rc = -EBUSY;
goto out;
}

ar7_wdt = (struct ar7_wdt *)
ioremap(ar7_regs_wdt, sizeof(struct ar7_wdt));
ar7_wdt = ioremap(ar7_regs_wdt->start, resource_size(ar7_regs_wdt));
if (!ar7_wdt) {
printk(KERN_ERR DRVNAME ": could not ioremap registers\n");
rc = -ENXIO;
goto out_mem_region;
}

ar7_wdt_disable_wdt();
ar7_wdt_prescale(prescale_value);
ar7_wdt_update_margin(margin);

rc = register_reboot_notifier(&ar7_wdt_notifier);
if (rc) {
printk(KERN_ERR DRVNAME
": unable to register reboot notifier\n");
goto out_alloc;
}

rc = misc_register(&ar7_wdt_miscdev);
if (rc) {
printk(KERN_ERR DRVNAME ": unable to register misc device\n");
goto out_register;
goto out_alloc;
}
goto out;

out_register:
unregister_reboot_notifier(&ar7_wdt_notifier);
out_alloc:
iounmap(ar7_wdt);
release_mem_region(ar7_regs_wdt, sizeof(struct ar7_wdt));
out_mem_region:
release_mem_region(ar7_regs_wdt->start, resource_size(ar7_regs_wdt));
out:
return rc;
}

static void __exit ar7_wdt_cleanup(void)
static int __devexit ar7_wdt_remove(struct platform_device *pdev)
{
misc_deregister(&ar7_wdt_miscdev);
unregister_reboot_notifier(&ar7_wdt_notifier);
iounmap(ar7_wdt);
release_mem_region(ar7_regs_wdt, sizeof(struct ar7_wdt));
release_mem_region(ar7_regs_wdt->start, resource_size(ar7_regs_wdt));

return 0;
}

static void ar7_wdt_shutdown(struct platform_device *pdev)
{
if (!nowayout)
ar7_wdt_disable_wdt();
}

static struct platform_driver ar7_wdt_driver = {
.probe = ar7_wdt_probe,
.remove = __devexit_p(ar7_wdt_remove),
.shutdown = ar7_wdt_shutdown,
.driver = {
.owner = THIS_MODULE,
.name = "ar7_wdt",
},
};

static int __init ar7_wdt_init(void)
{
return platform_driver_register(&ar7_wdt_driver);
}

static void __exit ar7_wdt_cleanup(void)
{
platform_driver_unregister(&ar7_wdt_driver);
}

module_init(ar7_wdt_init);
Expand Down
57 changes: 53 additions & 4 deletions drivers/watchdog/booke_wdt.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@

#include <asm/reg_booke.h>
#include <asm/system.h>
#include <asm/time.h>
#include <asm/div64.h>

/* If the kernel parameter wdt=1, the watchdog will be enabled at boot.
* Also, the wdt_period sets the watchdog timer period timeout.
Expand All @@ -32,7 +34,7 @@
*/

#ifdef CONFIG_FSL_BOOKE
#define WDT_PERIOD_DEFAULT 63 /* Ex. wdt_period=28 bus=333Mhz,reset=~40sec */
#define WDT_PERIOD_DEFAULT 38 /* Ex. wdt_period=28 bus=333Mhz,reset=~40sec */
#else
#define WDT_PERIOD_DEFAULT 3 /* Refer to the PPC40x and PPC4xx manuals */
#endif /* for timing information */
Expand All @@ -41,7 +43,7 @@ u32 booke_wdt_enabled;
u32 booke_wdt_period = WDT_PERIOD_DEFAULT;

#ifdef CONFIG_FSL_BOOKE
#define WDTP(x) ((((63-x)&0x3)<<30)|(((63-x)&0x3c)<<15))
#define WDTP(x) ((((x)&0x3)<<30)|(((x)&0x3c)<<15))
#define WDTP_MASK (WDTP(0))
#else
#define WDTP(x) (TCR_WP(x))
Expand All @@ -50,6 +52,45 @@ u32 booke_wdt_period = WDT_PERIOD_DEFAULT;

static DEFINE_SPINLOCK(booke_wdt_lock);

/* For the specified period, determine the number of seconds
* corresponding to the reset time. There will be a watchdog
* exception at approximately 3/5 of this time.
*
* The formula to calculate this is given by:
* 2.5 * (2^(63-period+1)) / timebase_freq
*
* In order to simplify things, we assume that period is
* at least 1. This will still result in a very long timeout.
*/
static unsigned long long period_to_sec(unsigned int period)
{
unsigned long long tmp = 1ULL << (64 - period);
unsigned long tmp2 = ppc_tb_freq;

/* tmp may be a very large number and we don't want to overflow,
* so divide the timebase freq instead of multiplying tmp
*/
tmp2 = tmp2 / 5 * 2;

do_div(tmp, tmp2);
return tmp;
}

/*
* This procedure will find the highest period which will give a timeout
* greater than the one required. e.g. for a bus speed of 66666666 and
* and a parameter of 2 secs, then this procedure will return a value of 38.
*/
static unsigned int sec_to_period(unsigned int secs)
{
unsigned int period;
for (period = 63; period > 0; period--) {
if (period_to_sec(period) >= secs)
return period;
}
return 0;
}

static void __booke_wdt_ping(void *data)
{
mtspr(SPRN_TSR, TSR_ENW|TSR_WIS);
Expand Down Expand Up @@ -93,7 +134,7 @@ static long booke_wdt_ioctl(struct file *file,

switch (cmd) {
case WDIOC_GETSUPPORT:
if (copy_to_user(arg, &ident, sizeof(struct watchdog_info)))
if (copy_to_user((void *)arg, &ident, sizeof(ident)))
return -EFAULT;
case WDIOC_GETSTATUS:
return put_user(ident.options, p);
Expand All @@ -115,8 +156,16 @@ static long booke_wdt_ioctl(struct file *file,
booke_wdt_ping();
return 0;
case WDIOC_SETTIMEOUT:
if (get_user(booke_wdt_period, p))
if (get_user(tmp, p))
return -EFAULT;
#ifdef CONFIG_FSL_BOOKE
/* period of 1 gives the largest possible timeout */
if (tmp > period_to_sec(1))
return -EINVAL;
booke_wdt_period = sec_to_period(tmp);
#else
booke_wdt_period = tmp;
#endif
mtspr(SPRN_TCR, (mfspr(SPRN_TCR) & ~WDTP_MASK) |
WDTP(booke_wdt_period));
return 0;
Expand Down
2 changes: 1 addition & 1 deletion drivers/watchdog/coh901327_wdt.c
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ static void coh901327_enable(u16 timeout)
* Wait 3 32 kHz cycles for it to take effect
*/
freq = clk_get_rate(clk);
delay_ns = (1000000000 + freq - 1) / freq; /* Freq to ns and round up */
delay_ns = DIV_ROUND_UP(1000000000, freq); /* Freq to ns and round up */
delay_ns = 3 * delay_ns; /* Wait 3 cycles */
ndelay(delay_ns);
/* Enable the watchdog interrupt */
Expand Down
Loading

0 comments on commit afa12e7

Please sign in to comment.