diff options
Diffstat (limited to 'packages/linux/linux-2.6.22.6/ts72xx/ts72xx-watchdog.patch')
-rw-r--r-- | packages/linux/linux-2.6.22.6/ts72xx/ts72xx-watchdog.patch | 430 |
1 files changed, 430 insertions, 0 deletions
diff --git a/packages/linux/linux-2.6.22.6/ts72xx/ts72xx-watchdog.patch b/packages/linux/linux-2.6.22.6/ts72xx/ts72xx-watchdog.patch new file mode 100644 index 0000000000..aa2cb834f9 --- /dev/null +++ b/packages/linux/linux-2.6.22.6/ts72xx/ts72xx-watchdog.patch @@ -0,0 +1,430 @@ + +TS-72xx watchdog driver + +Signed-off-by: Matthieu Crapet <mcrapet@gmail.com> + +Index: linux-2.6.22/arch/arm/mach-ep93xx/ts72xx.c +=================================================================== +--- linux-2.6.22.orig/arch/arm/mach-ep93xx/ts72xx.c 2007-08-30 01:33:00.000000000 +0200 ++++ linux-2.6.22/arch/arm/mach-ep93xx/ts72xx.c 2007-08-30 01:33:10.000000000 +0200 +@@ -183,6 +183,26 @@ + .resource = ts72xx_eth_resource, + }; + ++static struct resource ts72xx_watchdog_resources[] = { ++ [0] = { ++ .start = TS72XX_WATCHDOG_CONTROL_PHYS_BASE, ++ .end = TS72XX_WATCHDOG_CONTROL_PHYS_BASE + 0x0fff, ++ .flags = IORESOURCE_MEM, ++ }, ++ [1] = { ++ .start = TS72XX_WATCHDOG_FEED_PHYS_BASE, ++ .end = TS72XX_WATCHDOG_FEED_PHYS_BASE + 0x0fff, ++ .flags = IORESOURCE_MEM, ++ }, ++}; ++ ++static struct platform_device ts72xx_watchdog_device = { ++ .name = "ts72xx_wdt", ++ .id = -1, ++ .num_resources = ARRAY_SIZE(ts72xx_watchdog_resources), ++ .resource = ts72xx_watchdog_resources, ++}; ++ + static void __init ts72xx_init_machine(void) + { + ep93xx_init_devices(); +@@ -193,6 +213,7 @@ + memcpy(ts72xx_eth_data.dev_addr, + (void *)(EP93XX_ETHERNET_BASE + 0x50), 6); + platform_device_register(&ts72xx_eth_device); ++ platform_device_register(&ts72xx_watchdog_device); + } + + MACHINE_START(TS72XX, "Technologic Systems TS-72xx SBC") +Index: linux-2.6.22/drivers/char/watchdog/Kconfig +=================================================================== +--- linux-2.6.22.orig/drivers/char/watchdog/Kconfig 2007-08-30 01:33:00.000000000 +0200 ++++ linux-2.6.22/drivers/char/watchdog/Kconfig 2007-08-30 01:33:10.000000000 +0200 +@@ -187,6 +187,18 @@ + + Say N if you are unsure. + ++config TS72XX_WATCHDOG ++ tristate "TS-72xx Watchdog" ++ depends on WATCHDOG && ARCH_EP93XX && MACH_TS72XX ++ help ++ Say Y here if to include support for the CPLD watchdog ++ included on Technologic Systems SBC. ++ ++ NOTE: timeout value is given in milliseconds, not in seconds. ++ ++ To compile this driver as a module, choose M here: the ++ module will be called ts72xx_wdt. ++ + # X86 (i386 + ia64 + x86_64) Architecture + + config ACQUIRE_WDT +Index: linux-2.6.22/drivers/char/watchdog/Makefile +=================================================================== +--- linux-2.6.22.orig/drivers/char/watchdog/Makefile 2007-08-30 01:33:00.000000000 +0200 ++++ linux-2.6.22/drivers/char/watchdog/Makefile 2007-08-30 01:33:10.000000000 +0200 +@@ -34,6 +34,7 @@ + obj-$(CONFIG_SA1100_WATCHDOG) += sa1100_wdt.o + obj-$(CONFIG_MPCORE_WATCHDOG) += mpcore_wdt.o + obj-$(CONFIG_EP93XX_WATCHDOG) += ep93xx_wdt.o ++obj-$(CONFIG_TS72XX_WATCHDOG) += ts72xx_wdt.o + obj-$(CONFIG_PNX4008_WATCHDOG) += pnx4008_wdt.o + + # X86 (i386 + ia64 + x86_64) Architecture +Index: linux-2.6.22/drivers/char/watchdog/ts72xx_wdt.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ linux-2.6.22/drivers/char/watchdog/ts72xx_wdt.c 2007-08-30 01:33:10.000000000 +0200 +@@ -0,0 +1,332 @@ ++/* ++ * TS-72xx Watchdog Driver for Technologic Systems boards. ++ * ++ * Based on ep93xx_wdt.c by Lehtiniemi <rayl@mail.com> & ++ * Alessandro Zummo <a.zummo@towertech.it> ++ * and ib700wdt.c by Charles Howes <chowes@vsol.net> ++ * and mpc83xx_wdt.c by Dave Updegraff <dave@cray.org> & ++ * Kumar Gala <galak@kernel.crashing.org> ++ * ++ * (c) Copyright 2006 Matthieu Crapet <mcrapet@gmail.com> ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version ++ * 2 of the License, or (at your option) any later version. ++ * ++ * This driver only deals with native timeout provided by CPLD : ++ * 1/4s, 1/2s, 1s, 2s, 4s and 8s. No external timer is used. ++ * Notice that we must ping before modifying the control register. ++ */ ++ ++#include <linux/module.h> ++#include <linux/moduleparam.h> ++#include <linux/types.h> ++#include <linux/kernel.h> ++#include <linux/fs.h> ++#include <linux/miscdevice.h> ++#include <linux/platform_device.h> ++#include <linux/init.h> ++#include <linux/watchdog.h> ++#include <asm/io.h> ++#include <asm/uaccess.h> ++#include <asm/system.h> ++#include <asm/mach-types.h> ++ ++#define WATCHDOG_VERSION "0.2" ++#define PFX "ts72xx_wdt: " ++ ++#define WATCHDOG_TIMEOUT 8000 /* 8 seconds */ ++#define WDT_IN_USE 0 ++#define WDT_OK_TO_CLOSE 1 ++ ++static unsigned long ts72xx_wdt_status; ++static unsigned char ts72xx_wdt_cpld_value = 0x7; ++static int nowayout = WATCHDOG_NOWAYOUT; ++static int timeout = WATCHDOG_TIMEOUT; ++ ++static int ts72xx_wdt_times[12] = { ++ 6000, 3000, 1500, 750, 275, 0, ++ 8000, 4000, 2000, 1000, 500, 250 ++}; ++ ++static void __iomem *control_register; ++static void __iomem *feed_register; ++ ++ ++/* ++ * Kernel methods. ++ */ ++ ++static inline void ts72xx_wdt_ping(void) ++{ ++ __raw_writew(0x05, feed_register); ++} ++ ++static inline void ts72xx_wdt_enable(void) ++{ ++ __raw_writew(0x05, feed_register); ++ __raw_writew(ts72xx_wdt_cpld_value, control_register); ++} ++ ++static inline void ts72xx_wdt_disable(void) ++{ ++ __raw_writew(0x05, feed_register); ++ __raw_writew(0, control_register); ++} ++ ++static inline void ts72xx_parse_timeout(int value) ++{ ++ unsigned char cpld_value = 0x7; ++ int i; ++ ++ if ((value > 8000) || (value < 250)) { ++ timeout = WATCHDOG_TIMEOUT; ++ printk(KERN_INFO PFX "Timeout value out of range, set to %d\n", timeout); ++ } else { ++ for (i = 0; i < 6; i++) { ++ if (value >= ts72xx_wdt_times[i]) { ++ timeout = ts72xx_wdt_times[i+6]; ++ ++ if (value != timeout) ++ printk(KERN_INFO PFX "Timeout value rounded to %d\n", timeout); ++ ++ if (i >= 3) /* cpld_value can't be 4 */ ++ i++; ++ ++ cpld_value = 7 - i; ++ break; ++ } ++ } ++ } ++ ++ ts72xx_wdt_cpld_value = cpld_value; ++} ++ ++static ssize_t ts72xx_wdt_write(struct file *file, const char __user *buf, ++ size_t count, loff_t *ppos) ++{ ++ /* Can't seek (pwrite) on this device */ ++ if (*ppos != file->f_pos) ++ return -ESPIPE; ++ ++ if (count) { ++ if (!nowayout) { ++ size_t i; ++ ++ clear_bit(WDT_OK_TO_CLOSE, &ts72xx_wdt_status); ++ ++ for (i = 0; i != count; i++) { ++ char c; ++ ++ if (get_user(c, buf + i)) ++ return -EFAULT; ++ ++ if (c == 'V') ++ set_bit(WDT_OK_TO_CLOSE, &ts72xx_wdt_status); ++ else ++ clear_bit(WDT_OK_TO_CLOSE, &ts72xx_wdt_status); ++ } ++ } ++ ts72xx_wdt_ping(); ++ } ++ ++ return count; ++} ++ ++static int ts72xx_wdt_ioctl(struct inode *inode, struct file *file, ++ unsigned int cmd, unsigned long arg) ++{ ++ int new_margin; ++ int ret = -ENOIOCTLCMD; ++ ++ static struct watchdog_info ident = { ++ .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, ++ .firmware_version = 1, ++ .identity = "TS-72xx Watchdog", ++ }; ++ ++ switch (cmd) { ++ case WDIOC_GETSUPPORT: ++ ret = copy_to_user((struct watchdog_info __user *)arg, &ident, ++ sizeof(ident)) ? -EFAULT : 0; ++ break; ++ ++ case WDIOC_GETSTATUS: ++ case WDIOC_GETBOOTSTATUS: ++ ret = put_user(0, (int __user *)arg); ++ break; ++ ++ case WDIOC_KEEPALIVE: ++ ts72xx_wdt_ping(); ++ ret = 0; ++ break; ++ ++ case WDIOC_SETTIMEOUT: ++ if (get_user(new_margin, (int __user *)arg)) ++ return -EFAULT; ++ ++ ts72xx_parse_timeout(new_margin); ++ ts72xx_wdt_enable(); ++ /* Fall */ ++ ++ case WDIOC_GETTIMEOUT: ++ ret = put_user(timeout, (int __user *)arg); ++ break; ++ } ++ ++ return ret; ++} ++ ++static int ts72xx_wdt_open(struct inode *inode, struct file *file) ++{ ++ if (test_and_set_bit(WDT_IN_USE, &ts72xx_wdt_status)) ++ return -EBUSY; ++ ++ if (nowayout) { ++ __module_get(THIS_MODULE); ++ } ++ ++ ts72xx_wdt_enable(); ++ ts72xx_wdt_ping(); ++ ++ return nonseekable_open(inode, file); ++} ++ ++static int ts72xx_wdt_close(struct inode *inode, struct file *file) ++{ ++ if (test_bit(WDT_OK_TO_CLOSE, &ts72xx_wdt_status)) ++ ts72xx_wdt_disable(); ++ else ++ printk(KERN_CRIT PFX "Device file closed unexpectedly. " ++ "Will not stop the WDT!\n"); ++ ++ clear_bit(WDT_IN_USE, &ts72xx_wdt_status); ++ ++ return 0; ++} ++ ++/* ++ * Kernel Interfaces ++ */ ++ ++static struct file_operations ts72xx_wdt_fops = { ++ .owner = THIS_MODULE, ++ .llseek = no_llseek, ++ .write = ts72xx_wdt_write, ++ .ioctl = ts72xx_wdt_ioctl, ++ .open = ts72xx_wdt_open, ++ .release = ts72xx_wdt_close, ++}; ++ ++static struct miscdevice ts72xx_wdt_miscdev = { ++ .minor = WATCHDOG_MINOR, ++ .name = "watchdog", ++ .fops = &ts72xx_wdt_fops, ++}; ++ ++static void ts72xx_wdt_shutdown(struct platform_device *dev) ++{ ++ ts72xx_wdt_disable(); ++} ++ ++static int __devinit ts72xx_wdt_probe(struct platform_device *dev) ++{ ++ struct resource *r; ++ int ret; ++ ++ if (!machine_is_ts72xx()) ++ return -ENODEV; ++ ++ r = platform_get_resource(dev, IORESOURCE_MEM, 0); ++ ++ if (!r) { ++ ret = -ENODEV; ++ goto err_out; ++ } ++ ++ control_register = ioremap(r->start, r->end - r->start + 1); ++ ++ if (control_register == NULL) { ++ ret = -ENOMEM; ++ goto err_out; ++ } ++ ++ r = platform_get_resource(dev, IORESOURCE_MEM, 1); ++ ++ if (!r) { ++ ret = -ENODEV; ++ goto err_unmap1; ++ } ++ ++ feed_register = ioremap(r->start, r->end - r->start + 1); ++ ++ if (feed_register == NULL) { ++ ret = -ENOMEM; ++ goto err_unmap1; ++ } ++ ++ ret = misc_register(&ts72xx_wdt_miscdev); ++ if (ret) { ++ printk(KERN_ERR PFX "cannot register miscdev on minor=%d " ++ "(err=%d), ep93xx_watchdog already loaded?!\n", WATCHDOG_MINOR, ret); ++ goto err_unmap2; ++ } ++ ++ printk(KERN_INFO PFX "TS-72xx watchdog driver, v%s\n", WATCHDOG_VERSION); ++ ts72xx_parse_timeout(timeout); ++ ++ return 0; ++ ++err_unmap2: ++ iounmap(feed_register); ++err_unmap1: ++ iounmap(control_register); ++err_out: ++ return ret; ++} ++ ++static int __devexit ts72xx_wdt_remove(struct platform_device *dev) ++{ ++ misc_deregister(&ts72xx_wdt_miscdev); ++ iounmap(feed_register); ++ iounmap(control_register); ++ ++ return 0; ++} ++ ++static struct platform_driver ts72xx_wdt_driver = { ++ .probe = ts72xx_wdt_probe, ++ .remove = __devexit_p(ts72xx_wdt_remove), ++ .shutdown = ts72xx_wdt_shutdown, ++ .driver = { ++ .owner = THIS_MODULE, ++ .name = "ts72xx_wdt", ++ }, ++}; ++ ++static int __init ts72xx_wdt_init(void) ++{ ++ return platform_driver_register(&ts72xx_wdt_driver); ++} ++ ++static void __exit ts72xx_wdt_exit(void) ++{ ++ platform_driver_unregister(&ts72xx_wdt_driver); ++} ++ ++module_init(ts72xx_wdt_init); ++module_exit(ts72xx_wdt_exit); ++ ++#ifdef CONFIG_WATCHDOG_NOWAYOUT ++module_param(nowayout, int, 0); ++MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); ++#endif ++ ++module_param(timeout, int, 0); ++MODULE_PARM_DESC(timeout,"Watchdog timeout in milliseconds (250..8000, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ")"); ++ ++MODULE_AUTHOR("Matthieu Crapet <mcrapet@gmail.com>"); ++MODULE_DESCRIPTION("TS-72xx watchdog driver"); ++MODULE_LICENSE("GPL"); ++MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); +Index: linux-2.6.22/include/asm-arm/arch-ep93xx/ts72xx.h +=================================================================== +--- linux-2.6.22.orig/include/asm-arm/arch-ep93xx/ts72xx.h 2007-08-30 01:33:25.000000000 +0200 ++++ linux-2.6.22/include/asm-arm/arch-ep93xx/ts72xx.h 2007-08-30 01:34:14.000000000 +0200 +@@ -68,6 +68,9 @@ + #define TS72XX_RTC_DATA_PHYS_BASE 0x11700000 + #define TS72XX_RTC_DATA_SIZE 0x00001000 + ++#define TS72XX_WATCHDOG_CONTROL_PHYS_BASE 0x23800000 ++#define TS72XX_WATCHDOG_FEED_PHYS_BASE 0x23c00000 ++ + #ifndef __ASSEMBLY__ + #include <asm/io.h> + |