diff options
| author | kaloz <kaloz@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2008-06-05 17:14:02 +0000 | 
|---|---|---|
| committer | kaloz <kaloz@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2008-06-05 17:14:02 +0000 | 
| commit | d57e4d97e77506e9f634eabe6412c57d81ce0bd4 (patch) | |
| tree | 6f38cfee0e5539197d6de60dbe72192ab5b518f8 /target/linux/storm/patches/009-watchdog.patch | |
| parent | f4fb68ce2cd61529703f4244c3126e47ce0cfec4 (diff) | |
rename and renumber storm patches
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@11368 3c298f89-4303-0410-b956-a3cf2f4a3e73
Diffstat (limited to 'target/linux/storm/patches/009-watchdog.patch')
| -rw-r--r-- | target/linux/storm/patches/009-watchdog.patch | 398 | 
1 files changed, 398 insertions, 0 deletions
diff --git a/target/linux/storm/patches/009-watchdog.patch b/target/linux/storm/patches/009-watchdog.patch new file mode 100644 index 000000000..3055a9482 --- /dev/null +++ b/target/linux/storm/patches/009-watchdog.patch @@ -0,0 +1,398 @@ +--- a/arch/arm/mach-sl2312/sl3516_device.c ++++ b/arch/arm/mach-sl2312/sl3516_device.c +@@ -76,9 +76,30 @@ + 	.resource       = sl3516_sata0_resources, + }; +  ++static struct resource sl351x_wdt_resources[] = { ++	[0] = { ++		.start  = SL2312_WAQTCHDOG_BASE + 0x00, ++		.end    = SL2312_WAQTCHDOG_BASE + 0x1C, ++		.flags  = IORESOURCE_MEM, ++	}, ++	[1] = { ++		.start  = IRQ_WATCHDOG, ++		.end    = IRQ_WATCHDOG, ++		.flags  = IORESOURCE_IRQ, ++	}, ++}; ++ ++static struct platform_device sl351x_wdt = { ++	.name		= "sl351x-wdt", ++	.id		= -1, ++	.resource	= sl351x_wdt_resources, ++	.num_resources	= ARRAY_SIZE(sl351x_wdt_resources), ++}; ++ + static struct platform_device *sata_devices[] __initdata = { + 	&sata_device, + 	&sata0_device, ++	&sl351x_wdt, + }; +  + static int __init sl3516_init(void) +--- a/drivers/char/watchdog/Kconfig ++++ b/drivers/char/watchdog/Kconfig +@@ -171,6 +171,17 @@ + 	  To compile this driver as a module, choose M here: the + 	  module will be called ep93xx_wdt. +  ++config WATCHDOG_SL351X ++	tristate "SL351x Watchdog" ++	depends on WATCHDOG && ARCH_SL2312 ++	help ++	  This driver adds watchdog support for the integrated watchdog in the ++	  SL351x processors (Farraday core). If you have one of these processors ++	  and wish to have watchdog support enabled, say Y, otherwise say N. ++ ++	  To compile this driver as a module, choose M here: the ++	  module will be called sl351x_wdt. ++ + config OMAP_WATCHDOG + 	tristate "OMAP Watchdog" + 	depends on ARCH_OMAP16XX || ARCH_OMAP24XX +--- a/drivers/char/watchdog/Makefile ++++ b/drivers/char/watchdog/Makefile +@@ -36,6 +36,7 @@ + obj-$(CONFIG_SA1100_WATCHDOG) += sa1100_wdt.o + obj-$(CONFIG_MPCORE_WATCHDOG) += mpcore_wdt.o + obj-$(CONFIG_EP93XX_WATCHDOG) += ep93xx_wdt.o ++obj-$(CONFIG_WATCHDOG_SL351X) += sl351x_wdt.o + obj-$(CONFIG_PNX4008_WATCHDOG) += pnx4008_wdt.o + obj-$(CONFIG_IOP_WATCHDOG) += iop_wdt.o + obj-$(CONFIG_DAVINCI_WATCHDOG) += davinci_wdt.o +--- /dev/null ++++ b/drivers/char/watchdog/sl351x_wdt.c +@@ -0,0 +1,332 @@ ++#include <linux/module.h> ++#include <linux/types.h> ++#include <linux/fs.h> ++#include <linux/mm.h> ++#include <linux/errno.h> ++#include <linux/init.h> ++#include <linux/miscdevice.h> ++#include <linux/watchdog.h> ++#include <linux/platform_device.h> ++#include <asm/uaccess.h> ++#include <asm/arch/sl2312.h> ++#include <asm/arch/hardware.h> ++#include <asm/arch/irqs.h> ++#include <asm/arch/watchdog.h> ++#include <asm/io.h> ++#include <linux/interrupt.h> ++ ++#define WATCHDOG_TEST 1 ++#define PFX "sl351x-wdt: " ++ ++#define _WATCHDOG_COUNTER  0x00 ++#define _WATCHDOG_LOAD     0x04 ++#define _WATCHDOG_RESTART  0x08 ++#define _WATCHDOG_CR       0x0C ++#define _WATCHDOG_STATUS   0x10 ++#define _WATCHDOG_CLEAR    0x14 ++#define _WATCHDOG_INTRLEN  0x18 ++ ++static struct resource  *wdt_mem; ++static struct resource  *wdt_irq; ++static void __iomem     *wdt_base; ++static int 		wdt_margin = WATCHDOG_TIMEOUT_MARGIN;	/* in range of 0 .. 60s */ ++ ++static int open_state = WATCHDOG_DRIVER_CLOSE; ++static int wd_expire = 0; ++ ++static void watchdog_enable(void) ++{ ++	unsigned long wdcr; ++ ++	wdcr = readl(wdt_base + _WATCHDOG_CR); ++	wdcr |= (WATCHDOG_WDENABLE_MSK|WATCHDOG_WDRST_MSK); ++#ifdef WATCHDOG_TEST ++	wdcr |= WATCHDOG_WDINTR_MSK; ++//	wdcr &= ~WATCHDOG_WDRST_MSK; ++#endif ++	wdcr &= ~WATCHDOG_WDCLOCK_MSK; ++	writel(wdcr, wdt_base + _WATCHDOG_CR); ++} ++ ++static void watchdog_set_timeout(unsigned long timeout) ++{ ++	timeout = WATCHDOG_TIMEOUT_SCALE * timeout; ++	writel(timeout, wdt_base + _WATCHDOG_LOAD); ++	writel(WATCHDOG_RESTART_VALUE, wdt_base + _WATCHDOG_RESTART); ++} ++ ++static void watchdog_keepalive(void) ++{ ++	writel(WATCHDOG_RESTART_VALUE, wdt_base + _WATCHDOG_RESTART); ++} ++ ++static void watchdog_disable(void) ++{ ++	unsigned long wdcr; ++ ++	wdcr = readl(wdt_base + _WATCHDOG_CR); ++	wdcr &= ~WATCHDOG_WDENABLE_MSK; ++	writel(wdcr, wdt_base + _WATCHDOG_CR); ++} ++ ++ ++#ifdef WATCHDOG_TEST ++static irqreturn_t watchdog_irq(int irq, void *dev_id, struct pt_regs *regs) ++{ ++	unsigned int clear; ++ ++	writel(WATCHDOG_CLEAR_STATUS, wdt_base + _WATCHDOG_CLEAR); ++	printk(KERN_INFO PFX "Watchdog timeout, resetting system...\n"); ++ ++	clear = __raw_readl(IO_ADDRESS(SL2312_INTERRUPT_BASE)+0x0C); ++	clear &= 0x01; ++	__raw_writel(clear,IO_ADDRESS(SL2312_INTERRUPT_BASE)+0x08); ++	wd_expire = 1; ++	return IRQ_HANDLED; ++} ++ ++#endif ++ ++#define OPTIONS WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE ++static struct watchdog_info sl351x_wdt_ident = { ++	.options          =     OPTIONS, ++	.firmware_version =     0, ++	.identity         =     "sl351x Watchdog", ++}; ++ ++struct file_operations watchdog_fops = { ++	.write		= watchdog_write, ++	.read		= watchdog_read, ++	.open		= watchdog_open, ++	.release	= watchdog_release, ++	.ioctl		= watchdog_ioctl, ++}; ++ ++static int watchdog_open(struct inode *inode, struct file *filp) ++{ ++	if (open_state == WATCHDOG_DRIVER_OPEN) ++		return -EBUSY; ++ ++	wd_expire = 0; ++ ++	watchdog_disable(); ++	watchdog_set_timeout(wdt_margin); ++	watchdog_enable(); ++ ++	printk(KERN_INFO PFX "watchog timer enabled, margin: %ds.\n", wdt_margin); ++	open_state = WATCHDOG_DRIVER_OPEN; ++ ++	return nonseekable_open(inode, filp); ++} ++ ++static int watchdog_release(struct inode *inode, struct file *filp) ++{ ++	watchdog_disable(); ++ ++	open_state = WATCHDOG_DRIVER_CLOSE; ++	wd_expire = 0; ++	printk(KERN_INFO PFX "watchog timer disabled, margin: %ds.\n", wdt_margin); ++ ++	return 0; ++} ++ ++static ssize_t watchdog_read(struct file *filp, char *buf, size_t count, loff_t *off) ++{ ++	int i; ++	unsigned long val; ++ ++ ++	for(i=0;i< count;i++) ++	{ ++		if ((i%4)==0) ++			val = *((unsigned long *)WATCHDOG_COUNTER); ++		buf[i] = (val & 0xFF); ++		val >>= 8; ++	} ++	return count; ++} ++ ++static ssize_t watchdog_write(struct file *filp, const char *buf, size_t len, loff_t *off) ++{ ++	/*  Refresh the timer. */ ++	if (len) { ++		watchdog_keepalive(); ++	} ++	return len; ++ ++} ++ ++static int watchdog_ioctl(struct inode *inode, struct file *filp, ++			  unsigned int cmd, unsigned long arg) ++{ ++	void __user *argp = (void __user *)arg; ++	int margin; ++ ++	switch(cmd) ++	{ ++	case WDIOC_GETSUPPORT: ++		return copy_to_user(argp, &sl351x_wdt_ident, ++				    sizeof(sl351x_wdt_ident)) ? -EFAULT : 0; ++ ++	case WDIOC_GETSTATUS: ++	case WDIOC_GETBOOTSTATUS: ++		return put_user(0, (int __user*)argp); ++ ++	case WDIOC_KEEPALIVE: ++		watchdog_keepalive(); ++		return 0; ++ ++	case WDIOC_SETTIMEOUT: ++		if (get_user(margin, (int __user*)argp)) ++			return -EFAULT; ++ ++		/* Arbitrary, can't find the card's limits */ ++		if ((margin < 0) || (margin > 60)) ++			return -EINVAL; ++ ++		// watchdog_disable(); ++		wdt_margin = margin; ++		watchdog_set_timeout(margin); ++		watchdog_keepalive(); ++		// watchdog_enable(); ++ ++		/* Fall through */ ++ ++	case WDIOC_GETTIMEOUT: ++		return put_user(wdt_margin, (int *)arg); ++ ++	default: ++		return -ENOIOCTLCMD; ++	} ++} ++ ++static struct miscdevice wd_dev= { ++	WATCHDOG_MINOR, ++	"watchdog", ++	&watchdog_fops ++}; ++ ++static char banner[] __initdata = KERN_INFO "SL351x Watchdog Timer, (c) 2007 WILIBOX\n"; ++ ++static int sl351x_wdt_probe(struct platform_device *pdev) ++{ ++	struct resource *res; ++	int ret, size; ++	unsigned long wdcr; ++ ++	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++	if (res == NULL) { ++		printk(KERN_INFO PFX "failed to get memory region resouce\n"); ++		return -ENOMEM; ++	} ++ ++	size = (res->end-res->start)+1; ++ ++	wdt_mem = request_mem_region(res->start, size, pdev->name); ++	if (wdt_mem == NULL) { ++		printk(KERN_INFO PFX "failed to get memory region\n"); ++		return -ENOENT; ++	} ++ ++	wdt_base = ioremap(res->start, size); ++	if (wdt_base == NULL) { ++		printk(KERN_INFO PFX "failed to ioremap() region\n"); ++		return -EINVAL; ++	} ++ ++	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); ++	if (res == NULL) { ++		 printk(KERN_INFO PFX "failed to get irq resource\n"); ++		 return -ENOENT; ++	} ++ ++	wdt_irq = res; ++ ++	ret = request_irq(res->start, watchdog_irq, 0, pdev->name, pdev); ++	if (ret != 0) { ++		printk(KERN_INFO PFX "failed to install irq (%d)\n", ret); ++		return ret; ++	} ++ ++	wdcr = readl(wdt_base + _WATCHDOG_CR); ++	if (wdcr & WATCHDOG_WDENABLE_MSK) { ++		printk(KERN_INFO PFX "Found watchdog in enabled state, reseting ...\n"); ++		wdcr &= ~WATCHDOG_WDENABLE_MSK; ++		writel(wdcr, wdt_base + _WATCHDOG_CR); ++	} ++ ++	ret = misc_register(&wd_dev); ++ ++	return ret; ++} ++ ++static int sl351x_wdt_remove(struct platform_device *pdev) ++{ ++	if (wdt_base != NULL) { ++		iounmap(wdt_base); ++		wdt_base = NULL; ++	} ++ ++	if (wdt_irq != NULL) { ++		free_irq(wdt_irq->start, pdev); ++		release_resource(wdt_irq); ++		wdt_irq = NULL; ++	} ++ ++	if (wdt_mem != NULL) { ++		release_resource(wdt_mem); ++		wdt_mem = NULL; ++	} ++ ++	misc_deregister(&wd_dev); ++ ++	return 0; ++} ++ ++static void sl351x_wdt_shutdown(struct platform_device *dev) ++{ ++	watchdog_disable(); ++} ++ ++#ifdef CONFIG_PM ++static int sl351x_wdt_suspend(struct platform_device *dev, pm_message_t state) ++{ ++	watchdog_disable(); ++} ++ ++static int sl351x_wdt_resume(struct platform_device *dev) ++{ ++	watchdog_set_timeout(wdt_margin); ++	watchdog_enable(); ++} ++ ++#else ++#define sl351x_wdt_suspend	NULL ++#define sl351x_wdt_resume	NULL ++#endif ++ ++static struct platform_driver sl351x_wdt_driver = { ++	.probe          = sl351x_wdt_probe, ++	.remove         = sl351x_wdt_remove, ++	.shutdown       = sl351x_wdt_shutdown, ++	.suspend        = sl351x_wdt_suspend, ++	.resume         = sl351x_wdt_resume, ++	.driver         = { ++		.owner  = THIS_MODULE, ++		.name   = "sl351x-wdt", ++	}, ++}; ++ ++static int __init watchdog_init(void) ++{ ++	printk(banner); ++	return platform_driver_register(&sl351x_wdt_driver); ++} ++ ++static void __exit watchdog_exit(void) ++{ ++	platform_driver_unregister(&sl351x_wdt_driver); ++} ++ ++module_init(watchdog_init); ++module_exit(watchdog_exit);  | 
