Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit afa12e72 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* 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
parents 81ce31b7 e04ab958
Loading
Loading
Loading
Loading
+38 −0
Original line number Diff line number Diff line
@@ -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
@@ -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
@@ -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
+3 −0
Original line number Diff line number Diff line
@@ -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
@@ -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
@@ -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
+54 −53
Original line number Diff line number Diff line
@@ -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>
@@ -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)
{
@@ -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)
{
@@ -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);
+53 −4
Original line number Diff line number Diff line
@@ -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.
@@ -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 */
@@ -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))
@@ -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);
@@ -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);
@@ -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;
+1 −1
Original line number Diff line number Diff line
@@ -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 */
Loading