diff -pNur --exclude=.svn bcm-3.12/kernel/linux/drivers/char/watchdog/Kconfig dev/kernel/linux/drivers/char/watchdog/Kconfig --- bcm-3.12/kernel/linux/drivers/char/watchdog/Kconfig 2004-08-06 02:33:25.000000000 +0200 +++ dev/kernel/linux/drivers/char/watchdog/Kconfig 2007-12-18 16:18:13.000000000 +0100 @@ -330,6 +330,15 @@ config INDYDOG timer expired and no process has written to /dev/watchdog during that time. +config NEUFBOX_WDT + tristate "NeufBox Hardware Watchdog" + depends on WATCHDOG && NEUFBOX_SPECIFIC_OPTIONS + help + Hardwaredriver for the Neufbox's watchdog. This is a + watchdog timer that will reboot the machine after a 40 second + timer expired and no process has written to /dev/watchdog during + that time. + # SUPERH Architecture config SH_WDT diff -pNur --exclude=.svn bcm-3.12/kernel/linux/drivers/char/watchdog/Makefile dev/kernel/linux/drivers/char/watchdog/Makefile --- bcm-3.12/kernel/linux/drivers/char/watchdog/Makefile 2004-08-06 02:33:25.000000000 +0200 +++ dev/kernel/linux/drivers/char/watchdog/Makefile 2007-11-21 12:53:06.000000000 +0100 @@ -7,6 +7,8 @@ # watchdog dies or is 'borrowed' for some reason the software watchdog # still gives you some cover. +EXTRA_CFLAGS := -I$(INC_BRCMDRIVER_PUB_PATH)/$(BRCM_BOARD) -I$(INC_BRCMSHARED_PUB_PATH)/$(BRCM_BOARD) + obj-$(CONFIG_PCWATCHDOG) += pcwd.o obj-$(CONFIG_ACQUIRE_WDT) += acquirewdt.o obj-$(CONFIG_ADVANTECH_WDT) += advantechwdt.o @@ -33,6 +35,7 @@ obj-$(CONFIG_SC1200_WDT) += sc1200wdt.o obj-$(CONFIG_WAFER_WDT) += wafer5823wdt.o obj-$(CONFIG_CPU5_WDT) += cpu5wdt.o obj-$(CONFIG_INDYDOG) += indydog.o +obj-$(CONFIG_NEUFBOX_WDT) += neufbox_wdt.o obj-$(CONFIG_PCIPCWATCHDOG) += pcwd_pci.o obj-$(CONFIG_USBPCWATCHDOG) += pcwd_usb.o obj-$(CONFIG_IXP4XX_WATCHDOG) += ixp4xx_wdt.o diff -pNur --exclude=.svn bcm-3.12/kernel/linux/drivers/char/watchdog/neufbox_wdt.c dev/kernel/linux/drivers/char/watchdog/neufbox_wdt.c --- bcm-3.12/kernel/linux/drivers/char/watchdog/neufbox_wdt.c 1970-01-01 01:00:00.000000000 +0100 +++ dev/kernel/linux/drivers/char/watchdog/neufbox_wdt.c 2007-12-12 14:54:59.000000000 +0100 @@ -0,0 +1,247 @@ +/* + * watchdog.c + * + * Copyright 2007 Miguel GAIO + * + * 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 program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "bcm_map_part.h" + + + +#define WATCHDOG_HZ (50000000) /* 50 MHz */ +#define WATCHDOG_INTERVAL (40) /* in seconds */ +#define WATCHDOG_RESET_STEP1 (0xFF00) +#define WATCHDOG_RESET_STEP2 (0x00FF) +#define WATCHDOG_STOP_STEP1 (0xEE00) +#define WATCHDOG_STOP_STEP2 (0x00EE) + + + +static unsigned long inuse = 0ul; +static char expect_close = 0; +static int heartbeat; + +#ifdef CONFIG_WATCHDOG_NOWAYOUT +static int nowayout = 1; +#else +static int nowayout = 0; +#endif + +module_param( nowayout, int, 0 ); + +MODULE_PARM_DESC( nowayout, + "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)" ); + + + +static void watchdog_set_heartbeat( unsigned long new_heartbeat ) +{ + /*! \note force minimum heartbeat to 10 seconds, + * maximum to 40 seconds */ + new_heartbeat = max( new_heartbeat, 10ul ); + new_heartbeat = min( new_heartbeat, 40ul ); + + heartbeat = ( new_heartbeat * WATCHDOG_HZ ); + + TIMER->WatchDogDefCount = heartbeat; +} + +static void watchdog_keepalive( void ) +{ + TIMER->WatchDogCtl = WATCHDOG_RESET_STEP1; + TIMER->WatchDogCtl = WATCHDOG_RESET_STEP2; +} + +static void watchdog_start( void ) +{ + printk( "watchdog: started...\n" ); + watchdog_keepalive( ); +} + +static int watchdog_stop( void ) +{ + printk( "watchdog: stopped!\n" ); + TIMER->WatchDogCtl = WATCHDOG_STOP_STEP1; + TIMER->WatchDogCtl = WATCHDOG_STOP_STEP2; + + return 0; +} + +/* Filesystem functions */ + +static int watchdog_open( struct inode *inode, struct file *file ) +{ + if ( test_and_set_bit( 0, &inuse ) ) + return -EBUSY; + + return nonseekable_open( inode, file ); +} + +static int watchdog_release( struct inode *inode, struct file *file ) +{ + if ( expect_close == 42 ) { + watchdog_stop( ); + } + else { + printk( KERN_CRIT + "watchdog: device closed unexpectedly. WD will not stop!\n" ); + } + + expect_close = 0; + + clear_bit( 0, &inuse ); + + return 0; +} + +static int watchdog_ioctl( struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg ) +{ + void __user *argp = ( void __user * ) arg; + int __user *p = argp; + int new_heartbeat; + static struct watchdog_info ident = { + .options = WDIOF_CARDRESET, + .identity = "neufbox watchdog", + }; + + switch ( cmd ) { + case WDIOC_GETSUPPORT: + if ( copy_to_user( argp, &ident, sizeof( ident ) ) ) + return -EFAULT; + break; + + case WDIOC_GETSTATUS: + case WDIOC_GETBOOTSTATUS: + return put_user( 0, p ); + + case WDIOC_KEEPALIVE: + watchdog_keepalive( ); + break; + + case WDIOC_SETTIMEOUT: + if ( get_user( new_heartbeat, p ) ) + return -EFAULT; + + watchdog_set_heartbeat( new_heartbeat ); + watchdog_keepalive( ); + break; + + case WDIOC_GETTIMEOUT: + return put_user( heartbeat, p ); + + default: + return -ENOTTY; + } + return 0; +} + +static ssize_t watchdog_write( struct file *file, const char *buf, + size_t count, loff_t * ppos ) +{ + if ( count ) { + if ( !nowayout ) { + size_t i; + + /* In case it was set long ago */ + expect_close = 0; + + for ( i = 0; i != count; i++ ) { + char c; + + if ( get_user( c, buf + i ) ) + return -EFAULT; + + if ( c == 'V' ) + expect_close = 42; + } + } + + watchdog_keepalive( ); + } + + return count; +} + + + +static struct file_operations watchdog_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .write = watchdog_write, + .ioctl = watchdog_ioctl, + .open = watchdog_open, + .release = watchdog_release, +}; + +static struct miscdevice watchdog_miscdev = { + .minor = WATCHDOG_MINOR, + .name = "watchdog", + .fops = &watchdog_fops, +}; + + + +static int __devinit watchdog_init( void ) +{ + int err; + + printk( "watchdog: init...\n" ); + + err = misc_register( &watchdog_miscdev ); + if ( err < 0 ) { + return err; + } + + watchdog_set_heartbeat( WATCHDOG_INTERVAL ); + watchdog_start( ); + + return 0; +} + +static void __devexit watchdog_exit( void ) +{ + watchdog_stop( ); + + misc_deregister( &watchdog_miscdev ); +} + + + +module_init( watchdog_init ); +module_exit( watchdog_exit ); + + + +MODULE_AUTHOR( "Miguel GAIO" ); +MODULE_DESCRIPTION( "Driver neufbox watchdog" ); +MODULE_ALIAS_MISCDEV( WATCHDOG_MINOR ); +MODULE_LICENSE( "GPL" );