Matt,

Do you think this really needs a config option?  Should it not be  
sufficient that if you enable watchdog you get this functionality on  
4xx/e500?

- kumar

On Mar 4, 2005, at 3:38 AM, Takeharu KATO wrote:

> Matt and Kurmar:
>
> I post the device driver part with this mail.
>
> This is the last part of this driver.
>
> Please apply.
>
> Regards,
>
> Signed-off-by: Takeharu KATO <kato.takeharu at jp.fujitsu.com>
>
> --- linux-2.6.11/drivers/char/watchdog/Kconfig? 2005-03-04  
> 17:14:57.687966296 +0900
>  +++ linux-2.6.11-booke-wdt/drivers/char/watchdog/Kconfig???????  
> 2005-03-04 13:21:32.000000000 +0900
>  @@ -346,6 +346,13 @@ config 8xx_WDT
>  ? ????? tristate "MPC8xx Watchdog Timer"
>  ? ????? depends on WATCHDOG && 8xx
>
> +config BOOKE_WDT
>  +??? bool "Book E(PowerPC 4xx/e500) Watchdog Timer"
>  +??? depends on WATCHDOG && ( 4xx || E500 )
>  +??? ---help---
>  +????? This is the driver for the watchdog timers on
>  +????? PowerPC 4xx and PowerPC e500.
>  +
>  ? # MIPS Architecture
>
> ? config INDYDOG
>  --- linux-2.6.11/drivers/char/watchdog/Makefile 2005-03-04  
> 17:15:30.582965496 +0900
>  +++ linux-2.6.11-booke-wdt/drivers/char/watchdog/Makefile??????  
> 2005-03-04 13:21:32.000000000 +0900
>  @@ -39,3 +39,4 @@ obj-$(CONFIG_USBPCWATCHDOG) += pcwd_usb.
>  ? obj-$(CONFIG_IXP4XX_WATCHDOG) += ixp4xx_wdt.o
>  ? obj-$(CONFIG_IXP2000_WATCHDOG) += ixp2000_wdt.o
> ? obj-$(CONFIG_8xx_WDT) += mpc8xx_wdt.o
>  +obj-$(CONFIG_BOOKE_WDT) += booke_wdt.o
>  --- linux-2.6.11/drivers/char/watchdog/booke_wdt.c????? 1970-01-01  
> 09:00:00.000000000 +0900
>  +++ linux-2.6.11-booke-wdt/drivers/char/watchdog/booke_wdt.c???  
> 2005-03-04 16:38:58.000000000 +0900
>  @@ -0,0 +1,664 @@
>  +/*
>  + *??? Copyright (c) 2005 Fujitsu Limited
>  + *
>  + *??? Module name: booke_wdt.c
>  + *??? Author:????? Takeharu KATO<kato.takeharu at jp.fujitsu.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.
>  + *
>  + *??? Neither Takeharu KATO nor Fujitsu Ltd. admit liability nor  
> provide
>  + *??? warranty for any of this software.
>  + *
>  + *??? Description:
>  + *???? Watchdog driver for PowerPC Book E (PowerPC 4xx series  
> processors and
>  + *???? PowerPC e500 series processors).
>  + *???? Derived from drivers/char/watchdog/wdt.c by Alan cox
>  + *????????????? and? drivers/char/watchdog/ppc405_wdt.c by Armin  
> Kuster.
>  + *???? PPC4xx WDT operation is driverd from Appendix of
>  + *???? PowerPC Embedded Processors Application Note
>  + *????? ``PowerPC 40x Watch Dog Timer'' published from IBM.
>  + *???? This driver is written according to ``PowerPC e500 Core  
> Complex
>  + *???? Reference Manual'' for e500 part.
>  + */
>  +#include <linux/config.h>
> +#include <linux/kernel.h>
> +#include <linux/types.h>
> +#include <linux/miscdevice.h>
> +#include <linux/watchdog.h>
> +#include <linux/fs.h>
>  +#include <linux/reboot.h>
> +#include <linux/init.h>
>  +#include <linux/capability.h>
> +#include <linux/string.h>
> +#include <linux/ptrace.h>
> +#include <asm/reg.h>
>  +#include <asm/uaccess.h>
> +#include <asm/system.h>
> +#include "booke_wdt.h"
> +
>  +/* micro seconds per one milli-second(used to calculatewatchdog
> + * counter to be set). */
>  +#define US_PER_MS 1000
>  +/*? Calculate watchdog count?? */
>  +#define calculate_wdt_count(t) ((((unsigned long)(t))*HZ)/1000)
> +
>  +int wdt_enable=0;???????????? /* WDT start on boot? */
>  +int wdt_period=WDT_TIMO;?????? /* Time out in ms */
>  +
>  +#ifdef CONFIG_WATCHDOG_NOWAYOUT
> +static int nowayout = 1;
>  +#else
>  +static int nowayout = 0;
>  +#endif
>  +
>  +/*
>  + * Global variables
>  + */
>  +static int wdt_count = 0;??????????? /* WDT intrrupt counter to be  
> reloaded */
>  +static volatile int wdt_heartbeat_count = 0;? /* WDT intrrupt  
> counter(compatible mode)*/
>  +static unsigned long driver_state; /* Driver status (see:  
> booke_wdt.h) */
>  +/*
>  + *? Identifier for this watchdog
>  + */
>  +static struct watchdog_info ident = {
>  +? .options=WDIOF_SETTIMEOUT|WDIOF_KEEPALIVEPING|WDIOF_MAGICCLOSE,
> +? .firmware_version =??? 0, /*? This is filled with PVR in  
> initialization. */
>  +? .identity =??????? "Book E(PPC 4xx/e500) WDT",
>  +};
>  +
>  +/*
>  + *? PowerPC Linux common exception handler
>  + */
>  +extern void _exception(int signr, struct pt_regs *regs, int code,  
> unsigned long addr);
>  +/*? Panic notifier? */
>  +extern struct notifier_block *panic_notifier_list;
> +/*
>  + *? External linkage functions
>  + */
>  +void booke_wdt_heartbeat(void);
> +void booke_wdt_setup_options(char *cmd_line);
>  +void booke_wdt_exception(struct pt_regs *regs);
> +/*
>  + * Internal linkage functions
>  + */
>  +static __inline__ void __booke_wdt_setup_val(int period,int reset);
>  +static __inline__ void __booke_wdt_enable(void);
> +static __inline__ void __booke_wdt_disable(void);
> +static __inline__ int? __booke_wdt_is_enabled(void);
> +static __inline__ void __booke_wdt_clear_int_stat(void);
> +static __inline__ void __booke_wdt_set_timeout(int t);
>  +static __inline__ void booke_wdt_init_device(void);
> +static __inline__ int? booke_wdt_is_enabled(void);
> +static __inline__ int? booke_wdt_start(void);
> +static __inline__ int? booke_wdt_stop(void);
> +static __inline__ int? booke_wdt_ping(void);
> +static __inline__ int? booke_wdt_set_timeout(int t);
>  +static __inline__ int? booke_wdt_get_status(int *status);
>  +static ssize_t booke_wdt_write(struct file *file, const char *buf,  
> size_t count, loff_t *ppos);
>  +static int booke_wdt_ioctl(struct inode *inode, struct file *file,  
> unsigned int cmd,unsigned long arg);
>  +static int booke_wdt_open(struct inode *inode, struct file *file);
> +static int booke_wdt_release(struct inode *inode, struct file *file);
> +static int booke_wdt_notify_sys(struct notifier_block *this, unsigned  
> long code,void *unused);
>  +static int __init booke_wdt_init(void);
> +static void __exit booke_wdt_exit(void);
> +
>  +/*
>  + *??? Watchdog operations on PPC4xx/e500 MPU
>  + */
>  +
>  +/**
>  + *????? __booke_wdt_setup_val
> + *????? Enable Watchdog, sets up passed in values for TCR[WP],
>  + *????? TCR[WRC]
>  + *
>  + *??? @period:??? Input Watchdog Period - TCR[WP]
>  + *????????????????????? 0 = 217 clocks
> + *????????????????????? 1 = 221 clocks
> + *????????????????????? 2 = 225 clocks
> + *????????????????????? 3 = 229 clocks
> + *????? @reset:???????? Watchdog reset control - TCR[WRC]
>  + *????????????????????? 0 = No reset
>  + *????????????????????? 1 = PPC Core reset only
>  + *????????????????????? 2 = PPC Chip reset
>  + *????????????????????? 3 = System reset
>  + *???? Note: The meaning of period number is differ PPC440GP from  
> PPC440GX.
>  + */
>  +#if defined(CONFIG_4xx)
> +static __inline__ void
> +__booke_wdt_setup_val(int period,int reset)
>  +{
>  +? unsigned long val;
>  +
>  +? /*? Set up TCR? */
>  +?  
> val=((period)<<WDT_TCR_WP_SHIFT|(reset)<<WDT_TCR_WRC_SHIFT)|mfspr(SPRN_ 
> TCR);
> +? /*? Disable WDT? */
>  +? val &= ~(WDT_TCR_WDT_ENABLE);
> +
>  +? mtspr(SPRN_TCR,val);
> +}
>  +#else
>  +/*? e500? */
>  +static __inline__ void
> +__booke_wdt_setup_val(int period,int reset)
>  +{
>  +? unsigned long val;
>  +? /*? Set up TCR? */
>  +
>  +? val=(((period)&(WDT_TCR_WP_BITMSK)) << WDT_TCR_WP_SHIFT|
> +?????? ( ( (period) >> 2 )&(WDT_TCR_WPEXT_BITMSK)) <<  
> WDT_TCR_WPEXT_SHIFT|
> +?????? (reset)<<WDT_TCR_WRC_SHIFT)|mfspr(SPRN_TCR);
> +? /*? Disable WDT? */
>  +? val &= ~(WDT_TCR_WDT_ENABLE);
> +
>  +? mtspr(SPRN_TCR,val);
> +}
>  +#endif? /*? CONFIG_E500 */
>  +/**
>  + *????? __booke_wdt_enable
> + *????? Enable Watchdog
>  + */
>  +static __inline__ void
> +__booke_wdt_enable(void)
> +{
>  +? mtspr(SPRN_TCR,(mfspr(SPRN_TCR)|WDT_TCR_WDT_ENABLE));
> +}
>  +/**
>  + *????? __booke_wdt_disable
> + *????? Disable Watchdog
>  + */
>  +static __inline__ void
> +__booke_wdt_disable(void)
> +{
>  +? mtspr(SPRN_TCR,(mfspr(SPRN_TCR)&(~(WDT_TCR_WDT_ENABLE))));
> +}
>  +/**
>  + *????? __booke_wdt_is_enabled
> + *????? Check whether Watchdog is enabled.
>  + */
>  +static __inline__ int
>  +__booke_wdt_is_enabled(void)
> +{
>  +? return (mfspr(SPRN_TCR) & WDT_TCR_WDT_ENABLE);
> +}
>  +/**
>  + *????? __booke_wdt_clear_init_stat
> + *????? Clear interrupt status of watchdog to ping it.
>  + */
>  +static __inline__ void
> +__booke_wdt_clear_int_stat(void)
> +{
>  +? mtspr(SPRN_TSR, (TSR_ENW|TSR_WIS));
> +}
>  +/**
>  + *??? __booke_wdt_set_timeout:
> + *??? @t:??? the new time out value that needs to be set.
>  + *
>  + *??? Set a new time out value for the watchdog device.
>  + *
>  + */
>  +static __inline__ void
> +__booke_wdt_set_timeout(int t)
>  +{
>  +? wdt_count=calculate_wdt_count(t);
> +? return;
>  +}
>  +
>  +/*
>  + * Driver specific functions
>  + */
>  +
>  +/**
>  + *?? booke_wdt_setup_options
> + *?? @cmd_line : a pointer to kernel command line.
> + *
>  + */
>  +void
>  +booke_wdt_setup_options(char *cmd_line)
>  +{
>  +/*
>  + * Look for wdt= option on command line
>  + */
>  +? if (strstr(cmd_line, "wdt=")) {
>  +??? int valid_wdt = 0;
>  +??? char *p, *q;
> +
>  +??? for (q = cmd_line; (p = strstr(q, "wdt=")) != 0;) {
> +????? q = p + 4;
> +????? if (p > cmd_line && p[-1] != ' ')
>  +??? continue;
>  +????? wdt_period = simple_strtoul(q, &q, 0);
>  +????? valid_wdt = 1;
>  +????? ++q;
>  +??? }
>  +??? wdt_enable = valid_wdt;
>  +? }
>  +? return;
>  +}
>  +/**
>  + *??? booke_wdt_heartbeat:
> + *????? Ping routine called from kernel.
>  + */
>  +void
>  +booke_wdt_heartbeat(void)
> +{
>  +? /* Disable watchdog */
>  +? __booke_wdt_disable();
> +
>  +? /* Write a watchdog value */
>  +? __booke_wdt_clear_int_stat();
> +
>  +? if (!wdt_enable)
>  +??? goto out;
>  +
>  +? if? (wdt_heartbeat_count > 0)
>  +??? wdt_heartbeat_count--;
>  +? else
>  +??? panic(booke_mkmsg("Initiating system reboot.\n"));
>  +
>  +? /* Enable watchdog */
>  +? __booke_wdt_enable();
> + out:
>  +? /*? Reset count? */
>  +? ppc_md.heartbeat_count = 0;
>  +}
>  +/**
>  + *??? booke_wdt_exception:
> + *????? WatchDog Exception handler for PPC4xx/e500.
> + *????? @regs : A registers information.
>  + */
>  +void
>  +booke_wdt_exception(struct pt_regs *regs)
>  +{
>  +? wdt_enable=0;
> +? __booke_wdt_disable();
> +? printk("WDT Exception at PC: %lx, MSR: %lx, vector=%lx??? %s\n",
>  +??????? regs->nip, regs->msr, regs->trap, print_tainted());
> +? panic(booke_mkmsg("Initiating system reboot.\n"));
>  +}
>  +/*
>  + *??? Driver Logic functions
> + */
>  +static __inline__ int
>  +booke_wdt_is_enabled(void)
> +{
>  +? return? __booke_wdt_is_enabled();
> +}
>  +/**
>  + *??? booke_wdt_start:
> + *
>  + *??? Start the watchdog driver.
>  + */
>  +static __inline__ int
>  +booke_wdt_start(void)
> +{
>  +? __booke_wdt_enable();
> +? return 0;
>  +}
>  +
>  +/**
>  + *??? booke_wdt_stop:
> + *
>  + *??? Stop the watchdog driver.
>  + */
>  +static __inline__ int
>  +booke_wdt_stop (void)
>  +{
>  +? __booke_wdt_disable();
> +? return 0;
>  +}
>  +/**
>  + *??? booke_wdt_ping:
> + *
>  + *??? Reload counter one with the watchdog heartbeat. We don't  
> bother reloading
>  + *??? the cascade counter.
>  + */
>  +static __inline__ int
>  +booke_wdt_ping(void)
> +{
>  +? /* Disable watchdog */
>  +? __booke_wdt_disable();
> +? /* Write a watchdog value */
>  +? __booke_wdt_clear_int_stat();
> +? /*? Reset count? */
>  +? wdt_heartbeat_count=wdt_count;
> +? /* Enable watchdog */
>  +? __booke_wdt_enable();
> +
>  +? return 0;
>  +}
>  +/**
>  + *??? booke_wdt_set_timeout:
> + *??? @t:??????? the new timeout value that needs to be set.
>  + *
>  + *??? Set a new time out value for the watchdog device.
>  + *????? If the heartbeat value is incorrect we keep the old value
>  + *????? and return -EINVAL. If successfull we return 0.
>  + */
>  +static __inline__ int
>  +booke_wdt_set_timeout(int t)
>  +{
>  +? if ((t < WDT_HEARTBEAT_MIN) || (t > WDT_HEARTBEAT_MAX))
> +??? return -EINVAL;
>  +
>  +? wdt_period = t;
>  +? __booke_wdt_set_timeout(t);
> +? wdt_heartbeat_count=wdt_count;
> +? booke_wdt_dbg("The WDT counter set %d.\n",wdt_count);
> +
>  +? return 0;
>  +}
>  +
>  +/**
>  + *??? booke_wdt_get_status:
> + *??? @status: the new status.
>  + *
>  + *??? Return the enable/disable card status.
>  + */
>  +static __inline__ int
>  +booke_wdt_get_status(int *status)
>  +{
>  +? if (wdt_enable)
>  +????? *status = WDIOS_ENABLECARD;
> +? else
>  +????? *status = WDIOS_DISABLECARD;
> +
>  +? return 0;
>  +}
>  +/*
>  + *??? Kernel Interfaces
>  + */
>  +/**
>  + *??? booke_wdt_init_device:
> + *
>  + *????? Initilize PowerPC 4xx/e500 family Watch Dog facility.
>  + */
>  +static void
>  +booke_wdt_init_device(void)
> +{
>  +??????? /* Hardware WDT provided by the processor.
>  +???? * So, we set firmware version as processor version number.
>  +???? */
>  +??? ident.firmware_version=mfspr(PVR);
> +??? __booke_wdt_setup_val(WDT_WP,WDT_RESET_NONE);
> +}
>  +/**
>  + *??? booke_wdt_write:
> + *??? @file: file handle to the watchdog
>  + *??? @buf: buffer to write (unused as data does not matter here
>  + *??? @count: count of bytes
>  + *??? @ppos: pointer to the position to write. No seeks allowed
>  + *
>  + *??? A write to a watchdog device is defined as a keepalive signal.  
> Any
>  + *??? write of data will do, as we we don't define content meaning  
> expept
>  + *????? 'V' character. It is performed as a sign to set  
> stop-on-close mode.
>  + */
>  +
>  +static ssize_t
>  +booke_wdt_write(struct file *file, const char *buf, size_t count,  
> loff_t *ppos)
>  +{
>  +? size_t i;
>  +
>  +??? if (!nowayout) {
>  +????? /* In case it was set long ago */
>  +????? clear_bit(WDT_STATE_STOP_ON_CLOSE, &driver_state);
> +
>  +????? for (i = 0; i < count; i++) {
> +??? char c;
>  +
>  +??? if (get_user(c, buf + i))
>  +????? return -EFAULT;
>  +
>  +??? if (c == 'V') {
>  +????? set_bit(WDT_STATE_STOP_ON_CLOSE, &driver_state);
> +??? }
>  +????? }
>  +??? }
>  +??? booke_wdt_ping();
> +
>  +? return count;
>  +}
>  +
>  +/**
>  + *??? booke_wdt_ioctl:
> + *??? @inode: inode of the device
>  + *??? @file: file handle to the device
>  + *??? @cmd: watchdog command
>  + *??? @arg: argument pointer
>  + *
>  + */
>  +static int
>  +booke_wdt_ioctl(struct inode *inode, struct file *file, unsigned int  
> cmd,
>  +??? unsigned long arg)
>  +{
>  +??? int new_timeout;
>  +??? int status;
>  +
>  +??? if (!capable(CAP_SYS_ADMIN))
> +??????? return -EPERM;? /*? It may be too strict manner.? */
>  +??? switch(cmd)
>  +??? {
>  +??? default:
>  +??????? return -ENOIOCTLCMD;
> +??? case WDIOC_GETSUPPORT:
> +??????? if (copy_to_user((struct watchdog_info *)arg, &ident,  
> sizeof(struct watchdog_info)))
> +??????????? return -EFAULT;
>  +??????? else
>  +??????????? break;
>  +??? case WDIOC_GETSTATUS:
> +??????? booke_wdt_get_status(&status);
> +??????? return put_user(status,(int *)arg);
>  +??? case WDIOC_KEEPALIVE:
> +??????? booke_wdt_ping();
> +??????? break;
>  +??? case WDIOC_SETTIMEOUT:
> +??????? if (get_user(new_timeout, (int *)arg))
>  +??????????? return -EFAULT;
>  +??????? if (booke_wdt_set_timeout(new_timeout))
> +??????????? return -EINVAL;
>  +??????? booke_wdt_ping();
> +??????? break;
>  +??? case WDIOC_GETTIMEOUT:
> +??????? return put_user(wdt_period, (int *)arg);
>  +??? case WDIOC_SETOPTIONS:
> +??????? if (get_user(status, (int *)arg))
>  +??????????? return -EFAULT;
>  +??????? /*? Return -EINVAL when the driver can not figure out
>  +???????? *? what it should do. Unknown cases are just ignored.
>  +???????? */
>  +??????? if ( (status & (WDIOS_DISABLECARD|WDIOS_ENABLECARD))
> +???????????? == (WDIOS_DISABLECARD|WDIOS_ENABLECARD) )
>  +??????????? return -EINVAL;
>  +??????? if (status & WDIOS_DISABLECARD) {
>  +??????????? wdt_enable = 0;
>  +??????????? booke_wdt_stop();
> +??????????? booke_wdt_info("Watchdog timer is disabled\n");
>  +??????? }
>  +??????? if (status & WDIOS_ENABLECARD) {
>  +??????????? wdt_enable = 1;
>  +??????????? booke_wdt_start();
> +??????????? booke_wdt_info("Watchdog timer is enabled\n");
>  +??????? }
>  +??????? break;
>  +??? }
>  +??? return 0;
>  +}
>  +/**
>  + *??? booke_wdt_open:
> + *??? @inode: inode of device
>  + *??? @file: file handle to device
>  + *
>  + *??? The watchdog device has been opened. The watchdog device is  
> single
> + *??? open and start the WDT timer.
>  + */
>  +static int
>  +booke_wdt_open(struct inode *inode, struct file *file)
>  +{
>  +??? if (!capable(CAP_SYS_ADMIN))
> +??????? return -EPERM;
>  +
>  +??? if (test_and_set_bit(WDT_STATE_OPEN, &driver_state))
> +??????? return -EBUSY;
>  +??? /*
>  +???? * Activate
>  +???? */
>  +??? booke_wdt_start();
> +??? wdt_enable=1;
> +
>  +??? if (nowayout)
>  +????? set_bit(WDT_STATE_STOP_ON_CLOSE, &driver_state);
> +
>  +??? return 0;
>  +}
>  +
>  +/**
>  + *??? booke_wdt_release:
> + *??? @inode: inode to board
> + *??? @file: file handle to board
>  + *
>  + */
>  +static int
>  +booke_wdt_release(struct inode *inode, struct file *file)
>  +{
>  +? if (test_bit(WDT_STATE_STOP_ON_CLOSE, &driver_state)) {
>  +????? booke_wdt_note("WDT device is stopped.\n");
>  +??? booke_wdt_stop();
> +??? wdt_enable=0;
> +? } else {
>  +??? if ( (booke_wdt_is_enabled()) && (!nowayout) ) {
>  +????? booke_wdt_note("WDT device may be closed unexpectedly.? WDT  
> will not stop!\n");
>  +????? booke_wdt_ping();
> +??? }
>  +? }
>  +? clear_bit(WDT_STATE_OPEN, &driver_state);
> +
>  +? return 0;
>  +}
>  +/**
>  + *??? notify_sys:
>  + *??? @this: our notifier block
>  + *??? @code: the event being reported
> + *??? @unused: unused
>  + *??? Note: This function assume that the panic notifier is called  
> with CODE=0
>  + *????????? (see panic function in kernel/panic.c).
> + */
>  +static int
>  +booke_wdt_notify_sys(struct notifier_block *this, unsigned long code,
>  +??? void *unused)
>  +{
>  +
>  +??? if (code != SYS_POWER_OFF)?? /* Turn the card off */
>  +????? booke_wdt_stop();
> +
>  +??? return NOTIFY_DONE;
> +}
>  +
>  +static struct file_operations booke_wdt_fops = {
>  +??? .owner??????? = THIS_MODULE,
> +??? .llseek??????? = no_llseek,
>  +??? .write??????? = booke_wdt_write,
> +??? .ioctl??????? = booke_wdt_ioctl,
> +??? .open??????? = booke_wdt_open,
> +??? .release??? = booke_wdt_release,
> +};
>  +
>  +static struct miscdevice booke_wdt_miscdev = {
>  +??? .minor??? = WATCHDOG_MINOR,
> +??? .name??? = "watchdog",
>  +??? .fops??? = &booke_wdt_fops,
> +};
>  +
>  +/*
>  + *??? The WDT card needs to know about shutdowns in order to
>  + *??? turn WDT off.
>  + */
>  +
>  +static struct notifier_block booke_wdt_notifier = {
>  +??? .notifier_call = booke_wdt_notify_sys,
> +};
>  +
>  +/**
>  + *??? cleanup_module:
> + *
>  + *??? If your watchdog is set to continue ticking on close and you  
> unload
>  + *??? it, well it keeps ticking.? You just have to load a new
>  + *??? module in 60 seconds or reboot.
>  + *????? This behavior(more over the comments as above) is borrowed  
> from
>  + *????? Alan cox's driver.
>  + */
>  +
>  +static void __exit
>  +booke_wdt_exit(void)
> +{
>  +??? misc_deregister(&booke_wdt_miscdev);
> +??? unregister_reboot_notifier(&booke_wdt_notifier);
> +???  
> notifier_chain_unregister(&panic_notifier_list,&booke_wdt_notifier);
> +}
>  +
>  +/**
>  + *???? booke_wdt_init:
> + *
>  + *??? Set up the WDT relevant timer facility.
>  + */
>  +
>  +static int __init
>  +booke_wdt_init(void)
> +{
>  +??? int ret;
>  +??? unsigned long flags;
>  +
>  +??? ret = register_reboot_notifier(&booke_wdt_notifier);
> +??? if(ret) {
>  +????? booke_wdt_err("Cannot register reboot notifier (err=%d)\n",  
> ret);
>  +????? return ret;
> +??? }
>  +
>  +??? /* Register panic notifier? */
>  +??? ret =  
> notifier_chain_register(&panic_notifier_list,&booke_wdt_notifier);
> +??? if(ret) {
>  +????? booke_wdt_err("Cannot register panic notifier (err=%d)\n",  
> ret);
>  +????? unregister_reboot_notifier(&booke_wdt_notifier);
> +????? return ret;
> +??? }
>  +
>  +??? ret = 0;
>  +??? booke_wdt_init_device();
> +??? /* Check that the heartbeat value is within it's range ; if not  
> reset to the default */
>  +??? if (booke_wdt_set_timeout(wdt_period)) {
>  +????? if (wdt_period)
>  +??????? booke_wdt_info("The heartbeat value must be %d < wdt_period  
> < %d, using
> %d\n",WDT_HEARTBEAT_MIN,WDT_HEARTBEAT_MAX,WDT_TIMO);
> +????? booke_wdt_set_timeout(WDT_TIMO);
> +??? }
>  +
>  +??? local_irq_save(flags); /* Prevent timer interrupt */
>  +??? ppc_md.heartbeat_count = 0;
>  +??? ppc_md.heartbeat=booke_wdt_heartbeat;
> +??? local_irq_restore(flags);
> +
>  +??? booke_wdt_info("Book E(PPC 4xx/e500) Watchdog Driver. period=%d  
> ms (nowayout=%d)\n",wdt_period,
>  nowayout);
>  +
>  +??? ret = misc_register(&booke_wdt_miscdev);
> +??? if (ret) {
>  +????? booke_wdt_err("Cannot register miscdev on minor=%d (err=%d)\n",
>  +??????????? WATCHDOG_MINOR, ret);
>  +??????? goto outmisc;
>  +??? }
>  +
>  +??? if (wdt_enable) {
>  +????? booke_wdt_info("WDT start on boot.\n");
>  +????? booke_wdt_start();
> +??? }
>  +out:
>  +??? return ret;
>  +outmisc:
>  +??? unregister_reboot_notifier(&booke_wdt_notifier);
> +??? local_irq_save(flags);
> +??? ppc_md.heartbeat=NULL;
> +??? ppc_md.heartbeat_count = 0;
>  +??? local_irq_restore(flags);
> +??? goto out;
>  +}
>  +
>  +device_initcall(booke_wdt_init);
> --- linux-2.6.11/drivers/char/watchdog/booke_wdt.h????? 1970-01-01  
> 09:00:00.000000000 +0900
>  +++ linux-2.6.11-booke-wdt/drivers/char/watchdog/booke_wdt.h???  
> 2005-03-04 16:38:58.000000000 +0900
>  @@ -0,0 +1,125 @@
>  +/*
>  + *
>  + *??? Copyright (c) 2004 Fujitsu Limited
>  + *
>  + *??? Module name: booke_wdt.h
>  + *??? Author:????? Takeharu KATO<kato.takeharu at jp.fujitsu.com>
> + *??? Description:
>  + *????? Header file for PowerPC Book E(PPC 4xx/e500) watchdog driver.
>  + *
>  + *??? 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.
>  + *
>  + *??? Neither Takeharu KATO nor Fujitsu Ltd. admit liability nor  
> provide
>  + *??? warranty for any of this software.
>  + *
>  + */
>  +#ifndef _DRIVERS_CHAR_WATCHDOG_BOOKE_WDT_H
> +#define _DRIVERS_CHAR_WATCHDOG_BOOKE_WDT_H
> +#include <linux/config.h>
> +#include <linux/kernel.h>
> +#include <linux/ptrace.h>
> +#include <linux/watchdog.h>
> +
>  +/*
>  + *? Driver state flags(bit position)
>  + */
>  +#define WDT_STATE_OPEN????????????????? 0?? /* driver is opend? */
>  +#define WDT_STATE_STOP_ON_CLOSE???????? 1?? /* Stop with close is  
> expected */
>  +/*
>  + * Configurations
> + */
>  +#define WDT_TIMO?????????? 60000??? /* Default timeout = 60000  
> ms(1min) */
>  +#define WDT_HEARTBEAT_MIN? 100????????? /* Minimum timeout = 100 ms  
> */
>  +#define WDT_HEARTBEAT_MAX? 600000?????? /* Maximum timeout =  
> 600000ms(1hour) */
>  +#ifdef __KERNEL__
>  +//#define BOOKE_WDT_DEBUG???????????????????? /*? Debug switch */
>  +/*
>  + *? Reset type
> + */
>  +#define WDT_RESET_NONE???? 0
>  +#define WDT_RESET_CORE???? 1
>  +#define WDT_RESET_CHIP???? 2
>  +#define WDT_RESET_SYS????? 3
>  +/*
>  + *?? Bit positions in? TCR register on PPC4xx/e500 series.
>  + */
>  +#define WDT_TCR_WP_BIT???? 1?? /*? WP? bit in TCR (bit[0..1])?? */
>  +#define WDT_TCR_WRC_BIT??? 3?? /*? WRC bit in TCR (bit[2..3])?? */
>  +#define WDT_TCR_WIE_BIT??? 4?? /*? WIE bit in TCR (bit[4])????? */
>  +/*
>  + *? TCR[WP] relevant definitions
>  + */
>  +#define WDT_TCR_WP_SHIFT?????? (31 - WDT_TCR_WP_BIT)
> +#define WDT_TCR_WRC_SHIFT????? (31 - WDT_TCR_WRC_BIT)
> +#define WDT_TCR_WIE_SHIFT????? (31 - WDT_TCR_WIE_BIT)
> +#define WDT_TCR_WDT_ENABLE???? (1<<WDT_TCR_WIE_SHIFT)
> +/*? MASK value to obatain TCR[WP]? */
>  +#define WDT_TCR_WP_MASK??????? (3<<(WDT_TCR_WP_SHIFT))
> +
>  +/*? Watchdog timer periods can be set on PPC 4xx cpus. */
>  +#if defined(CONFIG_4xx)
> +/*
>  + *? For PowerPC 4xx
>  + */
>  +#define WDT_WP0?????????????? 0
>  +#define WDT_WP1?????????????? 1
>  +#define WDT_WP2?????????????? 2
>  +#define WDT_WP3?????????????? 3
>  +#else
>  +#if defined(CONFIG_E500)
> +/*
>  + *? For e500 CPU
>  + *? Actually, e500 can arbitrary periods can be set,
>  + *? But this driver uses fix period value as same as PPC440
>  + *? on purpose for simplicity.
>  + *? Following values split into WP and WP_EXT parts in booke_wdt.c.
>  + */
>  +#define WDT_WP0?????????????? 21
>  +#define WDT_WP1?????????????? 25
>  +#define WDT_WP2?????????????? 29
>  +#define WDT_WP3?????????????? 33
>  +#define WDT_TCR_WP_BITMSK???? 0x3? /*? 2bit length? */
>  +#define WDT_TCR_WPEXT_BITMSK? 0xf? /*? 4bit length? */
>  +#define WDT_TCR_WPEXT_SHIFT? 17
>  +#else
>  +#error "Book E WDT detects invalid configuration(Unknown CPU)"
>  +#endif? /*? CONFIG_E500? */
>  +#endif? /*? CONFIG_4xx?? */
>  +/*
>  + *? WP relevant values used in our driver.
>  + *? Note:WDT period must be more than HZ(Timer ticks)
> + */
>  +#define WDT_WP???????????????? WDT_WP3
>  +
>  +/*
>  + *? IOCTL commands for comaptiblity for old driver
>  + */
>  +#define WDIOC_GETPERIOD???????? WDIOC_GETTIMEOUT
> +#define WDIOC_SETPERIOD???????? WDIOC_SETTIMEOUT
> +
>  +/*
>  + *? output messages
>  + */
>  +#define __BOOKE_WDT_MSG "BookE-WDT : "
>  +#define booke_mkmsg(str) __BOOKE_WDT_MSG str
>  +#define booke_wdt_info(fmt,arg...) \
>  +??? printk(KERN_INFO __BOOKE_WDT_MSG fmt,##arg)
>  +#define booke_wdt_note(fmt,arg...) \
>  +??? printk(KERN_NOTICE __BOOKE_WDT_MSG fmt,##arg)
>  +#define booke_wdt_err(fmt,arg...) \
>  +??? printk(KERN_ALERT __BOOKE_WDT_MSG fmt,##arg)
>  +#define booke_wdt_crit(fmt,arg...) \
>  +??? printk(KERN_ALERT __BOOKE_WDT_MSG fmt,##arg)
>  +#if defined(BOOKE_WDT_DEBUG)
> +#define booke_wdt_dbg(fmt,arg...) \
>  +??? printk(KERN_ALERT __BOOKE_WDT_MSG fmt,##arg)
>  +#else
>  +#define booke_wdt_dbg(fmt,arg...) \
>  +??????? do{}while(0)
>  +#endif? /*? WDT_DEBUG? */
>  +
>  +#endif? /* __KERNEL__? */
>  +#endif? /*? _DRIVERS_CHAR_WATCHDOG_BOOKE_WDT_H? */
>
>  

Reply via email to