linuxppc-dev.lists.ozlabs.org archive mirror
 help / color / mirror / Atom feed
* PowerPC4xx Watchdog
@ 2005-02-23 19:00 Takeharu KATO
  2005-02-23 19:15 ` Takeharu KATO
  0 siblings, 1 reply; 33+ messages in thread
From: Takeharu KATO @ 2005-02-23 19:00 UTC (permalink / raw)
  To: ppcembed

Hi

I am trying to  WatchDog Driver for PowerPC4xx on Linux-2.6.
Does anyone have a plan to WatchDog Driver on this architecture?

-- 
Takeharu KATO

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: PowerPC4xx Watchdog
  2005-02-23 19:00 PowerPC4xx Watchdog Takeharu KATO
@ 2005-02-23 19:15 ` Takeharu KATO
  2005-02-23 21:27   ` Matt Porter
  0 siblings, 1 reply; 33+ messages in thread
From: Takeharu KATO @ 2005-02-23 19:15 UTC (permalink / raw)
  To: Takeharu KATO; +Cc: ppcembed

Hi

Sorry, I sent the mail before checking it by mistake.
I meant to say as follows:
I am working on developing WatchDog Driver for PowerPC4xx on Linux-2.6.
Does anyone have a plan or a patch to make WatchDog Driver on 
PowerPC4xx(405GP/405GPr/440GP/440GX) for Linux-2.6?


Takeharu KATO wrote:
> Hi
> 
> I am trying to  WatchDog Driver for PowerPC4xx on Linux-2.6.
> Does anyone have a plan to WatchDog Driver on this architecture?
> 


-- 
Takeharu KATO

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: PowerPC4xx Watchdog
  2005-02-23 19:15 ` Takeharu KATO
@ 2005-02-23 21:27   ` Matt Porter
  2005-02-23 23:23     ` Takeharu KATO
  2005-02-25 19:35     ` PowerPC4xx Watchdog Takeharu KATO
  0 siblings, 2 replies; 33+ messages in thread
From: Matt Porter @ 2005-02-23 21:27 UTC (permalink / raw)
  To: Takeharu KATO; +Cc: ppcembed

On Thu, Feb 24, 2005 at 04:15:53AM +0900, Takeharu KATO wrote:
> Hi
> 
> Sorry, I sent the mail before checking it by mistake.
> I meant to say as follows:
> I am working on developing WatchDog Driver for PowerPC4xx on Linux-2.6.
> Does anyone have a plan or a patch to make WatchDog Driver on 
> PowerPC4xx(405GP/405GPr/440GP/440GX) for Linux-2.6?

Are you looking for the old "ppc405 watchdog" driver that simply
hooked into the generic PPC heartbeat facility? Or are you looking
for a driver that utilizes the 4xx/booke hardware watchdog facility?

-Matt

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: PowerPC4xx Watchdog
  2005-02-23 21:27   ` Matt Porter
@ 2005-02-23 23:23     ` Takeharu KATO
  2005-02-23 23:36       ` Takeharu KATO
  2005-02-25 19:35     ` PowerPC4xx Watchdog Takeharu KATO
  1 sibling, 1 reply; 33+ messages in thread
From: Takeharu KATO @ 2005-02-23 23:23 UTC (permalink / raw)
  To: Matt Porter; +Cc: ppcembed

Hi

> 
> Are you looking for the old "ppc405 watchdog" driver that simply
> hooked into the generic PPC heartbeat facility? Or are you looking
> for a driver that utilizes the 4xx/booke hardware watchdog facility?
> 
I am looking for a driver that utilizes the 4xx/booke hardware watchdog 
facility.


-- 
Takeharu KATO

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: PowerPC4xx Watchdog
  2005-02-23 23:23     ` Takeharu KATO
@ 2005-02-23 23:36       ` Takeharu KATO
  2005-03-02 17:52         ` Matt Porter
  0 siblings, 1 reply; 33+ messages in thread
From: Takeharu KATO @ 2005-02-23 23:36 UTC (permalink / raw)
  To: Takeharu KATO; +Cc: ppcembed

Hi

>> Are you looking for the old "ppc405 watchdog" driver that simply
>> hooked into the generic PPC heartbeat facility? Or are you looking
>> for a driver that utilizes the 4xx/booke hardware watchdog facility?
>>
> I am looking for a driver that utilizes the 4xx/booke hardware watchdog 
> facility.
> 
> 
FYI, I wrote a driver uses 4xx/booke hardware watchdog.
BTW, is hooking PPC heartbeat facility obsoleted?

-- 
Takeharu KATO

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: PowerPC4xx Watchdog
  2005-02-23 21:27   ` Matt Porter
  2005-02-23 23:23     ` Takeharu KATO
@ 2005-02-25 19:35     ` Takeharu KATO
  2005-02-28 13:18       ` [PATCH 1/3] PowerPC4xx/E500 WatchDogTimerDriver(Core and PPC4xx part) Takeharu KATO
                         ` (2 more replies)
  1 sibling, 3 replies; 33+ messages in thread
From: Takeharu KATO @ 2005-02-25 19:35 UTC (permalink / raw)
  To: Matt Porter; +Cc: ppcembed

[-- Attachment #1: Type: text/plain, Size: 1238 bytes --]

Hi Matt

> Are you looking for the old "ppc405 watchdog" driver that simply
> hooked into the generic PPC heartbeat facility? Or are you looking
> for a driver that utilizes the 4xx/booke hardware watchdog facility?
> 
After all, I wrote watch dog driver for PowerPC 4xx using 4xx/book-e 
watchdog facility and generic PPC heartbeat mechanism.

On second thought, I found that these are almost same.
As far as I think generic PPC heartbeat mechanism is more preferable
for embedded systems from memory consumption view at least.

Using generic PPC heartbeat mechanism can make the driver simple and small.
And more, this approach can achieve following profits:

1) The approach may not need modification in low-exception handling routines
(in arch/ppc/kernel/head_XXX).
2) The approach can achieve compatibility with old-driver.

Any way, I attached current version of my patch.
Please take a look on the patch.

P.S.
I found critical interrupt relevant trivial bug in 
arch/ppc/kernel/head_booke.h.
CRITICAL_EXCEPTION macro in the file use transfer_to_handler_full and
ret_from_except_full.
IMHO, The correct code is that this macro should use 
crit_transfer_to_handler, ret_from_crit_exc instead, isn't it?

Regards,

-- 
Takeharu KATO

[-- Attachment #2: ppc4xx_wdt.patch --]
[-- Type: text/plain, Size: 29080 bytes --]

diff -uprN linux-2.6.11-rc4.orig/arch/ppc/kernel/head_44x.S linux-2.6.11-rc4/arch/ppc/kernel/head_44x.S
--- linux-2.6.11-rc4.orig/arch/ppc/kernel/head_44x.S	2005-02-22 12:59:33.000000000 +0900
+++ linux-2.6.11-rc4/arch/ppc/kernel/head_44x.S	2005-02-26 02:48:31.000000000 +0900
@@ -444,8 +444,13 @@ interrupt_base:
 	EXCEPTION(0x1010, FixedIntervalTimer, UnknownException, EXC_XFER_EE)
 
 	/* Watchdog Timer Interrupt */
-	/* TODO: Add watchdog support */
+#if defined(CONFIG_PPC4xx_WATCHDOG) && !defined(CONFIG_PPC4xx_WATCHDOG_COMPAT)
+	CRITICAL_EXCEPTION(0x1020, WatchdogTimer, ppc4xx_wdt_interrupt)
+#else
 	CRITICAL_EXCEPTION(0x1020, WatchdogTimer, UnknownException)
+#endif
+
+
 
 	/* Data TLB Error Interrupt */
 	START_EXCEPTION(DataTLBError)
diff -uprN linux-2.6.11-rc4.orig/arch/ppc/kernel/head_4xx.S linux-2.6.11-rc4/arch/ppc/kernel/head_4xx.S
--- linux-2.6.11-rc4.orig/arch/ppc/kernel/head_4xx.S	2005-02-22 12:59:33.000000000 +0900
+++ linux-2.6.11-rc4/arch/ppc/kernel/head_4xx.S	2005-02-26 02:48:31.000000000 +0900
@@ -477,19 +477,23 @@ label:
 
 #if 0
 /* NOTE:
- * FIT and WDT handlers are not implemented yet.
+ * FIT handlers are not implemented yet.
  */
 
 /* 0x1010 - Fixed Interval Timer (FIT) Exception
 */
 	STND_EXCEPTION(0x1010,	FITException,		UnknownException)
 
+#endif
+
 /* 0x1020 - Watchdog Timer (WDT) Exception
 */
-
+#if defined(CONFIG_PPC4xx_WATCHDOG) && !defined(CONFIG_PPC4xx_WATCHDOG_COMPAT)
+	CRITICAL_EXCEPTION(0x1020, WDTException, ppc4xx_wdt_interrupt)
+#else
 	CRITICAL_EXCEPTION(0x1020, WDTException, UnknownException)
 #endif
-
+	
 /* 0x1100 - Data TLB Miss Exception
  * As the name implies, translation is not in the MMU, so search the
  * page tables and fix it.  The only purpose of this function is to
diff -uprN linux-2.6.11-rc4.orig/arch/ppc/kernel/head_booke.h linux-2.6.11-rc4/arch/ppc/kernel/head_booke.h
--- linux-2.6.11-rc4.orig/arch/ppc/kernel/head_booke.h	2005-02-22 12:59:33.000000000 +0900
+++ linux-2.6.11-rc4/arch/ppc/kernel/head_booke.h	2005-02-26 01:01:11.000000000 +0900
@@ -194,8 +194,8 @@ label:
 	CRITICAL_EXCEPTION_PROLOG;				\
 	addi	r3,r1,STACK_FRAME_OVERHEAD;			\
 	EXC_XFER_TEMPLATE(hdlr, n+2, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \
-			  NOCOPY, transfer_to_handler_full, \
-			  ret_from_except_full)
+			  NOCOPY, crit_transfer_to_handler, \
+			  ret_from_crit_exc)
 
 #define MCHECK_EXCEPTION(n, label, hdlr)			\
 	START_EXCEPTION(label);					\
diff -uprN linux-2.6.11-rc4.orig/arch/ppc/syslib/ppc4xx_setup.c linux-2.6.11-rc4/arch/ppc/syslib/ppc4xx_setup.c
--- linux-2.6.11-rc4.orig/arch/ppc/syslib/ppc4xx_setup.c	2005-02-22 12:59:33.000000000 +0900
+++ linux-2.6.11-rc4/arch/ppc/syslib/ppc4xx_setup.c	2005-02-26 01:01:15.000000000 +0900
@@ -48,9 +48,11 @@
 extern void abort(void);
 extern void ppc4xx_find_bridges(void);
 
+#ifdef CONFIG_PPC4xx_WATCHDOG
 extern void ppc4xx_wdt_heartbeat(void);
 extern int wdt_enable;
 extern unsigned long wdt_period;
+#endif  /*  CONFIG_PPC4xx_WATCHDOG  */
 
 /* Global Variables */
 bd_t __res;
@@ -257,7 +259,7 @@ ppc4xx_init(unsigned long r3, unsigned l
 		*(char *) (r7 + KERNELBASE) = 0;
 		strcpy(cmd_line, (char *) (r6 + KERNELBASE));
 	}
-#if defined(CONFIG_PPC405_WDT)
+#ifdef CONFIG_PPC4xx_WATCHDOG
 /* Look for wdt= option on command line */
 	if (strstr(cmd_line, "wdt=")) {
 		int valid_wdt = 0;
@@ -272,7 +274,7 @@ ppc4xx_init(unsigned long r3, unsigned l
 		}
 		wdt_enable = valid_wdt;
 	}
-#endif
+#endif  /*  CONFIG_PPC4xx_WATCHDOG  */
 
 	/* Initialize machine-dependent vectors */
 
@@ -287,9 +289,9 @@ ppc4xx_init(unsigned long r3, unsigned l
 
 	ppc_md.calibrate_decr = ppc4xx_calibrate_decr;
 
-#ifdef CONFIG_PPC405_WDT
+#ifdef CONFIG_PPC4xx_WATCHDOG_COMPAT
 	ppc_md.heartbeat = ppc4xx_wdt_heartbeat;
-#endif
+#endif  /*  CONFIG_PPC4xx_WATCHDOG  */
 	ppc_md.heartbeat_count = 0;
 
 	ppc_md.find_end_of_memory = ppc4xx_find_end_of_memory;
diff -uprN linux-2.6.11-rc4.orig/drivers/char/watchdog/Kconfig linux-2.6.11-rc4/drivers/char/watchdog/Kconfig
--- linux-2.6.11-rc4.orig/drivers/char/watchdog/Kconfig	2005-02-22 12:58:29.000000000 +0900
+++ linux-2.6.11-rc4/drivers/char/watchdog/Kconfig	2005-02-26 02:48:42.000000000 +0900
@@ -346,6 +346,25 @@ config 8xx_WDT
 	tristate "MPC8xx Watchdog Timer"
 	depends on WATCHDOG && 8xx
 
+config PPC4xx_WATCHDOG
+	bool "Watchdog on PowerPC 4xx series"
+	depends on WATCHDOG && 4xx
+	---help---
+	  This is the driver for the hardware watchdog timers present on
+	  PowerPC 4xx series(PPC405GP/GPr,PPC440GP/GX).
+config PPC4xx_WATCHDOG_COMPAT
+	bool "Enable Compatibility with old ppc405 driver."
+	depends on PPC4xx_WATCHDOG
+	---help---
+	  If you want send acks to WDT with timer interrupt, turn on this 
+	  option.
+	  
+          This option changes behaviors of the driver to old ppc405 software 
+	  watch dog driver did. Strictly speaking, it may not have the 
+	  complete compatibility with ppc405 software WDT. It does not
+	  use WDT exception in PowerPC 4xx. 
+
+
 # MIPS Architecture
 
 config INDYDOG
diff -uprN linux-2.6.11-rc4.orig/drivers/char/watchdog/Makefile linux-2.6.11-rc4/drivers/char/watchdog/Makefile
--- linux-2.6.11-rc4.orig/drivers/char/watchdog/Makefile	2005-02-22 12:58:30.000000000 +0900
+++ linux-2.6.11-rc4/drivers/char/watchdog/Makefile	2005-02-26 01:01:20.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_PPC4xx_WATCHDOG)   += ppc4xx_wdt.o
\ No newline at end of file
diff -uprN linux-2.6.11-rc4.orig/drivers/char/watchdog/ppc4xx_wdt.c linux-2.6.11-rc4/drivers/char/watchdog/ppc4xx_wdt.c
--- linux-2.6.11-rc4.orig/drivers/char/watchdog/ppc4xx_wdt.c	1970-01-01 09:00:00.000000000 +0900
+++ linux-2.6.11-rc4/drivers/char/watchdog/ppc4xx_wdt.c	2005-02-26 02:48:42.000000000 +0900
@@ -0,0 +1,717 @@
+/*
+ *
+ *    Copyright (c) 2004 Fujitsu Limited
+ *
+ *    Module name: ppc4xx_wdt.c
+ *    Author:      Takeharu KATO<kato.takeharu@jp.fujitsu.com>
+ *    Description:
+ *      Watchdog driver for PowerPC 4xx-based 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.
+ */
+#include <linux/config.h>
+#include <linux/interrupt.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 <asm/uaccess.h>
+#include <asm/system.h>
+#if defined(CONFIG_440GP)
+#include <syslib/ibm440gp_common.h>
+#endif  /*  CONFIG_440GP  */
+#if defined(CONFIG_440GX)
+#include <syslib/ibm440gx_common.h>
+#endif  /*  CONFIG_440GX  */
+#include "ppc4xx_wdt.h"
+
+/* micro seconds per one milli-second(used to calculatewatchdog 
+ * counter to be set. */
+#define US_PER_MS 1000  
+/*  MHz in Hz  */
+#define MHZ  1000000
+/*
+ * External linkage
+ */
+int wdt_enable=0;                  /* WDT start on boot  */
+int wdt_period = WD_TIMO;          /* Time out in ms(see: ppc4xx_wdt.h) */
+/*
+ * 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: ppc4xx_wdt.h) */
+void ppc4xx_wdt_heartbeat(void);
+/*
+ * Internal linkage functions
+ */
+static __inline__ void __ppc4xx_wdt_setup_val(int period,int reset);
+static __inline__ void __ppc4xx_wdt_enable(void);
+static __inline__ void __ppc4xx_wdt_disable(void);
+static __inline__ int  __ppc4xx_wdt_is_enabled(void);
+static __inline__ void __ppc4xx_wdt_clear_int_stat(void);
+static __inline__ void __ppc4xx_wdt_set_timeout(int t);
+#if !defined(CONFIG_PPC4xx_WATCHDOG_COMPAT)
+static unsigned long cpu_clock=0;    /* To store cpu_clock */
+#if defined(CONFIG_40x)
+static __inline__ int  __ppc40x_get_cpu_clock(void);
+#endif  /*  CONFIG_40x  */
+#if defined(CONFIG_44x)
+static __inline__ int  __ppc44x_get_cpu_clock(void);
+#endif  /*  CONFIG_44x  */
+static __inline__ void  __ppc4xx_get_cpu_clock(void);
+#endif  /*  CONFIG_PPC4xx_WATCHDOG_COMPAT  */
+static __inline__ void ppc4xx_wdt_init_device(void);
+static __inline__ int  ppc4xx_wdt_is_enabled(void);
+static __inline__ int  ppc4xx_wdt_start(void);
+static __inline__ int  ppc4xx_wdt_stop(void);
+static __inline__ int  ppc4xx_wdt_ping(void);
+static __inline__ int  ppc4xx_wdt_set_timeout(int t);
+static __inline__ int  ppc4xx_wdt_get_status(int *status);
+static ssize_t ppc4xx_wdt_write(struct file *file, const char *buf, size_t count, loff_t *ppos);
+static int ppc4xx_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,unsigned long arg);
+static int ppc4xx_wdt_open(struct inode *inode, struct file *file);
+static int ppc4xx_wdt_release(struct inode *inode, struct file *file);
+static int ppc4xx_wdt_notify_sys(struct notifier_block *this, unsigned long code,void *unused);
+static int __init ppc4xx_wdt_init(void);
+static void __exit ppc4xx_wdt_exit(void);
+
+#ifdef CONFIG_WATCHDOG_NOWAYOUT
+static int nowayout = 1;
+#else
+static int nowayout = 0;
+#endif
+
+/*
+ *	Watchdog operations on PPC4xx MPU
+ */
+#if !defined(CONFIG_PPC4xx_WATCHDOG_COMPAT)
+#if defined(CONFIG_40x)
+/**
+ *      __ppc40x_get_cpu_clock
+ *      Get CPU clock of PPC405 family
+ */
+static __inline__ int 
+__ppc40x_get_cpu_clock(void)
+{
+  bd_t *bip = &__res;
+
+  return  (bip->bi_tbfreq);
+}
+#endif  /*  CONFIG_40x  */
+
+#if defined(CONFIG_44x)
+/**
+ *      ppc44x_get_cpu_clock
+ *      Get CPU clock of PPC440 family
+ */
+static __inline__ int 
+__ppc44x_get_cpu_clock(void)
+{
+  struct ibm44x_clocks clocks;
+
+  /* Note:
+   * Following functions are assigned in init section.
+   * So we keep cpu_clocks in this module.
+   */
+#if defined(CONFIG_440GX)
+  ibm440gx_get_clocks(&clocks, 33333333, 6 * 1843200);
+#else
+#if defined(CONFIG_440GP)
+  ibm440gp_get_clocks(&clocks, 33333333, 6 * 1843200);
+#endif
+#endif
+  
+  return clocks.cpu;
+}
+#endif  /*  CONFIG_44x  */
+#endif  /*   !CONFIG_PPC4xx_WATCHDOG_COMPAT  */
+/**
+ *      ppc4xx_get_cpu_clock
+ *      Get CPU clock of PPC4xx family
+ */
+#if !defined(CONFIG_PPC4xx_WATCHDOG_COMPAT)
+static __inline__ void
+__ppc4xx_get_cpu_clock(void)
+{
+	if (!cpu_clock)
+#if defined(CONFIG_40x)
+		cpu_clock = __ppc40x_get_cpu_clock();
+#else
+#if defined(CONFIG_44x)
+	        cpu_clock =  __ppc44x_get_cpu_clock();
+#else
+#error "PPC4xx WDT Detect invalid configuration(Unknown CPU)"
+#endif  /*  CONFIG_44x  */
+#endif  /*  CONFIG_40x  */
+  return;
+}
+#else
+#define __ppc4xx_get_cpu_clock() do{}while(0)
+#endif  /*  CONFIG_PPC4xx_WATCHDOG_COMPAT  */
+/**
+ *      __ppc4xx_wdt_setup_val
+ *      Enable 4xx Watchdog, sets up passed in values for TCR[WP],
+ *      TCR[WRC]
+ *   
+ *	@period:	Input Watchdog Period - TCR[WP]
+ *                      0 = 2^17 clocks
+ *                      1 = 2^21 clocks
+ *                      2 = 2^25 clocks
+ *                      3 = 2^29 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.
+ */
+static __inline__ void
+__ppc4xx_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);
+}
+/**
+ *      __ppc4xx_wdt_enable
+ *      Enable 4xx Watchdog
+ */
+static __inline__ void
+__ppc4xx_wdt_enable(void)
+{
+  mtspr(SPRN_TCR,(mfspr(SPRN_TCR)|WDT_TCR_WDT_ENABLE));
+}
+/**
+ *      __ppc4xx_wdt_disable
+ *      Disable 4xx Watchdog
+ */
+static __inline__ void
+__ppc4xx_wdt_disable(void)
+{
+  mtspr(SPRN_TCR,(mfspr(SPRN_TCR)&(~(WDT_TCR_WDT_ENABLE))));
+}
+/**
+ *      __ppc4xx_wdt_is_enabled
+ *      Check whether 4xx Watchdog is enabled.
+ */
+static __inline__ int
+__ppc4xx_wdt_is_enabled(void)
+{
+  return (mfspr(SPRN_TCR) & WDT_TCR_WDT_ENABLE);
+}
+/**
+ *      __ppc4xx_wdt_clear_init_stat
+ *      Clear interrupt status of PPC4xx Watchdog to ping it.
+ */
+static __inline__ void
+__ppc4xx_wdt_clear_int_stat(void)
+{
+  mtspr(SPRN_TSR, (TSR_ENW|TSR_WIS));
+}
+/**
+ *	__ppc4xx_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
+__ppc4xx_wdt_set_timeout(int t)
+{
+#if !defined(CONFIG_PPC4xx_WATCHDOG_COMPAT)
+  unsigned long tmp;
+  unsigned long div;
+
+  /*  Parameter check must be performed in wdt_set_timeout.  */  
+  ppc4xx_wdt_dbg("clock : %d\n",cpu_clock);
+  tmp=t*US_PER_MS; /*  in us */
+
+  /* Note:
+   * On  PowerPC 4xx processor, WatchDogTimer exception is occur according to
+   * Time Base bit tansition 0 -> 1. In other word, Time Base bit tansition 
+   * 1 -> 0 does not cause the exception. The is the reason why the divisor
+   * as follows should be multiplied by 2.
+   */
+  div=( (WDT_CLK_PER_INT_WP_VAL/(cpu_clock/MHZ)) * 2);
+  ppc4xx_wdt_dbg("div : %lu\n",div);
+  tmp /= div;
+  wdt_count=tmp;
+#else
+  wdt_count=t;  /*  Assume 1ms tick */
+#endif
+  return;
+}
+/*
+ * Driver specific functions
+ */
+/**
+ *	ppc4xx_wdt_heartbeat:
+ *      Ping routine called from kernel.
+ */
+void 
+ppc4xx_wdt_heartbeat(void)
+{
+  /* Disable watchdog */
+  __ppc4xx_wdt_disable();
+
+  /* Write a watchdog value */
+  __ppc4xx_wdt_clear_int_stat();
+  
+  if (!wdt_enable) 
+    goto out;
+
+#if defined(CONFIG_PPC4xx_WATCHDOG_COMPAT)
+  if  (wdt_heartbeat_count > 0)
+    wdt_heartbeat_count--;
+  else
+    panic(ppc4xx_mkmsg("Initiating system reboot.\n"));
+#endif /*  CONFIG_PPC4xx_WATCHDOG_COMPAT  */
+  /* Enable watchdog */
+  __ppc4xx_wdt_enable();
+ out:
+  /*  Reset count  */
+  ppc_md.heartbeat_count = 0;
+}
+/**
+ *	ppc4xx_wdt_interrupt:
+ *      Watchdog interrupt handler.
+ */
+void
+ppc4xx_wdt_interrupt(struct pt_regs *regs)
+{
+  unsigned long status=mfspr(SPRN_TSR);
+  unsigned long flags;
+
+  if (status & (TSR_WIS|TSR_ENW)){
+	  /* Disable watchdog */
+	  __ppc4xx_wdt_disable();
+
+	  __ppc4xx_wdt_clear_int_stat();
+	  local_irq_save(flags);
+#if !defined(CONFIG_PPC4xx_WATCHDOG_COMPAT)
+    if (wdt_heartbeat_count) {
+      --wdt_heartbeat_count;
+    } else {
+#ifdef ONLY_TESTING
+      ppc4xx_wdt_crit("Would Reboot by application failure.\n");
+#else
+#ifdef SOFTWARE_REBOOT
+      ppc4xx_wdt_crit("Initiating system reboot.\n");
+      machine_restart(NULL);
+#else
+      panic(ppc4xx_mkmsg("Initiating system reboot.\n"));
+#endif  /*   SOFTWARE_REBOOT  */
+#endif  /*   ONLY_TESTING  */
+    }   /*  Time out  */
+#endif  /*   !CONFIG_PPC4xx_WATCHDOG_COMPAT  */
+    local_irq_restore(flags);
+    /* Enable watchdog */
+    __ppc4xx_wdt_enable();
+  }
+  return;
+}
+\f
+/*
+ *	Driver Logic functions
+ */
+static __inline__ int
+ppc4xx_wdt_is_enabled(void)
+{
+  return  __ppc4xx_wdt_is_enabled();
+}
+/**
+ *	ppc4xx_wdt_start:
+ *
+ *	Start the watchdog driver.
+ */
+static __inline__ int 
+ppc4xx_wdt_start(void)
+{
+  __ppc4xx_wdt_enable();
+  return 0;
+}
+
+/**
+ *	ppc4xx_wdt_stop:
+ *
+ *	Stop the watchdog driver.
+ */
+static __inline__ int 
+ppc4xx_wdt_stop (void)
+{
+  __ppc4xx_wdt_disable();
+  return 0;
+}
+/**
+ *	ppc4xx_wdt_ping:
+ *
+ *	Reload counter one with the watchdog heartbeat. We don't bother reloading
+ *	the cascade counter.
+ */
+static __inline__ int 
+ppc4xx_wdt_ping(void)
+{
+  /* Disable watchdog */
+  __ppc4xx_wdt_disable();
+  /* Write a watchdog value */
+  __ppc4xx_wdt_clear_int_stat();
+  /*  Reset count  */
+  wdt_heartbeat_count=wdt_count;
+  /* Enable watchdog */
+  __ppc4xx_wdt_enable();
+
+  return 0;
+}
+/**
+ *	ppc4xx_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 
+ppc4xx_wdt_set_timeout(int t)
+{
+  if ((t < WDT_HEARTBEAT_MIN) || (t > WDT_HEARTBEAT_MAX))
+    return -EINVAL;
+
+  wdt_period = t;
+  __ppc4xx_wdt_set_timeout(t);
+  wdt_heartbeat_count=wdt_count;
+  ppc4xx_wdt_dbg("The WDT counter set %d.\n",wdt_count);
+
+  return 0;
+}
+
+/**
+ *	ppc4xx_wdt_get_status:
+ *	@status: the new status.
+ *
+ *	Return the enable/disable card status.
+ */
+static __inline__ int 
+ppc4xx_wdt_get_status(int *status)
+{
+  if (wdt_enable)
+	  *status = WDIOS_ENABLECARD;
+  else
+	  *status = WDIOS_DISABLECARD;
+
+  return 0;
+}
+/*
+ *	Kernel Interfaces
+ */
+/**
+ *	ppc4xx_wdt_init_device:
+ *
+ *      Initilize PowerPC 4xx family Watch Dog facility.
+ */
+static void
+ppc4xx_wdt_init_device(void)
+{
+        __ppc4xx_get_cpu_clock();
+	__ppc4xx_wdt_setup_val(WDT_WP,WDT_RESET_NONE);
+}
+/**
+ *	ppc4xx_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 
+ppc4xx_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);
+	}
+      }
+    }
+    ppc4xx_wdt_ping();
+
+  return count;
+}
+static struct watchdog_info ident = {
+  .options=WDIOF_SETTIMEOUT|WDIOF_KEEPALIVEPING|WDIOF_MAGICCLOSE,
+  .firmware_version =	1,
+  .identity =		"PPC4xx WDT",
+};
+
+/**
+ *	ppc4xx_wdt_ioctl:
+ *	@inode: inode of the device
+ *	@file: file handle to the device
+ *	@cmd: watchdog command
+ *	@arg: argument pointer
+ *
+ */
+static int 
+ppc4xx_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:
+		ppc4xx_wdt_get_status(&status);
+		return put_user(status,(int *)arg);
+	case WDIOC_KEEPALIVE:
+		ppc4xx_wdt_ping();
+		break;
+	case WDIOC_SETTIMEOUT:
+		if (get_user(new_timeout, (int *)arg))
+			return -EFAULT;
+		if (ppc4xx_wdt_set_timeout(new_timeout))
+			return -EINVAL;
+		ppc4xx_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;
+			ppc4xx_wdt_stop();
+			ppc4xx_wdt_note("Watchdog timer is disabled\n");
+		}
+		if (status & WDIOS_ENABLECARD) {
+			wdt_enable = 1;
+			ppc4xx_wdt_start();
+			ppc4xx_wdt_note("Watchdog timer is enabled\n");
+		}
+		break;
+	}
+	return 0;
+}
+/**
+ *	ppc4xx_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 
+ppc4xx_wdt_open(struct inode *inode, struct file *file)
+{
+	if (test_and_set_bit(WDT_STATE_OPEN, &driver_state))
+		return -EBUSY;
+	/*
+	 * Activate
+	 */
+	ppc4xx_wdt_start();
+	wdt_enable=1;
+
+	if (nowayout)
+	  set_bit(WDT_STATE_STOP_ON_CLOSE, &driver_state);
+
+	return 0;
+}
+
+/**
+ *	ppc4xx_wdt_release:
+ *	@inode: inode to board
+ *	@file: file handle to board
+ *
+ */
+static int
+ppc4xx_wdt_release(struct inode *inode, struct file *file)
+{
+  if (test_bit(WDT_STATE_STOP_ON_CLOSE, &driver_state)) {
+      ppc4xx_wdt_note("WDT device is stopped.\n");
+    ppc4xx_wdt_stop();
+    wdt_enable=0;
+  } else {
+    if ( (ppc4xx_wdt_is_enabled()) && (!nowayout) ) {
+      ppc4xx_wdt_note("WDT device may be closed unexpectedly.  WDT will not stop!\n");
+      ppc4xx_wdt_ping();
+    }
+  }
+  clear_bit(WDT_STATE_OPEN, &driver_state);
+
+  return 0;
+}
+/**
+ *	notify_sys:
+ *	@this: our notifier block
+ *	@code: the event being reported
+ *	@unused: unused
+ *
+ */
+
+static int 
+ppc4xx_wdt_notify_sys(struct notifier_block *this, unsigned long code,
+	void *unused)
+{
+	if(code==SYS_DOWN || code==SYS_HALT) {
+	  /* Turn the card off */
+	  ppc4xx_wdt_stop();
+	}
+	return NOTIFY_DONE;
+}
+
+static struct file_operations ppc4xx_wdt_fops = {
+	.owner		= THIS_MODULE,
+	.llseek		= no_llseek,
+	.write		= ppc4xx_wdt_write,
+	.ioctl		= ppc4xx_wdt_ioctl,
+	.open		= ppc4xx_wdt_open,
+	.release	= ppc4xx_wdt_release,
+};
+
+static struct miscdevice ppc4xx_wdt_miscdev = {
+	.minor	= WATCHDOG_MINOR,
+	.name	= "watchdog",
+	.fops	= &ppc4xx_wdt_fops,
+};
+
+/*
+ *	The WDT card needs to know about shutdowns in order to
+ *	turn WDT off.
+ */
+
+static struct notifier_block ppc4xx_wdt_notifier = {
+	.notifier_call = ppc4xx_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 
+ppc4xx_wdt_exit(void)
+{
+	misc_deregister(&ppc4xx_wdt_miscdev);
+	unregister_reboot_notifier(&ppc4xx_wdt_notifier);
+}
+
+/**
+ * 	ppc4xx_wdt_init:
+ *
+ *	Set up the WDT relevant timer facility. 
+ */
+
+static int __init 
+ppc4xx_wdt_init(void)
+{
+	int ret;
+
+	ret = register_reboot_notifier(&ppc4xx_wdt_notifier);
+	if(ret) {
+	  ppc4xx_wdt_err("Cannot register reboot notifier (err=%d)\n", ret);
+	  return ret;
+	}
+
+	ret = 0;
+	ppc4xx_wdt_init_device();
+	/* Check that the heartbeat value is within it's range ; if not reset to the default */
+	if (ppc4xx_wdt_set_timeout(wdt_period)) {
+	  ppc4xx_wdt_set_timeout(WD_TIMO);
+	  ppc4xx_wdt_info("The heartbeat value must be 0<wdt_period<65536, using %d\n",WD_TIMO);
+	}
+	
+#if defined(CONFIG_PPC4xx_WATCHDOG_COMPAT)
+	{
+		unsigned long flags;
+
+		local_irq_save(flags); /* Prevent timer interrupt */
+		ppc_md.heartbeat_count = 0;	
+		ppc_md.heartbeat=ppc4xx_wdt_heartbeat;
+		local_irq_restore(flags);
+	}
+#endif  /*  CONFIG_PPC4xx_WATCHDOG_COMPAT  */
+
+	ppc4xx_wdt_info("PowerPC 4xx Watchdog Driver. period=%d ms (nowayout=%d)\n",wdt_period, nowayout);
+
+	ret = misc_register(&ppc4xx_wdt_miscdev);
+	if (ret) {
+	  ppc4xx_wdt_err("Cannot register miscdev on minor=%d (err=%d)\n",
+			WATCHDOG_MINOR, ret);
+		goto outmisc;
+	}
+
+	if (wdt_enable) {
+	  ppc4xx_wdt_info("WDT start on boot.\n");
+	  ppc4xx_wdt_start();
+	}
+out:
+	return ret;
+outmisc:
+	unregister_reboot_notifier(&ppc4xx_wdt_notifier);
+#if defined(CONFIG_PPC4xx_WATCHDOG_COMPAT)
+	{
+		unsigned long flags;
+
+		local_irq_save(flags);
+		ppc_md.heartbeat=NULL;
+		ppc_md.heartbeat_count = 0;
+		local_irq_restore(flags);
+	}
+#endif
+	goto out;
+}
+
+module_init(ppc4xx_wdt_init);
+module_exit(ppc4xx_wdt_exit);
+
+MODULE_AUTHOR("Takeharu KATO");
+MODULE_DESCRIPTION("Driver for PPC4xx watchdog cards.");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
+MODULE_LICENSE("GPL");
diff -uprN linux-2.6.11-rc4.orig/drivers/char/watchdog/ppc4xx_wdt.h linux-2.6.11-rc4/drivers/char/watchdog/ppc4xx_wdt.h
--- linux-2.6.11-rc4.orig/drivers/char/watchdog/ppc4xx_wdt.h	1970-01-01 09:00:00.000000000 +0900
+++ linux-2.6.11-rc4/drivers/char/watchdog/ppc4xx_wdt.h	2005-02-26 02:48:42.000000000 +0900
@@ -0,0 +1,131 @@
+/*
+ *
+ *    Copyright (c) 2004 Fujitsu Limited
+ *
+ *    Module name: ppc4xx_wdt.h
+ *    Author:      Takeharu KATO<kato.takeharu@jp.fujitsu.com>
+ *    Description:
+ *      Header file for PPC4xx watchdog driver.
+ */
+#ifndef _ARCH_PPC_SYSLIB_PPC4XX_WDT_H
+#define _ARCH_PPC_SYSLIB_PPC4XX_WDT_H
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/ptrace.h>
+#include <linux/watchdog.h>
+
+/*
+ *  Driver behavior flags(bit position)
+ */
+#define WDT_STATE_OPEN                  0   /* driver is opend  */
+#define WDT_STATE_STOP_ON_CLOSE         1   /* Stop with close is expected */
+#define WDT_STATE_COMPAT_MODE           2   /* Monta Vista Linux Comaptible  */
+/*
+ *  For comaptible mode
+ */
+#define WDIOC_GETPERIOD         WDIOC_GETTIMEOUT
+#define WDIOC_SETPERIOD         WDIOC_SETTIMEOUT
+/*
+ * Configurations
+ */
+#define WD_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 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 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 PPC4xx cpus. */
+#define WDT_WP0               0
+#define WDT_WP1               1
+#define WDT_WP2               2
+#define WDT_WP3               3
+
+/*  Immediate values of TCR[WP] */
+/*  2^17 clocks period  */
+#define WDT_TCR_WP_VAL0        (0<<(WDT_TCR_WP_SHIFT))
+/*  2^21 clocks period  */
+#define WDT_TCR_WP_VAL1        (1<<(WDT_TCR_WP_SHIFT))
+/*  2^25 clocks period  */
+#define WDT_TCR_WP_VAL2        (2<<(WDT_TCR_WP_SHIFT))
+/*  2^29 clocks period  */
+#define WDT_TCR_WP_VAL3        (3<<(WDT_TCR_WP_SHIFT)) 
+
+/*  Clock periods expressed with power of 2 for each value. */
+#if defined(CONFIG_44x)
+#define WDT_CLK_POW_WP_VAL0  21  /*  2^17 clocks period  */
+#define WDT_CLK_POW_WP_VAL1  25  /*  2^21 clocks period  */
+#define WDT_CLK_POW_WP_VAL2  29  /*  2^25 clocks period  */
+#define WDT_CLK_POW_WP_VAL3  33  /*  2^29 clocks period  */
+#else
+#if defined(CONFIG_40x)
+#define WDT_CLK_POW_WP_VAL0  17  /*  2^17 clocks period  */
+#define WDT_CLK_POW_WP_VAL1  21  /*  2^21 clocks period  */
+#define WDT_CLK_POW_WP_VAL2  25  /*  2^25 clocks period  */
+#define WDT_CLK_POW_WP_VAL3  29  /*  2^29 clocks period  */
+#else
+#error "PPC4xx WDT Detect invalid configuration(Unknown CPU)"
+#endif
+#endif
+/*
+ *  WP relevant values used in our driver.
+ */
+#if !defined(CONFIG_PPC4xx_WATCHDOG_COMPAT)
+#define WDT_WP                 WDT_WP0
+#define WDT_WP_VAL             WDT_TCR_WP_VAL0
+#define WDT_CLK_POW_WP_VAL     WDT_CLK_POW_WP_VAL0
+#define WDT_CLK_PER_INT_WP_VAL ((1UL)<<WDT_CLK_POW_WP_VAL)
+#else
+/*
+ *  WDT period must be more than HZ(Timer ticks)
+ */
+#define WDT_WP                 WDT_WP3
+#define WDT_WP_VAL             WDT_TCR_WP_VAL3
+#define WDT_CLK_POW_WP_VAL     WDT_CLK_POW_WP_VAL3
+#define WDT_CLK_PER_INT_WP_VAL ((1UL)<<WDT_CLK_POW_WP_VAL)
+#endif
+/*
+ *  output messages
+ */
+#define __PPC4xx_WDT_MSG "PPC4xx WDT : "
+#define ppc4xx_mkmsg(str) __PPC4xx_WDT_MSG str
+#define ppc4xx_wdt_info(fmt,arg...) \
+	printk(KERN_INFO __PPC4xx_WDT_MSG fmt,##arg)
+#define ppc4xx_wdt_note(fmt,arg...) \
+	printk(KERN_NOTICE __PPC4xx_WDT_MSG fmt,##arg)
+#define ppc4xx_wdt_err(fmt,arg...) \
+	printk(KERN_ALERT __PPC4xx_WDT_MSG fmt,##arg)
+#define ppc4xx_wdt_crit(fmt,arg...) \
+	printk(KERN_ALERT __PPC4xx_WDT_MSG fmt,##arg)
+#if defined(WDT_DEBUG)
+#define ppc4xx_wdt_dbg(fmt,arg...) \
+	printk(KERN_ALERT __PPC4xx_WDT_MSG fmt,##arg)
+#else
+#define ppc4xx_wdt_dbg(fmt,arg...) \
+        do{}while(0)
+#endif  /*  WDT_DEBUG  */
+
+void ppc4xx_wdt_interrupt(struct pt_regs *regs);
+#endif  /* __KERNEL__  */
+#endif  /*  _ARCH_PPC_SYSLIB_PPC4XX_WDT_H  */

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH 1/3] PowerPC4xx/E500 WatchDogTimerDriver(Core and PPC4xx part)
  2005-02-25 19:35     ` PowerPC4xx Watchdog Takeharu KATO
@ 2005-02-28 13:18       ` Takeharu KATO
  2005-02-28 13:20       ` PowerPC4xx Watchdog Takeharu KATO
  2005-02-28 13:27       ` [PATCH 3/3] PowerPC4xx/E500 WatchDogTimerDriver(exception handler part) Takeharu KATO
  2 siblings, 0 replies; 33+ messages in thread
From: Takeharu KATO @ 2005-02-28 13:18 UTC (permalink / raw)
  To: Matt Porter; +Cc: ppcembed

Dear Matt and all:

I finished writing PowerPC4xx/e500 Watch Dog Timer Driver.
This driver consist of three parts of patches:

1) ppc4xx-wdt.patch  ... Driver core and PowerPC4xx relevant setup.
2) e500-wdt.patch    ... PowerPC e500 (MPC85xx) relevant setup.
3) exc-wdt.patch     ... Exception handler fixes.

Please apply these patches.

This driver is tested on following environments:

i)  Ebony evaluation board(CPU:PowerPC440GP)
ii) MPC8560 CDS evaluation board (CPU:MPC8560)

Please contact me via e-mail if there is a person who cooperates in the test.
I can send test-sets for this driver off-list.

Regards,

Signed-off-by: Takeharu KATO <kato.takeharu@jp.fujitsu.com>

--- linux-2.6.11-rc5.orig/arch/ppc/syslib/ppc4xx_setup.c	2005-02-27 15:26:57.000000000 +0900
+++ linux-2.6.11-rc5/arch/ppc/syslib/ppc4xx_setup.c	2005-02-28 20:51:45.000000000 +0900
@@ -48,10 +48,6 @@
  extern void abort(void);
  extern void ppc4xx_find_bridges(void);

-extern void ppc4xx_wdt_heartbeat(void);
-extern int wdt_enable;
-extern unsigned long wdt_period;
-
  /* Global Variables */
  bd_t __res;

@@ -257,22 +253,13 @@ ppc4xx_init(unsigned long r3, unsigned l
  		*(char *) (r7 + KERNELBASE) = 0;
  		strcpy(cmd_line, (char *) (r6 + KERNELBASE));
  	}
-#if defined(CONFIG_PPC405_WDT)
-/* 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;
+#ifdef CONFIG_PPC4xx_WATCHDOG
+	{
+	  extern void ppc4xx_wdt_setup_options(char *cmd_line);
+
+	  ppc4xx_wdt_setup_options(cmd_line);
  	}
-#endif
+#endif  /*  CONFIG_PPC4xx_WATCHDOG  */

  	/* Initialize machine-dependent vectors */

@@ -287,9 +274,9 @@ ppc4xx_init(unsigned long r3, unsigned l

  	ppc_md.calibrate_decr = ppc4xx_calibrate_decr;

-#ifdef CONFIG_PPC405_WDT
+#ifdef CONFIG_PPC4xx_WATCHDOG
  	ppc_md.heartbeat = ppc4xx_wdt_heartbeat;
-#endif
+#endif  /*  CONFIG_PPC4xx_WATCHDOG  */
  	ppc_md.heartbeat_count = 0;

  	ppc_md.find_end_of_memory = ppc4xx_find_end_of_memory;
@@ -319,3 +306,5 @@ void platform_machine_check(struct pt_re
  #endif

  }
+
+
--- linux-2.6.11-rc5.orig/drivers/char/watchdog/Kconfig	2005-02-27 15:29:22.000000000 +0900
+++ linux-2.6.11-rc5/drivers/char/watchdog/Kconfig	2005-02-28 19:33:10.000000000 +0900
@@ -346,6 +346,13 @@ config 8xx_WDT
  	tristate "MPC8xx Watchdog Timer"
  	depends on WATCHDOG && 8xx

+config PPC4xx_WATCHDOG
+	bool "Watchdog on PowerPC 4xx/e500"
+	depends on WATCHDOG && ( 4xx || E500 )
+	---help---
+	  This is the driver for the watchdog timers present on
+	  PowerPC 4xx series(PPC405GP/GPr,PPC440GP/GX and so on).
+
  # MIPS Architecture

  config INDYDOG
--- linux-2.6.11-rc5.orig/drivers/char/watchdog/Makefile	2005-02-27 15:29:33.000000000 +0900
+++ linux-2.6.11-rc5/drivers/char/watchdog/Makefile	2005-02-27 21:37:31.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_PPC4xx_WATCHDOG)   += ppc4xx_wdt.o
\ No newline at end of file
--- linux-2.6.11-rc5.orig/drivers/char/watchdog/ppc4xx_wdt.c	1970-01-01 09:00:00.000000000 +0900
+++ linux-2.6.11-rc5/drivers/char/watchdog/ppc4xx_wdt.c	2005-02-28 20:51:45.000000000 +0900
@@ -0,0 +1,635 @@
+/*
+ *    Copyright (c) 2005 Fujitsu Limited
+ *
+ *    Module name: ppc4xx_wdt.c
+ *    Author:      Takeharu KATO<kato.takeharu@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 4xx-based 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 <asm/reg.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include "ppc4xx_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: ppc4xx_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 =		"PPC4xx WDT",
+};
+
+/*
+ *  External linkage functions
+ */
+void ppc4xx_wdt_heartbeat(void);
+void ppc4xx_wdt_setup_options(char *cmd_line);
+/*
+ * Internal linkage functions
+ */
+static __inline__ void __ppc4xx_wdt_setup_val(int period,int reset);
+static __inline__ void __ppc4xx_wdt_enable(void);
+static __inline__ void __ppc4xx_wdt_disable(void);
+static __inline__ int  __ppc4xx_wdt_is_enabled(void);
+static __inline__ void __ppc4xx_wdt_clear_int_stat(void);
+static __inline__ void __ppc4xx_wdt_set_timeout(int t);
+static __inline__ void ppc4xx_wdt_init_device(void);
+static __inline__ int  ppc4xx_wdt_is_enabled(void);
+static __inline__ int  ppc4xx_wdt_start(void);
+static __inline__ int  ppc4xx_wdt_stop(void);
+static __inline__ int  ppc4xx_wdt_ping(void);
+static __inline__ int  ppc4xx_wdt_set_timeout(int t);
+static __inline__ int  ppc4xx_wdt_get_status(int *status);
+static ssize_t ppc4xx_wdt_write(struct file *file, const char *buf, size_t count, loff_t *ppos);
+static int ppc4xx_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,unsigned long 
arg);
+static int ppc4xx_wdt_open(struct inode *inode, struct file *file);
+static int ppc4xx_wdt_release(struct inode *inode, struct file *file);
+static int ppc4xx_wdt_notify_sys(struct notifier_block *this, unsigned long code,void *unused);
+static int __init ppc4xx_wdt_init(void);
+static void __exit ppc4xx_wdt_exit(void);
+
+/*
+ *	Watchdog operations on PPC4xx MPU
+ */
+
+/**
+ *      __ppc4xx_wdt_setup_val
+ *      Enable 4xx Watchdog, sets up passed in values for TCR[WP],
+ *      TCR[WRC]
+ *
+ *	@period:	Input Watchdog Period - TCR[WP]
+ *                      0 = 2^17 clocks
+ *                      1 = 2^21 clocks
+ *                      2 = 2^25 clocks
+ *                      3 = 2^29 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
+__ppc4xx_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
+__ppc4xx_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 */
+/**
+ *      __ppc4xx_wdt_enable
+ *      Enable 4xx Watchdog
+ */
+static __inline__ void
+__ppc4xx_wdt_enable(void)
+{
+  mtspr(SPRN_TCR,(mfspr(SPRN_TCR)|WDT_TCR_WDT_ENABLE));
+}
+/**
+ *      __ppc4xx_wdt_disable
+ *      Disable 4xx Watchdog
+ */
+static __inline__ void
+__ppc4xx_wdt_disable(void)
+{
+  mtspr(SPRN_TCR,(mfspr(SPRN_TCR)&(~(WDT_TCR_WDT_ENABLE))));
+}
+/**
+ *      __ppc4xx_wdt_is_enabled
+ *      Check whether 4xx Watchdog is enabled.
+ */
+static __inline__ int
+__ppc4xx_wdt_is_enabled(void)
+{
+  return (mfspr(SPRN_TCR) & WDT_TCR_WDT_ENABLE);
+}
+/**
+ *      __ppc4xx_wdt_clear_init_stat
+ *      Clear interrupt status of PPC4xx Watchdog to ping it.
+ */
+static __inline__ void
+__ppc4xx_wdt_clear_int_stat(void)
+{
+  mtspr(SPRN_TSR, (TSR_ENW|TSR_WIS));
+}
+/**
+ *	__ppc4xx_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
+__ppc4xx_wdt_set_timeout(int t)
+{
+  wdt_count=calculate_wdt_count(t);
+  return;
+}
+
+/*
+ * Driver specific functions
+ */
+
+/**
+ *   ppc4xx_wdt_setup_options
+ *   @cmd_line : a pointer to kernel command line.
+ *
+ */
+void
+ppc4xx_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;
+}
+/**
+ *	ppc4xx_wdt_heartbeat:
+ *      Ping routine called from kernel.
+ */
+void
+ppc4xx_wdt_heartbeat(void)
+{
+  /* Disable watchdog */
+  __ppc4xx_wdt_disable();
+
+  /* Write a watchdog value */
+  __ppc4xx_wdt_clear_int_stat();
+
+  if (!wdt_enable)
+    goto out;
+
+  if  (wdt_heartbeat_count > 0)
+    wdt_heartbeat_count--;
+  else
+    panic(ppc4xx_mkmsg("Initiating system reboot.\n"));
+
+  /* Enable watchdog */
+  __ppc4xx_wdt_enable();
+ out:
+  /*  Reset count  */
+  ppc_md.heartbeat_count = 0;
+}
+\f
+/*
+ *	Driver Logic functions
+ */
+static __inline__ int
+ppc4xx_wdt_is_enabled(void)
+{
+  return  __ppc4xx_wdt_is_enabled();
+}
+/**
+ *	ppc4xx_wdt_start:
+ *
+ *	Start the watchdog driver.
+ */
+static __inline__ int
+ppc4xx_wdt_start(void)
+{
+  __ppc4xx_wdt_enable();
+  return 0;
+}
+
+/**
+ *	ppc4xx_wdt_stop:
+ *
+ *	Stop the watchdog driver.
+ */
+static __inline__ int
+ppc4xx_wdt_stop (void)
+{
+  __ppc4xx_wdt_disable();
+  return 0;
+}
+/**
+ *	ppc4xx_wdt_ping:
+ *
+ *	Reload counter one with the watchdog heartbeat. We don't bother reloading
+ *	the cascade counter.
+ */
+static __inline__ int
+ppc4xx_wdt_ping(void)
+{
+  /* Disable watchdog */
+  __ppc4xx_wdt_disable();
+  /* Write a watchdog value */
+  __ppc4xx_wdt_clear_int_stat();
+  /*  Reset count  */
+  wdt_heartbeat_count=wdt_count;
+  /* Enable watchdog */
+  __ppc4xx_wdt_enable();
+
+  return 0;
+}
+/**
+ *	ppc4xx_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
+ppc4xx_wdt_set_timeout(int t)
+{
+  if ((t < WDT_HEARTBEAT_MIN) || (t > WDT_HEARTBEAT_MAX))
+    return -EINVAL;
+
+  wdt_period = t;
+  __ppc4xx_wdt_set_timeout(t);
+  wdt_heartbeat_count=wdt_count;
+  ppc4xx_wdt_dbg("The WDT counter set %d.\n",wdt_count);
+
+  return 0;
+}
+
+/**
+ *	ppc4xx_wdt_get_status:
+ *	@status: the new status.
+ *
+ *	Return the enable/disable card status.
+ */
+static __inline__ int
+ppc4xx_wdt_get_status(int *status)
+{
+  if (wdt_enable)
+	  *status = WDIOS_ENABLECARD;
+  else
+	  *status = WDIOS_DISABLECARD;
+
+  return 0;
+}
+/*
+ *	Kernel Interfaces
+ */
+/**
+ *	ppc4xx_wdt_init_device:
+ *
+ *      Initilize PowerPC 4xx family Watch Dog facility.
+ */
+static void
+ppc4xx_wdt_init_device(void)
+{
+        /* Hardware WDT provided by the processor.
+	 * So, we set firmware version as processor version number.
+	 */
+	ident.firmware_version=mfspr(PVR);
+	__ppc4xx_wdt_setup_val(WDT_WP,WDT_RESET_NONE);
+}
+/**
+ *	ppc4xx_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
+ppc4xx_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);
+	}
+      }
+    }
+    ppc4xx_wdt_ping();
+
+  return count;
+}
+
+/**
+ *	ppc4xx_wdt_ioctl:
+ *	@inode: inode of the device
+ *	@file: file handle to the device
+ *	@cmd: watchdog command
+ *	@arg: argument pointer
+ *
+ */
+static int
+ppc4xx_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:
+		ppc4xx_wdt_get_status(&status);
+		return put_user(status,(int *)arg);
+	case WDIOC_KEEPALIVE:
+		ppc4xx_wdt_ping();
+		break;
+	case WDIOC_SETTIMEOUT:
+		if (get_user(new_timeout, (int *)arg))
+			return -EFAULT;
+		if (ppc4xx_wdt_set_timeout(new_timeout))
+			return -EINVAL;
+		ppc4xx_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;
+			ppc4xx_wdt_stop();
+			ppc4xx_wdt_note("Watchdog timer is disabled\n");
+		}
+		if (status & WDIOS_ENABLECARD) {
+			wdt_enable = 1;
+			ppc4xx_wdt_start();
+			ppc4xx_wdt_note("Watchdog timer is enabled\n");
+		}
+		break;
+	}
+	return 0;
+}
+/**
+ *	ppc4xx_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
+ppc4xx_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
+	 */
+	ppc4xx_wdt_start();
+	wdt_enable=1;
+
+	if (nowayout)
+	  set_bit(WDT_STATE_STOP_ON_CLOSE, &driver_state);
+
+	return 0;
+}
+
+/**
+ *	ppc4xx_wdt_release:
+ *	@inode: inode to board
+ *	@file: file handle to board
+ *
+ */
+static int
+ppc4xx_wdt_release(struct inode *inode, struct file *file)
+{
+  if (test_bit(WDT_STATE_STOP_ON_CLOSE, &driver_state)) {
+      ppc4xx_wdt_note("WDT device is stopped.\n");
+    ppc4xx_wdt_stop();
+    wdt_enable=0;
+  } else {
+    if ( (ppc4xx_wdt_is_enabled()) && (!nowayout) ) {
+      ppc4xx_wdt_note("WDT device may be closed unexpectedly.  WDT will not stop!\n");
+      ppc4xx_wdt_ping();
+    }
+  }
+  clear_bit(WDT_STATE_OPEN, &driver_state);
+
+  return 0;
+}
+/**
+ *	notify_sys:
+ *	@this: our notifier block
+ *	@code: the event being reported
+ *	@unused: unused
+ *
+ */
+
+static int
+ppc4xx_wdt_notify_sys(struct notifier_block *this, unsigned long code,
+	void *unused)
+{
+	if(code==SYS_DOWN || code==SYS_HALT) {
+	  /* Turn the card off */
+	  ppc4xx_wdt_stop();
+	}
+	return NOTIFY_DONE;
+}
+
+static struct file_operations ppc4xx_wdt_fops = {
+	.owner		= THIS_MODULE,
+	.llseek		= no_llseek,
+	.write		= ppc4xx_wdt_write,
+	.ioctl		= ppc4xx_wdt_ioctl,
+	.open		= ppc4xx_wdt_open,
+	.release	= ppc4xx_wdt_release,
+};
+
+static struct miscdevice ppc4xx_wdt_miscdev = {
+	.minor	= WATCHDOG_MINOR,
+	.name	= "watchdog",
+	.fops	= &ppc4xx_wdt_fops,
+};
+
+/*
+ *	The WDT card needs to know about shutdowns in order to
+ *	turn WDT off.
+ */
+
+static struct notifier_block ppc4xx_wdt_notifier = {
+	.notifier_call = ppc4xx_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
+ppc4xx_wdt_exit(void)
+{
+	misc_deregister(&ppc4xx_wdt_miscdev);
+	unregister_reboot_notifier(&ppc4xx_wdt_notifier);
+}
+
+/**
+ * 	ppc4xx_wdt_init:
+ *
+ *	Set up the WDT relevant timer facility.
+ */
+
+static int __init
+ppc4xx_wdt_init(void)
+{
+	int ret;
+	unsigned long flags;
+
+	ret = register_reboot_notifier(&ppc4xx_wdt_notifier);
+	if(ret) {
+	  ppc4xx_wdt_err("Cannot register reboot notifier (err=%d)\n", ret);
+	  return ret;
+	}
+
+	ret = 0;
+	ppc4xx_wdt_init_device();
+	/* Check that the heartbeat value is within it's range ; if not reset to the default */
+	if (ppc4xx_wdt_set_timeout(wdt_period)) {
+	  if (wdt_period)
+	    ppc4xx_wdt_info("The heartbeat value must be %d < wdt_period < %d, using 
%d\n",WDT_HEARTBEAT_MIN,WDT_HEARTBEAT_MAX,WDT_TIMO);
+	  ppc4xx_wdt_set_timeout(WDT_TIMO);
+	}
+	
+	local_irq_save(flags); /* Prevent timer interrupt */
+	ppc_md.heartbeat_count = 0;	
+	ppc_md.heartbeat=ppc4xx_wdt_heartbeat;
+	local_irq_restore(flags);
+
+	ppc4xx_wdt_info("PowerPC 4xx Watchdog Driver. period=%d ms (nowayout=%d)\n",wdt_period, nowayout);
+
+	ret = misc_register(&ppc4xx_wdt_miscdev);
+	if (ret) {
+	  ppc4xx_wdt_err("Cannot register miscdev on minor=%d (err=%d)\n",
+			WATCHDOG_MINOR, ret);
+		goto outmisc;
+	}
+
+	if (wdt_enable) {
+	  ppc4xx_wdt_info("WDT start on boot.\n");
+	  ppc4xx_wdt_start();
+	}
+out:
+	return ret;
+outmisc:
+	unregister_reboot_notifier(&ppc4xx_wdt_notifier);
+	local_irq_save(flags);
+	ppc_md.heartbeat=NULL;
+	ppc_md.heartbeat_count = 0;
+	local_irq_restore(flags);
+	goto out;
+}
+
+module_init(ppc4xx_wdt_init);
+module_exit(ppc4xx_wdt_exit);
+
--- linux-2.6.11-rc5.orig/drivers/char/watchdog/ppc4xx_wdt.h	1970-01-01 09:00:00.000000000 +0900
+++ linux-2.6.11-rc5/drivers/char/watchdog/ppc4xx_wdt.h	2005-02-28 19:33:10.000000000 +0900
@@ -0,0 +1,125 @@
+/*
+ *
+ *    Copyright (c) 2004 Fujitsu Limited
+ *
+ *    Module name: ppc4xx_wdt.h
+ *    Author:      Takeharu KATO<kato.takeharu@jp.fujitsu.com>
+ *    Description:
+ *      Header file for PPC4xx 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_PPC4XX_WDT_H
+#define _DRIVERS_CHAR_WATCHDOG_PPC4XX_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 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 PPC4xx cpus. */
+#if defined(CONFIG_4xx)
+/*
+ *  For PowerPC4xx
+ */
+#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 ppc4xx_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 "PPC4xx WDT Detect 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 __PPC4xx_WDT_MSG "PPC4xx WDT : "
+#define ppc4xx_mkmsg(str) __PPC4xx_WDT_MSG str
+#define ppc4xx_wdt_info(fmt,arg...) \
+	printk(KERN_INFO __PPC4xx_WDT_MSG fmt,##arg)
+#define ppc4xx_wdt_note(fmt,arg...) \
+	printk(KERN_NOTICE __PPC4xx_WDT_MSG fmt,##arg)
+#define ppc4xx_wdt_err(fmt,arg...) \
+	printk(KERN_ALERT __PPC4xx_WDT_MSG fmt,##arg)
+#define ppc4xx_wdt_crit(fmt,arg...) \
+	printk(KERN_ALERT __PPC4xx_WDT_MSG fmt,##arg)
+#if defined(WDT_DEBUG)
+#define ppc4xx_wdt_dbg(fmt,arg...) \
+	printk(KERN_ALERT __PPC4xx_WDT_MSG fmt,##arg)
+#else
+#define ppc4xx_wdt_dbg(fmt,arg...) \
+        do{}while(0)
+#endif  /*  WDT_DEBUG  */
+
+#endif  /* __KERNEL__  */
+#endif  /*  _DRIVERS_CHAR_WATCHDOG_PPC4XX_WDT_H  */

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: PowerPC4xx Watchdog
  2005-02-25 19:35     ` PowerPC4xx Watchdog Takeharu KATO
  2005-02-28 13:18       ` [PATCH 1/3] PowerPC4xx/E500 WatchDogTimerDriver(Core and PPC4xx part) Takeharu KATO
@ 2005-02-28 13:20       ` Takeharu KATO
  2005-02-28 13:27       ` [PATCH 3/3] PowerPC4xx/E500 WatchDogTimerDriver(exception handler part) Takeharu KATO
  2 siblings, 0 replies; 33+ messages in thread
From: Takeharu KATO @ 2005-02-28 13:20 UTC (permalink / raw)
  Cc: ppcembed

Dear Matt and all:

This is PowerPC e500 part.

Signed-off-by: Takeharu KATO <kato.takeharu@jp.fujitsu.com>

--- linux-2.6.11-rc5.orig/arch/ppc/platforms/85xx/mpc8540_ads.c	2005-02-27 15:27:54.000000000 +0900
+++ linux-2.6.11-rc5/arch/ppc/platforms/85xx/mpc8540_ads.c	2005-02-28 20:51:45.000000000 +0900
@@ -54,6 +54,7 @@

  #include <syslib/ppc85xx_setup.h>

+
  /* ************************************************************************
   *
   * Setup the architecture
@@ -187,6 +188,14 @@ platform_init(unsigned long r3, unsigned
  		strcpy(cmd_line, (char *) (r6 + KERNELBASE));
  	}

+#ifdef CONFIG_PPC4xx_WATCHDOG
+	{
+	  extern void ppc4xx_wdt_setup_options(char *cmd_line);
+
+	  ppc4xx_wdt_setup_options(cmd_line);
+	}
+#endif  /*  CONFIG_PPC4xx_WATCHDOG  */
+
  	identify_ppc_sys_by_id(mfspr(SVR));

  	/* setup the PowerPC module struct */
--- linux-2.6.11-rc5.orig/arch/ppc/platforms/85xx/mpc8560_ads.c	2005-02-27 15:31:26.000000000 +0900
+++ linux-2.6.11-rc5/arch/ppc/platforms/85xx/mpc8560_ads.c	2005-02-28 20:51:45.000000000 +0900
@@ -197,6 +197,14 @@ platform_init(unsigned long r3, unsigned
  		strcpy(cmd_line, (char *) (r6 + KERNELBASE));
  	}

+#ifdef CONFIG_PPC4xx_WATCHDOG
+	{
+	  extern void ppc4xx_wdt_setup_options(char *cmd_line);
+
+	  ppc4xx_wdt_setup_options(cmd_line);
+	}
+#endif  /*  CONFIG_PPC4xx_WATCHDOG  */
+
  	identify_ppc_sys_by_id(mfspr(SVR));

  	/* setup the PowerPC module struct */
--- linux-2.6.11-rc5.orig/arch/ppc/platforms/85xx/mpc85xx_cds_common.c	2005-02-27 15:30:26.000000000 
+0900
+++ linux-2.6.11-rc5/arch/ppc/platforms/85xx/mpc85xx_cds_common.c	2005-02-28 20:51:45.000000000 +0900
@@ -437,6 +437,14 @@ platform_init(unsigned long r3, unsigned
                  strcpy(cmd_line, (char *) (r6 + KERNELBASE));
          }

+#ifdef CONFIG_PPC4xx_WATCHDOG
+	{
+	  extern void ppc4xx_wdt_setup_options(char *cmd_line);
+
+	  ppc4xx_wdt_setup_options(cmd_line);
+	}
+#endif  /*  CONFIG_PPC4xx_WATCHDOG  */
+
  	identify_ppc_sys_by_id(mfspr(SVR));

          /* setup the PowerPC module struct */
--- linux-2.6.11-rc5.orig/arch/ppc/platforms/85xx/sbc8560.c	2005-02-27 15:31:09.000000000 +0900
+++ linux-2.6.11-rc5/arch/ppc/platforms/85xx/sbc8560.c	2005-02-28 20:51:45.000000000 +0900
@@ -198,6 +198,14 @@ platform_init(unsigned long r3, unsigned
  		strcpy(cmd_line, (char *) (r6 + KERNELBASE));
  	}

+#ifdef CONFIG_PPC4xx_WATCHDOG
+	{
+	  extern void ppc4xx_wdt_setup_options(char *cmd_line);
+
+	  ppc4xx_wdt_setup_options(cmd_line);
+	}
+#endif  /*  CONFIG_PPC4xx_WATCHDOG  */
+
  	identify_ppc_sys_by_id(mfspr(SVR));

  	/* setup the PowerPC module struct */
--- linux-2.6.11-rc5.orig/arch/ppc/platforms/85xx/stx_gp3.c	2005-02-27 15:28:44.000000000 +0900
+++ linux-2.6.11-rc5/arch/ppc/platforms/85xx/stx_gp3.c	2005-02-28 20:51:45.000000000 +0900
@@ -68,6 +68,7 @@ unsigned long isa_mem_base = 0;
  unsigned long pci_dram_offset = 0;
  #endif

+
  /* Internal interrupts are all Level Sensitive, and Positive Polarity */
  static u8 gp3_openpic_initsenses[] __initdata = {
  	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  0: L2 Cache */
@@ -357,6 +358,14 @@ platform_init(unsigned long r3, unsigned
  		strcpy(cmd_line, (char *) (r6 + KERNELBASE));
  	}

+#ifdef CONFIG_PPC4xx_WATCHDOG
+	{
+	  extern void ppc4xx_wdt_setup_options(char *cmd_line);
+
+	  ppc4xx_wdt_setup_options(cmd_line);
+	}
+#endif  /*  CONFIG_PPC4xx_WATCHDOG  */
+
  	identify_ppc_sys_by_id(mfspr(SVR));

  	/* setup the PowerPC module struct */

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH 3/3] PowerPC4xx/E500 WatchDogTimerDriver(exception handler part)
  2005-02-25 19:35     ` PowerPC4xx Watchdog Takeharu KATO
  2005-02-28 13:18       ` [PATCH 1/3] PowerPC4xx/E500 WatchDogTimerDriver(Core and PPC4xx part) Takeharu KATO
  2005-02-28 13:20       ` PowerPC4xx Watchdog Takeharu KATO
@ 2005-02-28 13:27       ` Takeharu KATO
  2005-03-03  7:14         ` Kumar Gala
  2005-03-03 12:07         ` Takeharu KATO
  2 siblings, 2 replies; 33+ messages in thread
From: Takeharu KATO @ 2005-02-28 13:27 UTC (permalink / raw)
  To: Matt Porter; +Cc: ppcembed

Dear Matt and all:

This is PowerPC405 exception handling part.
This patch consist of two parts.

I create this just in case, if you think that this is not needed,
please ignore them.

1) WatchDogException vector routine for ppc4xx.
    It cause Oops with MachineCheckException as other PPC4xx do.
2) Trivial bug fix in head_booke.h
    Trivial bug fix of CRITICAL_EXCEPTION macro.

Signed-off-by: Takeharu KATO <kato.takeharu@jp.fujitsu.com>


diff -uprN linux-2.6.11-rc5.orig/arch/ppc/kernel/head_4xx.S 
linux-2.6.11-rc5-ppc4xx/arch/ppc/kernel/head_4xx.S
--- linux-2.6.11-rc5.orig/arch/ppc/kernel/head_4xx.S	2005-02-27 15:30:39.000000000 +0900
+++ linux-2.6.11-rc5-ppc4xx/arch/ppc/kernel/head_4xx.S	2005-02-28 21:47:42.531317912 +0900
@@ -484,11 +484,11 @@ label:
  */
  	STND_EXCEPTION(0x1010,	FITException,		UnknownException)

+#endif
  /* 0x1020 - Watchdog Timer (WDT) Exception
  */

  	CRITICAL_EXCEPTION(0x1020, WDTException, UnknownException)
-#endif

  /* 0x1100 - Data TLB Miss Exception
   * As the name implies, translation is not in the MMU, so search the
diff -uprN linux-2.6.11-rc5.orig/arch/ppc/kernel/head_booke.h 
linux-2.6.11-rc5-ppc4xx/arch/ppc/kernel/head_booke.h
--- linux-2.6.11-rc5.orig/arch/ppc/kernel/head_booke.h	2005-02-27 15:27:12.000000000 +0900
+++ linux-2.6.11-rc5-ppc4xx/arch/ppc/kernel/head_booke.h	2005-02-28 21:50:05.060650160 +0900
@@ -194,8 +194,8 @@ label:
  	CRITICAL_EXCEPTION_PROLOG;				\
  	addi	r3,r1,STACK_FRAME_OVERHEAD;			\
  	EXC_XFER_TEMPLATE(hdlr, n+2, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \
-			  NOCOPY, transfer_to_handler_full, \
-			  ret_from_except_full)
+			  NOCOPY, crit_transfer_to_handler, \
+			  ret_from_crit_exc)

  #define MCHECK_EXCEPTION(n, label, hdlr)			\
  	START_EXCEPTION(label);					\

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: PowerPC4xx Watchdog
  2005-02-23 23:36       ` Takeharu KATO
@ 2005-03-02 17:52         ` Matt Porter
  2005-03-02 23:06           ` Kumar Gala
  0 siblings, 1 reply; 33+ messages in thread
From: Matt Porter @ 2005-03-02 17:52 UTC (permalink / raw)
  To: Takeharu KATO; +Cc: ppcembed

On Thu, Feb 24, 2005 at 08:36:21AM +0900, Takeharu KATO wrote:
> Hi
> 
> >> Are you looking for the old "ppc405 watchdog" driver that simply
> >> hooked into the generic PPC heartbeat facility? Or are you looking
> >> for a driver that utilizes the 4xx/booke hardware watchdog facility?
> >>
> > I am looking for a driver that utilizes the 4xx/booke hardware watchdog 
> > facility.
> > 
> > 
> FYI, I wrote a driver uses 4xx/booke hardware watchdog.
> BTW, is hooking PPC heartbeat facility obsoleted?

I see.  The ppc_md.heartbeat facility isn't going anywhere as there
are multiple users.  It's possible to take the "ppc405_wdt" driver
with a rename and minor cleanup have it be a generic timebase driven
watchdog driver that is compliant with the familiar WD interface.

What do you see as the advantage to having a watchdog driver
that uses the booke hardware watchdog facility over a generic
timebase driven driver?

-Matt

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: PowerPC4xx Watchdog
  2005-03-02 17:52         ` Matt Porter
@ 2005-03-02 23:06           ` Kumar Gala
  2005-03-02 23:15             ` Matt Porter
  0 siblings, 1 reply; 33+ messages in thread
From: Kumar Gala @ 2005-03-02 23:06 UTC (permalink / raw)
  To: Matt Porter; +Cc: ppcembed

Matt,

[snip]

> What do you see as the advantage to having a watchdog driver
>  that uses the booke hardware watchdog facility over a generic
>  timebase driven driver?

I would think the watchdog would be useful in cases that the normal 
decrementer exceptions gets disabled when MSR[EE] = 0.

- kumar

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: PowerPC4xx Watchdog
  2005-03-02 23:06           ` Kumar Gala
@ 2005-03-02 23:15             ` Matt Porter
  2005-03-03 11:50               ` Takeharu KATO
  0 siblings, 1 reply; 33+ messages in thread
From: Matt Porter @ 2005-03-02 23:15 UTC (permalink / raw)
  To: Kumar Gala; +Cc: ppcembed

On Wed, Mar 02, 2005 at 05:06:31PM -0600, Kumar Gala wrote:
> Matt,
> 
> [snip]
> 
> > What do you see as the advantage to having a watchdog driver
> >  that uses the booke hardware watchdog facility over a generic
> >  timebase driven driver?
> 
> I would think the watchdog would be useful in cases that the normal 
> decrementer exceptions gets disabled when MSR[EE] = 0.

That's the only thing I can think of.  I guess my question then
is whether people think this is important enough in practice
to have the hardware watchdog as an alternative. My guess is yes,
but I don't have a strong opinion. 

-Matt

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH 3/3] PowerPC4xx/E500 WatchDogTimerDriver(exception handler part)
  2005-02-28 13:27       ` [PATCH 3/3] PowerPC4xx/E500 WatchDogTimerDriver(exception handler part) Takeharu KATO
@ 2005-03-03  7:14         ` Kumar Gala
  2005-03-03  7:31           ` Takeharu KATO
  2005-03-03 12:07         ` Takeharu KATO
  1 sibling, 1 reply; 33+ messages in thread
From: Kumar Gala @ 2005-03-03  7:14 UTC (permalink / raw)
  To: Takeharu KATO; +Cc: ppcembed

I've sent the part of this that was a bug fix to head_booke.h up stream=20=

to andrew.

- kumar

On Feb 28, 2005, at 7:27 AM, Takeharu KATO wrote:

> Dear Matt and all:
>
> This is PowerPC405 exception handling part.
>  This patch consist of two parts.
>
> I create this just in case, if you think that this is not needed,
>  please ignore them.
>
> 1) WatchDogException vector routine for ppc4xx.
>  =A0=A0=A0 It cause Oops with MachineCheckException as other PPC4xx =
do.
>  2) Trivial bug fix in head_booke.h
> =A0=A0=A0 Trivial bug fix of CRITICAL_EXCEPTION macro.
>
> Signed-off-by: Takeharu KATO <kato.takeharu@jp.fujitsu.com>
>
>
>
> diff -uprN linux-2.6.11-rc5.orig/arch/ppc/kernel/head_4xx.S
>  linux-2.6.11-rc5-ppc4xx/arch/ppc/kernel/head_4xx.S
> --- linux-2.6.11-rc5.orig/arch/ppc/kernel/head_4xx.S=A0=A0=A0 =
2005-02-27=20
> 15:30:39.000000000 +0900
>  +++ linux-2.6.11-rc5-ppc4xx/arch/ppc/kernel/head_4xx.S=A0 2005-02-28=20=

> 21:47:42.531317912 +0900
>  @@ -484,11 +484,11 @@ label:
>  =A0 */
>  =A0 =A0=A0=A0=A0=A0 STND_EXCEPTION(0x1010,=A0 FITException,=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0=20
> UnknownException)
>
> +#endif
>  =A0 /* 0x1020 - Watchdog Timer (WDT) Exception
>  =A0 */
>
> =A0 =A0=A0=A0=A0=A0 CRITICAL_EXCEPTION(0x1020, WDTException, =
UnknownException)
> -#endif
>
> =A0 /* 0x1100 - Data TLB Miss Exception
>  =A0=A0 * As the name implies, translation is not in the MMU, so =
search the
>  diff -uprN linux-2.6.11-rc5.orig/arch/ppc/kernel/head_booke.h
>  linux-2.6.11-rc5-ppc4xx/arch/ppc/kernel/head_booke.h
> --- linux-2.6.11-rc5.orig/arch/ppc/kernel/head_booke.h=A0 2005-02-27=20=

> 15:27:12.000000000 +0900
>  +++ linux-2.6.11-rc5-ppc4xx/arch/ppc/kernel/head_booke.h=A0=A0=A0=A0=A0=
=A0=A0=20
> 2005-02-28 21:50:05.060650160 +0900
>  @@ -194,8 +194,8 @@ label:
>  =A0 =A0=A0=A0=A0=A0 CRITICAL_EXCEPTION_PROLOG;=A0=A0=A0=A0=A0 =A0=A0=A0=
=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 \
>  =A0 =A0=A0=A0=A0=A0 addi=A0=A0=A0 r3,r1,STACK_FRAME_OVERHEAD;=A0=A0=A0=A0=
 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 \
>  =A0 =A0=A0=A0=A0=A0 EXC_XFER_TEMPLATE(hdlr, n+2, (MSR_KERNEL &=20
> ~(MSR_ME|MSR_DE|MSR_CE)), \
>  -=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0 =
NOCOPY, transfer_to_handler_full, \
>  -=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0 =
ret_from_except_full)
> +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0 =
NOCOPY, crit_transfer_to_handler, \
>  +=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0 =
ret_from_crit_exc)
>
> =A0 #define MCHECK_EXCEPTION(n, label, hdlr)=A0=A0=A0=A0=A0 =A0=A0=A0=A0=
=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 \
>  =A0 =A0=A0=A0=A0=A0 START_EXCEPTION(label); =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 \
>
>
>
> _______________________________________________
> Linuxppc-embedded mailing list
>  Linuxppc-embedded@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-embedded

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH 3/3] PowerPC4xx/E500 WatchDogTimerDriver(exception handler part)
  2005-03-03  7:14         ` Kumar Gala
@ 2005-03-03  7:31           ` Takeharu KATO
  0 siblings, 0 replies; 33+ messages in thread
From: Takeharu KATO @ 2005-03-03  7:31 UTC (permalink / raw)
  To: Kumar Gala; +Cc: ppcembed

Hi

Kumar Gala wrote:

> I've sent the part of this that was a bug fix to head_booke.h up stream 
> to andrew.
> 
> - kumar
> 
Thank you, I confirmed your mail to akpm.


-- 
Takeharu KATO
Fujitsu Limited
Email:kato.takeharu at jp.fujitsu.com

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: PowerPC4xx Watchdog
  2005-03-02 23:15             ` Matt Porter
@ 2005-03-03 11:50               ` Takeharu KATO
  2005-03-03 12:13                 ` Takeharu KATO
  0 siblings, 1 reply; 33+ messages in thread
From: Takeharu KATO @ 2005-03-03 11:50 UTC (permalink / raw)
  To: Matt Porter; +Cc: ppcembed

Matt and Kurmar,

Thank you for your response.

 >>>What do you see as the advantage to having a watchdog driver
 >>> that uses the booke hardware watchdog facility over a generic
 >>> timebase driven driver?
 >>
I do not think that there is especially an important
reason to use the hardware watchdog as your saying
though it noticed by thinking later.

Therefore, I agrees the shortest way of implementing
the driver is fixing minor things of a old ppc405 driver.

However, I posted the new driver for the following reasons.

1) The old driver depends on HZ value (10ms).
2) The old driver doesn't support e500.
3) When the last mail was sent, it had finished
    writing the driver to certain extent.

So, we are
 > That's the only thing I can think of.  I guess my question then
 > is whether people think this is important enough in practice
 > to have the hardware watchdog as an alternative. My guess is yes,
 > but I don't have a strong opinion.
 >
I also thought like that before.

Certainly, this case doesn't become a big problem
while it is developing on the evaluation boards.

However, a lot of users think that they install
Linux on the custom board, and ships the product.
When the problem of causing hanging up with the interruption disabled
occurs on the custom board, pursuing the cause becomes very
difficult.

In the case that we experienced, it kept operating with the device
  driver became an interruption prohibition, and hanging up was caused
very unusually occasionally.
To solve this problem, we are consuming time of about half a year.

Because the incidence of the problem is very low,
it is important to  the generation part such a problem when generated.

In this case, WDT driver may be good help.

Regards,

-- 
Takeharu KATO
Fujitsu Limited
Email:kato.takeharu at jp.fujitsu.com

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH 3/3] PowerPC4xx/E500 WatchDogTimerDriver(exception handler part)
  2005-02-28 13:27       ` [PATCH 3/3] PowerPC4xx/E500 WatchDogTimerDriver(exception handler part) Takeharu KATO
  2005-03-03  7:14         ` Kumar Gala
@ 2005-03-03 12:07         ` Takeharu KATO
  1 sibling, 0 replies; 33+ messages in thread
From: Takeharu KATO @ 2005-03-03 12:07 UTC (permalink / raw)
  To: Takeharu KATO; +Cc: ppcembed

Dear all:

I fix PowerPC405 exception handling part.
This patch corrects the problem of having not stopped WDT
when the WDT exception is generated.
This patch also stop WDT when the system fall in panic.

Signed-off-by: Takeharu KATO <kato.takeharu@jp.fujitsu.com>


--- linux-2.6.11-rc5-ppc4xx/arch/ppc/kernel/head_44x.S	2005-02-27 15:27:46.000000000 +0900
+++ linux-2.6.11-rc5/arch/ppc/kernel/head_44x.S	2005-03-03 18:09:03.000000000 +0900
@@ -444,8 +444,11 @@ interrupt_base:
  	EXCEPTION(0x1010, FixedIntervalTimer, UnknownException, EXC_XFER_EE)

  	/* Watchdog Timer Interrupt */
-	/* TODO: Add watchdog support */
+#if defined(CONFIG_PPC4xx_WATCHDOG)
+	CRITICAL_EXCEPTION(0x1020, WatchdogTimer, ppc4xx_wdt_exception)
+#else
  	CRITICAL_EXCEPTION(0x1020, WatchdogTimer, UnknownException)
+#endif

  	/* Data TLB Error Interrupt */
  	START_EXCEPTION(DataTLBError)
diff -uprN linux-2.6.11-rc5-ppc4xx/arch/ppc/kernel/head_4xx.S 
linux-2.6.11-rc5/arch/ppc/kernel/head_4xx.S
--- linux-2.6.11-rc5-ppc4xx/arch/ppc/kernel/head_4xx.S	2005-03-03 18:30:12.000000000 +0900
+++ linux-2.6.11-rc5/arch/ppc/kernel/head_4xx.S	2005-03-03 18:09:04.000000000 +0900
@@ -477,17 +477,21 @@ label:

  #if 0
  /* NOTE:
- * FIT and WDT handlers are not implemented yet.
+ * FIT handler is not implemented yet.
   */

  /* 0x1010 - Fixed Interval Timer (FIT) Exception
  */
  	STND_EXCEPTION(0x1010,	FITException,		UnknownException)

+#endif
+
  /* 0x1020 - Watchdog Timer (WDT) Exception
  */
-
-	CRITICAL_EXCEPTION(0x1020, WDTException, UnknownException)
+#if defined(CONFIG_PPC4xx_WATCHDOG)
+	CRITICAL_EXCEPTION(0x1020, WDTException, ppc4xx_wdt_exception)
+#else
+ 	CRITICAL_EXCEPTION(0x1020, WDTException, UnknownException)
  #endif

  /* 0x1100 - Data TLB Miss Exception
diff -uprN linux-2.6.11-rc5-ppc4xx/arch/ppc/kernel/head_e500.S 
linux-2.6.11-rc5/arch/ppc/kernel/head_e500.S
--- linux-2.6.11-rc5-ppc4xx/arch/ppc/kernel/head_e500.S	2005-02-27 15:29:39.000000000 +0900
+++ linux-2.6.11-rc5/arch/ppc/kernel/head_e500.S	2005-03-03 18:09:04.000000000 +0900
@@ -494,8 +494,12 @@ interrupt_base:
  	EXCEPTION(0x3100, FixedIntervalTimer, UnknownException, EXC_XFER_EE)

  	/* Watchdog Timer Interrupt */
-	/* TODO: Add watchdog support */
+#if defined(CONFIG_PPC4xx_WATCHDOG)
+	CRITICAL_EXCEPTION(0x3200, WatchdogTimer, ppc4xx_wdt_exception)
+#else
  	CRITICAL_EXCEPTION(0x3200, WatchdogTimer, UnknownException)
+#endif
+

  	/* Data TLB Error Interrupt */
  	START_EXCEPTION(DataTLBError)
diff -uprN linux-2.6.11-rc5-ppc4xx/drivers/char/watchdog/ppc4xx_wdt.c 
linux-2.6.11-rc5/drivers/char/watchdog/ppc4xx_wdt.c
--- linux-2.6.11-rc5-ppc4xx/drivers/char/watchdog/ppc4xx_wdt.c	2005-03-03 18:28:33.000000000 +0900
+++ linux-2.6.11-rc5/drivers/char/watchdog/ppc4xx_wdt.c	2005-03-03 20:29:16.946286104 +0900
@@ -66,12 +66,18 @@ static struct watchdog_info ident = {
    .firmware_version =	0, /*  This is filled with PVR in initialization. */
    .identity =		"PPC4xx 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 ppc4xx_wdt_heartbeat(void);
  void ppc4xx_wdt_setup_options(char *cmd_line);
+void ppc4xx_wdt_exception(struct pt_regs *regs);
  /*
   * Internal linkage functions
   */
@@ -243,7 +249,7 @@ ppc4xx_wdt_heartbeat(void)

    if (!wdt_enable)
      goto out;
-
+
    if  (wdt_heartbeat_count > 0)
      wdt_heartbeat_count--;
    else
@@ -255,6 +261,20 @@ ppc4xx_wdt_heartbeat(void)
    /*  Reset count  */
    ppc_md.heartbeat_count = 0;
  }
+/**
+ *	ppc4xx_wdt_exception:
+ *      WatchDog Exception
+ */
+void
+ppc4xx_wdt_exception(struct pt_regs *regs)
+{
+  wdt_enable=0;
+
+  __ppc4xx_wdt_disable();
+  printk("WDT Exception at PC: %lx, MSR: %lx, vector=%lx    %s\n",
+	 regs->nip, regs->msr, regs->trap, print_tainted());
+  panic(ppc4xx_mkmsg("Initiating system reboot.\n"));
+}
  \f
  /*
   *	Driver Logic functions
@@ -526,10 +546,9 @@ static int
  ppc4xx_wdt_notify_sys(struct notifier_block *this, unsigned long code,
  	void *unused)
  {
-	if(code==SYS_DOWN || code==SYS_HALT) {
-	  /* Turn the card off */
+	if (code != SYS_POWER_OFF)   /* Turn the card off */
  	  ppc4xx_wdt_stop();
-	}
+	
  	return NOTIFY_DONE;
  }

@@ -572,6 +591,7 @@ ppc4xx_wdt_exit(void)
  {
  	misc_deregister(&ppc4xx_wdt_miscdev);
  	unregister_reboot_notifier(&ppc4xx_wdt_notifier);
+	notifier_chain_unregister(&panic_notifier_list,&ppc4xx_wdt_notifier);
  }

  /**
@@ -592,6 +612,14 @@ ppc4xx_wdt_init(void)
  	  return ret;
  	}

+	/* Register panic notifier  */
+	ret = notifier_chain_register(&panic_notifier_list,&ppc4xx_wdt_notifier);
+	if(ret) {
+	  ppc4xx_wdt_err("Cannot register panic notifier (err=%d)\n", ret);
+	  unregister_reboot_notifier(&ppc4xx_wdt_notifier);
+	  return ret;
+	}
+
  	ret = 0;
  	ppc4xx_wdt_init_device();
  	/* Check that the heartbeat value is within it's range ; if not reset to the default */


-- 
Takeharu KATO
Fujitsu Limited
Email:kato.takeharu at jp.fujitsu.com

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: PowerPC4xx Watchdog
  2005-03-03 11:50               ` Takeharu KATO
@ 2005-03-03 12:13                 ` Takeharu KATO
  2005-03-03 14:53                   ` Kumar Gala
  0 siblings, 1 reply; 33+ messages in thread
From: Takeharu KATO @ 2005-03-03 12:13 UTC (permalink / raw)
  To: Takeharu KATO; +Cc: ppcembed

Matt and Kurmar:

Sorry to typo:
> Because the incidence of the problem is very low,
> it is important to  the generation part such a problem when generated.
> 

I was going to have written the following things, to make sure though
it is likely already to have understood:

Because the incidence of the problem is very low,
WDT is important to find the generation part such a problem when generated.


-- 
Takeharu KATO
Fujitsu Limited
Email:kato.takeharu at jp.fujitsu.com

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: PowerPC4xx Watchdog
  2005-03-03 12:13                 ` Takeharu KATO
@ 2005-03-03 14:53                   ` Kumar Gala
  2005-03-03 15:20                     ` Matt Porter
  2005-03-03 15:21                     ` Takeharu KATO
  0 siblings, 2 replies; 33+ messages in thread
From: Kumar Gala @ 2005-03-03 14:53 UTC (permalink / raw)
  To: Takeharu KATO; +Cc: ppcembed

One thing the code needs is a general name cleanup.  Its just confusing=20=

to me for e500 to have 4xx references.

- kumar

On Mar 3, 2005, at 6:13 AM, Takeharu KATO wrote:

> Matt and Kurmar:
>
> Sorry to typo:
>  > Because the incidence of the problem is very low,
>  > it is important to=A0 the generation part such a problem when=20
> generated.
>  >
>
>  I was going to have written the following things, to make sure though
>  it is likely already to have understood:
>
> Because the incidence of the problem is very low,
>  WDT is important to find the generation part such a problem when=20
> generated.
>
>
>
> --=20
> Takeharu KATO
>  Fujitsu Limited
>  Email:kato.takeharu at jp.fujitsu.com

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: PowerPC4xx Watchdog
  2005-03-03 14:53                   ` Kumar Gala
@ 2005-03-03 15:20                     ` Matt Porter
  2005-03-03 15:21                     ` Takeharu KATO
  1 sibling, 0 replies; 33+ messages in thread
From: Matt Porter @ 2005-03-03 15:20 UTC (permalink / raw)
  To: Kumar Gala; +Cc: ppcembed

On Thu, Mar 03, 2005 at 08:53:15AM -0600, Kumar Gala wrote:
> One thing the code needs is a general name cleanup.  Its just confusing 
> to me for e500 to have 4xx references.

I suggest booke_wdt* since the Book E spec is where this feature
came from.

Since you already picked up the bug-fix patch, we just need a two
part patch with the name cleanup where 1) arch-specific code
2) driver portion.

-Matt

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: PowerPC4xx Watchdog
  2005-03-03 14:53                   ` Kumar Gala
  2005-03-03 15:20                     ` Matt Porter
@ 2005-03-03 15:21                     ` Takeharu KATO
  2005-03-03 17:11                       ` Matt Porter
  1 sibling, 1 reply; 33+ messages in thread
From: Takeharu KATO @ 2005-03-03 15:21 UTC (permalink / raw)
  To: Kumar Gala; +Cc: ppcembed

Hi Kumar,

Thank you for your suggestion.
Kumar Gala wrote:
> One thing the code needs is a general name cleanup.  Its just confusing 
> to me for e500 to have 4xx references.
> 
How about the use of booke instead of 4xx?

I seem to use ``booke'' for common name for them like 
arch/ppc/kernel/head_booke.h in the kernel source.

Strictly speaking, PowerPC4xx series may not be called booke.
But I think that it is more preferable than current name.

-- 
Takeharu KATO

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: PowerPC4xx Watchdog
  2005-03-03 15:21                     ` Takeharu KATO
@ 2005-03-03 17:11                       ` Matt Porter
  2005-03-04  9:38                         ` [PATCH] WDT Driver for Book-E [1/2] Architecture specific part Takeharu KATO
  2005-03-04  9:38                         ` [PATCH] WDT Driver for Book-E [2/2] Device driver part Takeharu KATO
  0 siblings, 2 replies; 33+ messages in thread
From: Matt Porter @ 2005-03-03 17:11 UTC (permalink / raw)
  To: Takeharu KATO; +Cc: ppcembed

On Fri, Mar 04, 2005 at 12:21:13AM +0900, Takeharu KATO wrote:
> Hi Kumar,
> 
> Thank you for your suggestion.
> Kumar Gala wrote:
> > One thing the code needs is a general name cleanup.  Its just confusing 
> > to me for e500 to have 4xx references.
> > 
> How about the use of booke instead of 4xx?

Yes, please. :)

> I seem to use ``booke'' for common name for them like 
> arch/ppc/kernel/head_booke.h in the kernel source.
> 
> Strictly speaking, PowerPC4xx series may not be called booke.
> But I think that it is more preferable than current name.

440 is strictly Book E, 405 is a hybrid that pulled borrowed
from Green book and Book E.

-Matt

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH] WDT Driver for Book-E [1/2] Architecture specific part.
  2005-03-03 17:11                       ` Matt Porter
@ 2005-03-04  9:38                         ` Takeharu KATO
  2005-03-04 15:54                           ` Kumar Gala
  2005-03-04  9:38                         ` [PATCH] WDT Driver for Book-E [2/2] Device driver part Takeharu KATO
  1 sibling, 1 reply; 33+ messages in thread
From: Takeharu KATO @ 2005-03-04  9:38 UTC (permalink / raw)
  To: Matt Porter; +Cc: ppcembed

Matt and Kurmar:

I performed name-cleanup in the driver.

Moreover, I tested this driver with PowerPC405GPr(Sycamore)
in addition to PowerPC440GP(ebony)/MPC8555(MPC8555-CDS).

This driver consist of two patches as follows:

1) Architecture specific part(booke_wdt-arch.patch)
This is the architecture specific part of the driver.
It contains WDT exception handlers
and kernel command line processing
routines.

2) Device driver part(booke_wdt-drv.patch)
This is the core of this WDT
driver.

At first, I post the architecture specific part with this mail.

Please apply.

Regards,

Signed-off-by: Takeharu KATO <kato.takeharu@jp.fujitsu.com>

--- linux-2.6.11/arch/ppc/kernel/head_44x.S	2005-03-04 17:12:42.944450424 +0900
+++ linux-2.6.11-booke-wdt/arch/ppc/kernel/head_44x.S	2005-03-04 13:21:31.000000000 +0900
@@ -444,8 +444,12 @@ interrupt_base:
  	EXCEPTION(0x1010, FixedIntervalTimer, UnknownException, EXC_XFER_EE)

  	/* Watchdog Timer Interrupt */
-	/* TODO: Add watchdog support */
+#if defined(CONFIG_BOOKE_WDT)
+	CRITICAL_EXCEPTION(0x1020, WatchdogTimer, booke_wdt_exception)
+#else
  	CRITICAL_EXCEPTION(0x1020, WatchdogTimer, UnknownException)
+#endif  /*  CONFIG_BOOKE_WDT  */
+	

  	/* Data TLB Error Interrupt */
  	START_EXCEPTION(DataTLBError)
--- linux-2.6.11/arch/ppc/kernel/head_4xx.S	2005-03-04 17:16:48.089182760 +0900
+++ linux-2.6.11-booke-wdt/arch/ppc/kernel/head_4xx.S	2005-03-04 13:21:31.000000000 +0900
@@ -469,27 +469,23 @@ label:

  /* 0x1000 - Programmable Interval Timer (PIT) Exception */
  	START_EXCEPTION(0x1000, Decrementer)
-	NORMAL_EXCEPTION_PROLOG
-	lis	r0,TSR_PIS@h
-	mtspr	SPRN_TSR,r0		/* Clear the PIT exception */
-	addi	r3,r1,STACK_FRAME_OVERHEAD
-	EXC_XFER_LITE(0x1000, timer_interrupt)
-
+	b	DecrementerHandler
  #if 0
  /* NOTE:
- * FIT and WDT handlers are not implemented yet.
+ * FIT handler are not implemented yet.
   */

  /* 0x1010 - Fixed Interval Timer (FIT) Exception
  */
  	STND_EXCEPTION(0x1010,	FITException,		UnknownException)

-/* 0x1020 - Watchdog Timer (WDT) Exception
-*/
-
-	CRITICAL_EXCEPTION(0x1020, WDTException, UnknownException)
  #endif

+  /* 0x1020 - Watchdog Timer (WDT) Exception
+  */
+	START_EXCEPTION(0x1020, WDTException)
+	b	WatchDogHandler
+
  /* 0x1100 - Data TLB Miss Exception
   * As the name implies, translation is not in the MMU, so search the
   * page tables and fix it.  The only purpose of this function is to
@@ -771,6 +767,14 @@ label:
  		(MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \
  		NOCOPY, crit_transfer_to_handler, ret_from_crit_exc)

+
+DecrementerHandler:
+	NORMAL_EXCEPTION_PROLOG
+	lis	r0,TSR_PIS@h
+	mtspr	SPRN_TSR,r0		/* Clear the PIT exception */
+	addi	r3,r1,STACK_FRAME_OVERHEAD
+	EXC_XFER_LITE(0x1000, timer_interrupt)
+
  /*
   * The other Data TLB exceptions bail out to this point
   * if they can't resolve the lightweight TLB fault.
@@ -844,6 +848,19 @@ finish_tlb_load:
  	rfi			/* Should sync shadow TLBs */
  	b	.		/* prevent prefetch past rfi */

+/*
+ * WatchDog Exception
+ */
+WatchDogHandler:
+	CRITICAL_EXCEPTION_PROLOG;
+	addi	r3,r1,STACK_FRAME_OVERHEAD;
+#if defined(CONFIG_BOOKE_WDT)
+	EXC_XFER_TEMPLATE(booke_wdt_exception, 0x1022, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)),NOCOPY, 
crit_transfer_to_handler, ret_from_crit_exc)
+
+#else
+	EXC_XFER_TEMPLATE(UnknownException, 0x1022, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)),NOCOPY, 
crit_transfer_to_handler, ret_from_crit_exc)
+#endif  /*  CONFIG_BOOKE_WDT  */
+
  /* extern void giveup_fpu(struct task_struct *prev)
   *
   * The PowerPC 4xx family of processors do not have an FPU, so this just
--- linux-2.6.11/arch/ppc/kernel/head_e500.S	2005-03-04 17:15:36.641044528 +0900
+++ linux-2.6.11-booke-wdt/arch/ppc/kernel/head_e500.S	2005-03-04 13:21:31.000000000 +0900
@@ -494,8 +494,11 @@ interrupt_base:
  	EXCEPTION(0x3100, FixedIntervalTimer, UnknownException, EXC_XFER_EE)

  	/* Watchdog Timer Interrupt */
-	/* TODO: Add watchdog support */
+#if defined(CONFIG_BOOKE_WDT)
+	CRITICAL_EXCEPTION(0x3200, WatchdogTimer, booke_wdt_exception)
+#else
  	CRITICAL_EXCEPTION(0x3200, WatchdogTimer, UnknownException)
+#endif  /*  CONFIG_BOOKE_WDT  */

  	/* Data TLB Error Interrupt */
  	START_EXCEPTION(DataTLBError)
--- linux-2.6.11/arch/ppc/platforms/85xx/mpc8540_ads.c	2005-03-04 17:13:11.927044400 +0900
+++ linux-2.6.11-booke-wdt/arch/ppc/platforms/85xx/mpc8540_ads.c	2005-03-04 13:21:31.000000000 +0900
@@ -54,6 +54,7 @@

  #include <syslib/ppc85xx_setup.h>

+
  /* ************************************************************************
   *
   * Setup the architecture
@@ -187,6 +188,14 @@ platform_init(unsigned long r3, unsigned
  		strcpy(cmd_line, (char *) (r6 + KERNELBASE));
  	}

+#ifdef CONFIG_BOOKE_WDT
+     {
+       extern void booke_wdt_setup_options(char *cmd_line);
+
+       booke_wdt_setup_options(cmd_line);
+     }
+#endif  /*  CONFIG_BOOKE_WDT  */
+
  	identify_ppc_sys_by_id(mfspr(SVR));

  	/* setup the PowerPC module struct */
--- linux-2.6.11/arch/ppc/platforms/85xx/mpc8560_ads.c	2005-03-04 17:17:54.566076736 +0900
+++ linux-2.6.11-booke-wdt/arch/ppc/platforms/85xx/mpc8560_ads.c	2005-03-04 13:21:31.000000000 +0900
@@ -197,6 +197,14 @@ platform_init(unsigned long r3, unsigned
  		strcpy(cmd_line, (char *) (r6 + KERNELBASE));
  	}

+#ifdef CONFIG_BOOKE_WDT
+     {
+       extern void booke_wdt_setup_options(char *cmd_line);
+
+       booke_wdt_setup_options(cmd_line);
+     }
+#endif  /*  CONFIG_BOOKE_WDT  */
+
  	identify_ppc_sys_by_id(mfspr(SVR));

  	/* setup the PowerPC module struct */
--- linux-2.6.11/arch/ppc/platforms/85xx/mpc85xx_cds_common.c	2005-03-04 17:16:27.056380232 +0900
+++ linux-2.6.11-booke-wdt/arch/ppc/platforms/85xx/mpc85xx_cds_common.c	2005-03-04 
13:21:31.000000000 +0900
@@ -437,6 +437,14 @@ platform_init(unsigned long r3, unsigned
                  strcpy(cmd_line, (char *) (r6 + KERNELBASE));
          }

+#ifdef CONFIG_BOOKE_WDT
+     {
+       extern void booke_wdt_setup_options(char *cmd_line);
+
+       booke_wdt_setup_options(cmd_line);
+     }
+#endif  /*  CONFIG_BOOKE_WDT  */
+
  	identify_ppc_sys_by_id(mfspr(SVR));

          /* setup the PowerPC module struct */
--- linux-2.6.11/arch/ppc/platforms/85xx/sbc8560.c	2005-03-04 17:17:22.985877656 +0900
+++ linux-2.6.11-booke-wdt/arch/ppc/platforms/85xx/sbc8560.c	2005-03-04 13:21:31.000000000 +0900
@@ -198,6 +198,14 @@ platform_init(unsigned long r3, unsigned
  		strcpy(cmd_line, (char *) (r6 + KERNELBASE));
  	}

+#ifdef CONFIG_BOOKE_WDT
+     {
+       extern void booke_wdt_setup_options(char *cmd_line);
+
+       booke_wdt_setup_options(cmd_line);
+     }
+#endif  /*  CONFIG_BOOKE_WDT  */
+
  	identify_ppc_sys_by_id(mfspr(SVR));

  	/* setup the PowerPC module struct */
--- linux-2.6.11/arch/ppc/platforms/85xx/stx_gp3.c	2005-03-04 17:14:12.883777568 +0900
+++ linux-2.6.11-booke-wdt/arch/ppc/platforms/85xx/stx_gp3.c	2005-03-04 13:21:31.000000000 +0900
@@ -68,6 +68,7 @@ unsigned long isa_mem_base = 0;
  unsigned long pci_dram_offset = 0;
  #endif

+
  /* Internal interrupts are all Level Sensitive, and Positive Polarity */
  static u8 gp3_openpic_initsenses[] __initdata = {
  	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  0: L2 Cache */
@@ -357,6 +358,14 @@ platform_init(unsigned long r3, unsigned
  		strcpy(cmd_line, (char *) (r6 + KERNELBASE));
  	}

+#ifdef CONFIG_BOOKE_WDT
+     {
+       extern void booke_wdt_setup_options(char *cmd_line);
+
+       booke_wdt_setup_options(cmd_line);
+     }
+#endif  /*  CONFIG_BOOKE_WDT  */
+
  	identify_ppc_sys_by_id(mfspr(SVR));

  	/* setup the PowerPC module struct */
--- linux-2.6.11/arch/ppc/syslib/ppc4xx_setup.c	2005-03-04 17:10:56.867576560 +0900
+++ linux-2.6.11-booke-wdt/arch/ppc/syslib/ppc4xx_setup.c	2005-03-04 13:21:31.000000000 +0900
@@ -48,10 +48,6 @@
  extern void abort(void);
  extern void ppc4xx_find_bridges(void);

-extern void ppc4xx_wdt_heartbeat(void);
-extern int wdt_enable;
-extern unsigned long wdt_period;
-
  /* Global Variables */
  bd_t __res;

@@ -257,22 +253,14 @@ ppc4xx_init(unsigned long r3, unsigned l
  		*(char *) (r7 + KERNELBASE) = 0;
  		strcpy(cmd_line, (char *) (r6 + KERNELBASE));
  	}
-#if defined(CONFIG_PPC405_WDT)
-/* 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;
-	}
-#endif
+
+#ifdef CONFIG_BOOKE_WDT
+     {
+       extern void booke_wdt_setup_options(char *cmd_line);
+
+       booke_wdt_setup_options(cmd_line);
+     }
+#endif  /*  CONFIG_BOOKE_WDT  */

  	/* Initialize machine-dependent vectors */

@@ -319,3 +307,5 @@ void platform_machine_check(struct pt_re
  #endif

  }
+
+

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH] WDT Driver for Book-E [2/2] Device driver part.
  2005-03-03 17:11                       ` Matt Porter
  2005-03-04  9:38                         ` [PATCH] WDT Driver for Book-E [1/2] Architecture specific part Takeharu KATO
@ 2005-03-04  9:38                         ` Takeharu KATO
  2005-03-04 16:02                           ` Kumar Gala
  2005-03-05  0:34                           ` Josh Boyer
  1 sibling, 2 replies; 33+ messages in thread
From: Takeharu KATO @ 2005-03-04  9:38 UTC (permalink / raw)
  To: Matt Porter; +Cc: ppcembed

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@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@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@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  */

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH] WDT Driver for Book-E [1/2] Architecture specific part.
  2005-03-04  9:38                         ` [PATCH] WDT Driver for Book-E [1/2] Architecture specific part Takeharu KATO
@ 2005-03-04 15:54                           ` Kumar Gala
  2005-03-08 17:08                             ` Takeharu KATO
  0 siblings, 1 reply; 33+ messages in thread
From: Kumar Gala @ 2005-03-04 15:54 UTC (permalink / raw)
  To: Takeharu KATO; +Cc: ppcembed

Out of interest how did you test this?  If I find some time I will test =20=

it on an e500 system, just havent given much thought on how to test the =20=

watchdog though.

- kumar

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

> Matt and Kurmar:
>
> I performed name-cleanup in the driver.
>
> Moreover, I tested this driver with PowerPC405GPr(Sycamore)
> in addition to PowerPC440GP(ebony)/MPC8555(MPC8555-CDS).
>
> This driver consist of two patches as follows:
>
> 1) Architecture specific part(booke_wdt-arch.patch)
>  This is the architecture specific part of the driver.
>  It contains WDT exception handlers
>  and kernel command line processing
>  routines.
>
> 2) Device driver part(booke_wdt-drv.patch)
>  This is the core of this WDT
>  driver.
>
> At first, I post the architecture specific part with this mail.
>
> Please apply.
>
> Regards,
>
> Signed-off-by: Takeharu KATO <kato.takeharu@jp.fujitsu.com>
>
> --- linux-2.6.11/arch/ppc/kernel/head_44x.S=A0=A0=A0=A0 2005-03-04 =20
> 17:12:42.944450424 +0900
>  +++ linux-2.6.11-booke-wdt/arch/ppc/kernel/head_44x.S=A0=A0 =
2005-03-04 =20
> 13:21:31.000000000 +0900
>  @@ -444,8 +444,12 @@ interrupt_base:
> =A0 =A0=A0=A0=A0=A0 EXCEPTION(0x1010, FixedIntervalTimer, =
UnknownException, =20
> EXC_XFER_EE)
>
> =A0 =A0=A0=A0=A0=A0 /* Watchdog Timer Interrupt */
>  -=A0=A0=A0=A0=A0=A0 /* TODO: Add watchdog support */
>  +#if defined(CONFIG_BOOKE_WDT)
> +=A0=A0=A0=A0=A0=A0 CRITICAL_EXCEPTION(0x1020, WatchdogTimer, =
booke_wdt_exception)
> +#else
>  =A0 =A0=A0=A0=A0=A0 CRITICAL_EXCEPTION(0x1020, WatchdogTimer, =
UnknownException)
> +#endif=A0 /*=A0 CONFIG_BOOKE_WDT=A0 */
>  +=A0=A0=A0=A0=A0=A0
>
>  =A0 =A0=A0=A0=A0=A0 /* Data TLB Error Interrupt */
>  =A0 =A0=A0=A0=A0=A0 START_EXCEPTION(DataTLBError)
> --- linux-2.6.11/arch/ppc/kernel/head_4xx.S=A0=A0=A0=A0 2005-03-04 =20
> 17:16:48.089182760 +0900
>  +++ linux-2.6.11-booke-wdt/arch/ppc/kernel/head_4xx.S=A0=A0 =
2005-03-04 =20
> 13:21:31.000000000 +0900
>  @@ -469,27 +469,23 @@ label:
>
> =A0 /* 0x1000 - Programmable Interval Timer (PIT) Exception */
>  =A0 =A0=A0=A0=A0=A0 START_EXCEPTION(0x1000, Decrementer)
>  -=A0=A0=A0=A0=A0=A0 NORMAL_EXCEPTION_PROLOG
> -=A0=A0=A0=A0=A0=A0 lis=A0=A0=A0=A0 r0,TSR_PIS@h
> -=A0=A0=A0=A0=A0=A0 mtspr=A0=A0 SPRN_TSR,r0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=
=A0 /* Clear the PIT exception */
>  -=A0=A0=A0=A0=A0=A0 addi=A0=A0=A0 r3,r1,STACK_FRAME_OVERHEAD
> -=A0=A0=A0=A0=A0=A0 EXC_XFER_LITE(0x1000, timer_interrupt)
> -
>  +=A0=A0=A0=A0=A0=A0 b=A0=A0=A0=A0=A0=A0 DecrementerHandler
> =A0 #if 0
>  =A0 /* NOTE:
>  - * FIT and WDT handlers are not implemented yet.
>  + * FIT handler are not implemented yet.
>  =A0=A0 */
>
> =A0 /* 0x1010 - Fixed Interval Timer (FIT) Exception
>  =A0 */
>  =A0 =A0=A0=A0=A0=A0 STND_EXCEPTION(0x1010,=A0 FITException,=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 =20
> UnknownException)
>
> -/* 0x1020 - Watchdog Timer (WDT) Exception
>  -*/
>  -
>  -=A0=A0=A0=A0=A0=A0 CRITICAL_EXCEPTION(0x1020, WDTException, =
UnknownException)
> =A0 #endif
>
> +=A0 /* 0x1020 - Watchdog Timer (WDT) Exception
>  +=A0 */
>  +=A0=A0=A0=A0=A0=A0 START_EXCEPTION(0x1020, WDTException)
> +=A0=A0=A0=A0=A0=A0 b=A0=A0=A0=A0=A0=A0 WatchDogHandler
> +
>  =A0 /* 0x1100 - Data TLB Miss Exception
>  =A0=A0 * As the name implies, translation is not in the MMU, so =
search the
>  =A0=A0 * page tables and fix it.=A0 The only purpose of this function =
is to
>  @@ -771,6 +767,14 @@ label:
>  =A0 =A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 (MSR_KERNEL & =
~(MSR_ME|MSR_DE|MSR_CE)), \
>  =A0 =A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 NOCOPY, =
crit_transfer_to_handler, ret_from_crit_exc)
>
> +
>  +DecrementerHandler:
> +=A0=A0=A0=A0=A0=A0 NORMAL_EXCEPTION_PROLOG
> +=A0=A0=A0=A0=A0=A0 lis=A0=A0=A0=A0 r0,TSR_PIS@h
> +=A0=A0=A0=A0=A0=A0 mtspr=A0=A0 SPRN_TSR,r0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=
=A0 /* Clear the PIT exception */
>  +=A0=A0=A0=A0=A0=A0 addi=A0=A0=A0 r3,r1,STACK_FRAME_OVERHEAD
> +=A0=A0=A0=A0=A0=A0 EXC_XFER_LITE(0x1000, timer_interrupt)
> +
>  =A0 /*
>  =A0=A0 * The other Data TLB exceptions bail out to this point
>  =A0=A0 * if they can't resolve the lightweight TLB fault.
>  @@ -844,6 +848,19 @@ finish_tlb_load:
> =A0 =A0=A0=A0=A0=A0 rfi=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=
=A0=A0 /* Should sync shadow TLBs */
>  =A0 =A0=A0=A0=A0=A0 b=A0=A0=A0=A0=A0=A0 .=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=
=A0=A0=A0 /* prevent prefetch past rfi */
>
> +/*
>  + * WatchDog Exception
>  + */
>  +WatchDogHandler:
> +=A0=A0=A0=A0=A0=A0 CRITICAL_EXCEPTION_PROLOG;
> +=A0=A0=A0=A0=A0=A0 addi=A0=A0=A0 r3,r1,STACK_FRAME_OVERHEAD;
> +#if defined(CONFIG_BOOKE_WDT)
> +=A0=A0=A0=A0=A0=A0 EXC_XFER_TEMPLATE(booke_wdt_exception, 0x1022, =
(MSR_KERNEL & =20
> ~(MSR_ME|MSR_DE|MSR_CE)),NOCOPY,
>  crit_transfer_to_handler, ret_from_crit_exc)
> +
>  +#else
>  +=A0=A0=A0=A0=A0=A0 EXC_XFER_TEMPLATE(UnknownException, 0x1022, =
(MSR_KERNEL & =20
> ~(MSR_ME|MSR_DE|MSR_CE)),NOCOPY,
>  crit_transfer_to_handler, ret_from_crit_exc)
> +#endif=A0 /*=A0 CONFIG_BOOKE_WDT=A0 */
>  +
>  =A0 /* extern void giveup_fpu(struct task_struct *prev)
>  =A0=A0 *
>  =A0=A0 * The PowerPC 4xx family of processors do not have an FPU, so =
this =20
> just
>  --- linux-2.6.11/arch/ppc/kernel/head_e500.S=A0=A0=A0 2005-03-04 =20
> 17:15:36.641044528 +0900
>  +++ linux-2.6.11-booke-wdt/arch/ppc/kernel/head_e500.S=A0 2005-03-04 =20=

> 13:21:31.000000000 +0900
>  @@ -494,8 +494,11 @@ interrupt_base:
> =A0 =A0=A0=A0=A0=A0 EXCEPTION(0x3100, FixedIntervalTimer, =
UnknownException, =20
> EXC_XFER_EE)
>
> =A0 =A0=A0=A0=A0=A0 /* Watchdog Timer Interrupt */
>  -=A0=A0=A0=A0=A0=A0 /* TODO: Add watchdog support */
>  +#if defined(CONFIG_BOOKE_WDT)
> +=A0=A0=A0=A0=A0=A0 CRITICAL_EXCEPTION(0x3200, WatchdogTimer, =
booke_wdt_exception)
> +#else
>  =A0 =A0=A0=A0=A0=A0 CRITICAL_EXCEPTION(0x3200, WatchdogTimer, =
UnknownException)
> +#endif=A0 /*=A0 CONFIG_BOOKE_WDT=A0 */
>
> =A0 =A0=A0=A0=A0=A0 /* Data TLB Error Interrupt */
>  =A0 =A0=A0=A0=A0=A0 START_EXCEPTION(DataTLBError)
> --- linux-2.6.11/arch/ppc/platforms/85xx/mpc8540_ads.c=A0 2005-03-04 =20=

> 17:13:11.927044400 +0900
>  +++ =20
> linux-2.6.11-booke-wdt/arch/ppc/platforms/85xx/mpc8540_ads.c=A0=A0=A0=A0=
=A0=A0=A0 =20
> 2005-03-04 13:21:31.000000000 +0900
>  @@ -54,6 +54,7 @@
>
> =A0 #include <syslib/ppc85xx_setup.h>
>
> +
>  =A0 /* =20
> =
***********************************************************************=20=

> *
> =A0=A0 *
>  =A0=A0 * Setup the architecture
>  @@ -187,6 +188,14 @@ platform_init(unsigned long r3, unsigned
>  =A0 =A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 strcpy(cmd_line, (char *) =
(r6 + KERNELBASE));
> =A0 =A0=A0=A0=A0=A0 }
>
> +#ifdef CONFIG_BOOKE_WDT
> +=A0=A0=A0=A0 {
>  +=A0=A0=A0=A0=A0=A0 extern void booke_wdt_setup_options(char =
*cmd_line);
>  +
>  +=A0=A0=A0=A0=A0=A0 booke_wdt_setup_options(cmd_line);
> +=A0=A0=A0=A0 }
>  +#endif=A0 /*=A0 CONFIG_BOOKE_WDT=A0 */
>  +
>  =A0 =A0=A0=A0=A0=A0 identify_ppc_sys_by_id(mfspr(SVR));
>
> =A0 =A0=A0=A0=A0=A0 /* setup the PowerPC module struct */
>  --- linux-2.6.11/arch/ppc/platforms/85xx/mpc8560_ads.c=A0 2005-03-04 =20=

> 17:17:54.566076736 +0900
>  +++ =20
> linux-2.6.11-booke-wdt/arch/ppc/platforms/85xx/mpc8560_ads.c=A0=A0=A0=A0=
=A0=A0=A0 =20
> 2005-03-04 13:21:31.000000000 +0900
>  @@ -197,6 +197,14 @@ platform_init(unsigned long r3, unsigned
>  =A0 =A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 strcpy(cmd_line, (char *) =
(r6 + KERNELBASE));
> =A0 =A0=A0=A0=A0=A0 }
>
> +#ifdef CONFIG_BOOKE_WDT
> +=A0=A0=A0=A0 {
>  +=A0=A0=A0=A0=A0=A0 extern void booke_wdt_setup_options(char =
*cmd_line);
>  +
>  +=A0=A0=A0=A0=A0=A0 booke_wdt_setup_options(cmd_line);
> +=A0=A0=A0=A0 }
>  +#endif=A0 /*=A0 CONFIG_BOOKE_WDT=A0 */
>  +
>  =A0 =A0=A0=A0=A0=A0 identify_ppc_sys_by_id(mfspr(SVR));
>
> =A0 =A0=A0=A0=A0=A0 /* setup the PowerPC module struct */
>  --- linux-2.6.11/arch/ppc/platforms/85xx/mpc85xx_cds_common.c=A0=A0 =20=

> 2005-03-04 17:16:27.056380232 +0900
>  +++ =20
> linux-2.6.11-booke-wdt/arch/ppc/platforms/85xx/mpc85xx_cds_common.c =20=

> 2005-03-04
> 13:21:31.000000000 +0900
>  @@ -437,6 +437,14 @@ platform_init(unsigned long r3, unsigned
>  =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 strcpy(cmd_line, =
(char *) (r6 + KERNELBASE));
> =A0=A0=A0=A0=A0=A0=A0=A0=A0 }
>
> +#ifdef CONFIG_BOOKE_WDT
> +=A0=A0=A0=A0 {
>  +=A0=A0=A0=A0=A0=A0 extern void booke_wdt_setup_options(char =
*cmd_line);
>  +
>  +=A0=A0=A0=A0=A0=A0 booke_wdt_setup_options(cmd_line);
> +=A0=A0=A0=A0 }
>  +#endif=A0 /*=A0 CONFIG_BOOKE_WDT=A0 */
>  +
>  =A0 =A0=A0=A0=A0=A0 identify_ppc_sys_by_id(mfspr(SVR));
>
> =A0=A0=A0=A0=A0=A0=A0=A0=A0 /* setup the PowerPC module struct */
>  --- linux-2.6.11/arch/ppc/platforms/85xx/sbc8560.c=A0=A0=A0=A0=A0 =
2005-03-04 =20
> 17:17:22.985877656 +0900
>  +++ linux-2.6.11-booke-wdt/arch/ppc/platforms/85xx/sbc8560.c=A0=A0=A0 =
=20
> 2005-03-04 13:21:31.000000000 +0900
>  @@ -198,6 +198,14 @@ platform_init(unsigned long r3, unsigned
>  =A0 =A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 strcpy(cmd_line, (char *) =
(r6 + KERNELBASE));
> =A0 =A0=A0=A0=A0=A0 }
>
> +#ifdef CONFIG_BOOKE_WDT
> +=A0=A0=A0=A0 {
>  +=A0=A0=A0=A0=A0=A0 extern void booke_wdt_setup_options(char =
*cmd_line);
>  +
>  +=A0=A0=A0=A0=A0=A0 booke_wdt_setup_options(cmd_line);
> +=A0=A0=A0=A0 }
>  +#endif=A0 /*=A0 CONFIG_BOOKE_WDT=A0 */
>  +
>  =A0 =A0=A0=A0=A0=A0 identify_ppc_sys_by_id(mfspr(SVR));
>
> =A0 =A0=A0=A0=A0=A0 /* setup the PowerPC module struct */
>  --- linux-2.6.11/arch/ppc/platforms/85xx/stx_gp3.c=A0=A0=A0=A0=A0 =
2005-03-04 =20
> 17:14:12.883777568 +0900
>  +++ linux-2.6.11-booke-wdt/arch/ppc/platforms/85xx/stx_gp3.c=A0=A0=A0 =
=20
> 2005-03-04 13:21:31.000000000 +0900
>  @@ -68,6 +68,7 @@ unsigned long isa_mem_base =3D 0;
>  =A0 unsigned long pci_dram_offset =3D 0;
>  =A0 #endif
>
> +
>  =A0 /* Internal interrupts are all Level Sensitive, and Positive =20
> Polarity */
>  =A0 static u8 gp3_openpic_initsenses[] __initdata =3D {
>  =A0 =A0=A0=A0=A0=A0 (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),=A0=A0=A0=
=A0=A0 /* Internal=A0 =20
> 0: L2 Cache */
>  @@ -357,6 +358,14 @@ platform_init(unsigned long r3, unsigned
>  =A0 =A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 strcpy(cmd_line, (char *) =
(r6 + KERNELBASE));
> =A0 =A0=A0=A0=A0=A0 }
>
> +#ifdef CONFIG_BOOKE_WDT
> +=A0=A0=A0=A0 {
>  +=A0=A0=A0=A0=A0=A0 extern void booke_wdt_setup_options(char =
*cmd_line);
>  +
>  +=A0=A0=A0=A0=A0=A0 booke_wdt_setup_options(cmd_line);
> +=A0=A0=A0=A0 }
>  +#endif=A0 /*=A0 CONFIG_BOOKE_WDT=A0 */
>  +
>  =A0 =A0=A0=A0=A0=A0 identify_ppc_sys_by_id(mfspr(SVR));
>
> =A0 =A0=A0=A0=A0=A0 /* setup the PowerPC module struct */
>  --- linux-2.6.11/arch/ppc/syslib/ppc4xx_setup.c 2005-03-04 =20
> 17:10:56.867576560 +0900
>  +++ linux-2.6.11-booke-wdt/arch/ppc/syslib/ppc4xx_setup.c=A0=A0=A0=A0=A0=
=A0 =20
> 2005-03-04 13:21:31.000000000 +0900
>  @@ -48,10 +48,6 @@
>  =A0 extern void abort(void);
>  =A0 extern void ppc4xx_find_bridges(void);
>
> -extern void ppc4xx_wdt_heartbeat(void);
> -extern int wdt_enable;
>  -extern unsigned long wdt_period;
>  -
>  =A0 /* Global Variables */
>  =A0 bd_t __res;
>
> @@ -257,22 +253,14 @@ ppc4xx_init(unsigned long r3, unsigned l
>  =A0 =A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 *(char *) (r7 + KERNELBASE) =
=3D 0;
>  =A0 =A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 strcpy(cmd_line, (char *) =
(r6 + KERNELBASE));
> =A0 =A0=A0=A0=A0=A0 }
>  -#if defined(CONFIG_PPC405_WDT)
> -/* Look for wdt=3D option on command line */
>  -=A0=A0=A0=A0=A0=A0 if (strstr(cmd_line, "wdt=3D")) {
>  -=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 int valid_wdt =3D 0;
>  -=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 char *p, *q;
>  -=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 for (q =3D cmd_line; (p =3D =
strstr(q, "wdt=3D")) !=3D 0;) {
> -=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 q =3D =
p + 4;
>  -=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 if (p =
> cmd_line && p[-1] !=3D ' ')
>  -=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
=A0=A0=A0=A0=A0=A0=A0 continue;
> -=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
wdt_period =3D simple_strtoul(q, &q, 0);
>  -=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =
valid_wdt =3D 1;
>  -=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 ++q;
>  -=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 }
>  -=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 wdt_enable =3D valid_wdt;
>  -=A0=A0=A0=A0=A0=A0 }
>  -#endif
>  +
>  +#ifdef CONFIG_BOOKE_WDT
> +=A0=A0=A0=A0 {
>  +=A0=A0=A0=A0=A0=A0 extern void booke_wdt_setup_options(char =
*cmd_line);
>  +
>  +=A0=A0=A0=A0=A0=A0 booke_wdt_setup_options(cmd_line);
> +=A0=A0=A0=A0 }
>  +#endif=A0 /*=A0 CONFIG_BOOKE_WDT=A0 */
>
> =A0 =A0=A0=A0=A0=A0 /* Initialize machine-dependent vectors */
>
> @@ -319,3 +307,5 @@ void platform_machine_check(struct pt_re
>  =A0 #endif
>
> =A0 }
>  +
>  +
>
>
> =20=

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH] WDT Driver for Book-E [2/2] Device driver part.
  2005-03-04  9:38                         ` [PATCH] WDT Driver for Book-E [2/2] Device driver part Takeharu KATO
@ 2005-03-04 16:02                           ` Kumar Gala
  2005-03-04 16:35                             ` Matt Porter
  2005-03-05  0:34                           ` Josh Boyer
  1 sibling, 1 reply; 33+ messages in thread
From: Kumar Gala @ 2005-03-04 16:02 UTC (permalink / raw)
  To: Takeharu KATO; +Cc: ppcembed

Matt,

Do you think this really needs a config option?  Should it not be =20
sufficient that if you enable watchdog you get this functionality on =20
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@jp.fujitsu.com>
>
> --- linux-2.6.11/drivers/char/watchdog/Kconfig=A0 2005-03-04 =20
> 17:14:57.687966296 +0900
>  +++ linux-2.6.11-booke-wdt/drivers/char/watchdog/Kconfig=A0=A0=A0=A0=A0=
=A0=A0 =20
> 2005-03-04 13:21:32.000000000 +0900
>  @@ -346,6 +346,13 @@ config 8xx_WDT
>  =A0 =A0=A0=A0=A0=A0 tristate "MPC8xx Watchdog Timer"
>  =A0 =A0=A0=A0=A0=A0 depends on WATCHDOG && 8xx
>
> +config BOOKE_WDT
>  +=A0=A0=A0 bool "Book E(PowerPC 4xx/e500) Watchdog Timer"
>  +=A0=A0=A0 depends on WATCHDOG && ( 4xx || E500 )
>  +=A0=A0=A0 ---help---
>  +=A0=A0=A0=A0=A0 This is the driver for the watchdog timers on
>  +=A0=A0=A0=A0=A0 PowerPC 4xx and PowerPC e500.
>  +
>  =A0 # MIPS Architecture
>
> =A0 config INDYDOG
>  --- linux-2.6.11/drivers/char/watchdog/Makefile 2005-03-04 =20
> 17:15:30.582965496 +0900
>  +++ linux-2.6.11-booke-wdt/drivers/char/watchdog/Makefile=A0=A0=A0=A0=A0=
=A0 =20
> 2005-03-04 13:21:32.000000000 +0900
>  @@ -39,3 +39,4 @@ obj-$(CONFIG_USBPCWATCHDOG) +=3D pcwd_usb.
>  =A0 obj-$(CONFIG_IXP4XX_WATCHDOG) +=3D ixp4xx_wdt.o
>  =A0 obj-$(CONFIG_IXP2000_WATCHDOG) +=3D ixp2000_wdt.o
> =A0 obj-$(CONFIG_8xx_WDT) +=3D mpc8xx_wdt.o
>  +obj-$(CONFIG_BOOKE_WDT) +=3D booke_wdt.o
>  --- linux-2.6.11/drivers/char/watchdog/booke_wdt.c=A0=A0=A0=A0=A0 =
1970-01-01 =20
> 09:00:00.000000000 +0900
>  +++ linux-2.6.11-booke-wdt/drivers/char/watchdog/booke_wdt.c=A0=A0=A0 =
=20
> 2005-03-04 16:38:58.000000000 +0900
>  @@ -0,0 +1,664 @@
>  +/*
>  + *=A0=A0=A0 Copyright (c) 2005 Fujitsu Limited
>  + *
>  + *=A0=A0=A0 Module name: booke_wdt.c
>  + *=A0=A0=A0 Author:=A0=A0=A0=A0=A0 Takeharu =
KATO<kato.takeharu@jp.fujitsu.com>
> + *
>  + *=A0=A0=A0 This program is free software; you can redistribute it =
and/or
>  + *=A0=A0=A0 modify it under the terms of the GNU General Public =
License
> + *=A0=A0=A0 as published by the Free Software Foundation; either =
version 2
>  + *=A0=A0=A0 of the License, or (at your option) any later version.
>  + *
>  + *=A0=A0=A0 Neither Takeharu KATO nor Fujitsu Ltd. admit liability =
nor =20
> provide
>  + *=A0=A0=A0 warranty for any of this software.
>  + *
>  + *=A0=A0=A0 Description:
>  + *=A0=A0=A0=A0 Watchdog driver for PowerPC Book E (PowerPC 4xx =
series =20
> processors and
>  + *=A0=A0=A0=A0 PowerPC e500 series processors).
>  + *=A0=A0=A0=A0 Derived from drivers/char/watchdog/wdt.c by Alan cox
>  + *=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 and=A0 =
drivers/char/watchdog/ppc405_wdt.c by Armin =20
> Kuster.
>  + *=A0=A0=A0=A0 PPC4xx WDT operation is driverd from Appendix of
>  + *=A0=A0=A0=A0 PowerPC Embedded Processors Application Note
>  + *=A0=A0=A0=A0=A0 ``PowerPC 40x Watch Dog Timer'' published from =
IBM.
>  + *=A0=A0=A0=A0 This driver is written according to ``PowerPC e500 =
Core =20
> Complex
>  + *=A0=A0=A0=A0 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
>  +/*=A0 Calculate watchdog count=A0=A0 */
>  +#define calculate_wdt_count(t) ((((unsigned long)(t))*HZ)/1000)
> +
>  +int wdt_enable=3D0;=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 /* WDT start =
on boot=A0 */
>  +int wdt_period=3DWDT_TIMO;=A0=A0=A0=A0=A0=A0 /* Time out in ms */
>  +
>  +#ifdef CONFIG_WATCHDOG_NOWAYOUT
> +static int nowayout =3D 1;
>  +#else
>  +static int nowayout =3D 0;
>  +#endif
>  +
>  +/*
>  + * Global variables
>  + */
>  +static int wdt_count =3D 0;=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 /* WDT =
intrrupt counter to be =20
> reloaded */
>  +static volatile int wdt_heartbeat_count =3D 0;=A0 /* WDT intrrupt =20=

> counter(compatible mode)*/
>  +static unsigned long driver_state; /* Driver status (see: =20
> booke_wdt.h) */
>  +/*
>  + *=A0 Identifier for this watchdog
>  + */
>  +static struct watchdog_info ident =3D {
>  +=A0 .options=3DWDIOF_SETTIMEOUT|WDIOF_KEEPALIVEPING|WDIOF_MAGICCLOSE,
> +=A0 .firmware_version =3D=A0=A0=A0 0, /*=A0 This is filled with PVR =
in =20
> initialization. */
>  +=A0 .identity =3D=A0=A0=A0=A0=A0=A0=A0 "Book E(PPC 4xx/e500) WDT",
>  +};
>  +
>  +/*
>  + *=A0 PowerPC Linux common exception handler
>  + */
>  +extern void _exception(int signr, struct pt_regs *regs, int code, =20=

> unsigned long addr);
>  +/*=A0 Panic notifier=A0 */
>  +extern struct notifier_block *panic_notifier_list;
> +/*
>  + *=A0 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=A0 __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=A0 booke_wdt_is_enabled(void);
> +static __inline__ int=A0 booke_wdt_start(void);
> +static __inline__ int=A0 booke_wdt_stop(void);
> +static __inline__ int=A0 booke_wdt_ping(void);
> +static __inline__ int=A0 booke_wdt_set_timeout(int t);
>  +static __inline__ int=A0 booke_wdt_get_status(int *status);
>  +static ssize_t booke_wdt_write(struct file *file, const char *buf, =20=

> size_t count, loff_t *ppos);
>  +static int booke_wdt_ioctl(struct inode *inode, struct file *file, =20=

> 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 =
=20
> long code,void *unused);
>  +static int __init booke_wdt_init(void);
> +static void __exit booke_wdt_exit(void);
> +
>  +/*
>  + *=A0=A0=A0 Watchdog operations on PPC4xx/e500 MPU
>  + */
>  +
>  +/**
>  + *=A0=A0=A0=A0=A0 __booke_wdt_setup_val
> + *=A0=A0=A0=A0=A0 Enable Watchdog, sets up passed in values for =
TCR[WP],
>  + *=A0=A0=A0=A0=A0 TCR[WRC]
>  + *
>  + *=A0=A0=A0 @period:=A0=A0=A0 Input Watchdog Period - TCR[WP]
>  + *=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 0 =
=3D 217 clocks
> + *=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 1 =3D=
 221 clocks
> + *=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 2 =3D=
 225 clocks
> + *=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 3 =3D=
 229 clocks
> + *=A0=A0=A0=A0=A0 @reset:=A0=A0=A0=A0=A0=A0=A0=A0 Watchdog reset =
control - TCR[WRC]
>  + *=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 0 =
=3D No reset
>  + *=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 1 =
=3D PPC Core reset only
>  + *=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 2 =
=3D PPC Chip reset
>  + *=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 3 =
=3D System reset
>  + *=A0=A0=A0=A0 Note: The meaning of period number is differ PPC440GP =
from =20
> PPC440GX.
>  + */
>  +#if defined(CONFIG_4xx)
> +static __inline__ void
> +__booke_wdt_setup_val(int period,int reset)
>  +{
>  +=A0 unsigned long val;
>  +
>  +=A0 /*=A0 Set up TCR=A0 */
>  +=A0 =20
> =
val=3D((period)<<WDT_TCR_WP_SHIFT|(reset)<<WDT_TCR_WRC_SHIFT)|mfspr(SPRN_=20=

> TCR);
> +=A0 /*=A0 Disable WDT=A0 */
>  +=A0 val &=3D ~(WDT_TCR_WDT_ENABLE);
> +
>  +=A0 mtspr(SPRN_TCR,val);
> +}
>  +#else
>  +/*=A0 e500=A0 */
>  +static __inline__ void
> +__booke_wdt_setup_val(int period,int reset)
>  +{
>  +=A0 unsigned long val;
>  +=A0 /*=A0 Set up TCR=A0 */
>  +
>  +=A0 val=3D(((period)&(WDT_TCR_WP_BITMSK)) << WDT_TCR_WP_SHIFT|
> +=A0=A0=A0=A0=A0=A0 ( ( (period) >> 2 )&(WDT_TCR_WPEXT_BITMSK)) << =20
> WDT_TCR_WPEXT_SHIFT|
> +=A0=A0=A0=A0=A0=A0 (reset)<<WDT_TCR_WRC_SHIFT)|mfspr(SPRN_TCR);
> +=A0 /*=A0 Disable WDT=A0 */
>  +=A0 val &=3D ~(WDT_TCR_WDT_ENABLE);
> +
>  +=A0 mtspr(SPRN_TCR,val);
> +}
>  +#endif=A0 /*=A0 CONFIG_E500 */
>  +/**
>  + *=A0=A0=A0=A0=A0 __booke_wdt_enable
> + *=A0=A0=A0=A0=A0 Enable Watchdog
>  + */
>  +static __inline__ void
> +__booke_wdt_enable(void)
> +{
>  +=A0 mtspr(SPRN_TCR,(mfspr(SPRN_TCR)|WDT_TCR_WDT_ENABLE));
> +}
>  +/**
>  + *=A0=A0=A0=A0=A0 __booke_wdt_disable
> + *=A0=A0=A0=A0=A0 Disable Watchdog
>  + */
>  +static __inline__ void
> +__booke_wdt_disable(void)
> +{
>  +=A0 mtspr(SPRN_TCR,(mfspr(SPRN_TCR)&(~(WDT_TCR_WDT_ENABLE))));
> +}
>  +/**
>  + *=A0=A0=A0=A0=A0 __booke_wdt_is_enabled
> + *=A0=A0=A0=A0=A0 Check whether Watchdog is enabled.
>  + */
>  +static __inline__ int
>  +__booke_wdt_is_enabled(void)
> +{
>  +=A0 return (mfspr(SPRN_TCR) & WDT_TCR_WDT_ENABLE);
> +}
>  +/**
>  + *=A0=A0=A0=A0=A0 __booke_wdt_clear_init_stat
> + *=A0=A0=A0=A0=A0 Clear interrupt status of watchdog to ping it.
>  + */
>  +static __inline__ void
> +__booke_wdt_clear_int_stat(void)
> +{
>  +=A0 mtspr(SPRN_TSR, (TSR_ENW|TSR_WIS));
> +}
>  +/**
>  + *=A0=A0=A0 __booke_wdt_set_timeout:
> + *=A0=A0=A0 @t:=A0=A0=A0 the new time out value that needs to be set.
>  + *
>  + *=A0=A0=A0 Set a new time out value for the watchdog device.
>  + *
>  + */
>  +static __inline__ void
> +__booke_wdt_set_timeout(int t)
>  +{
>  +=A0 wdt_count=3Dcalculate_wdt_count(t);
> +=A0 return;
>  +}
>  +
>  +/*
>  + * Driver specific functions
>  + */
>  +
>  +/**
>  + *=A0=A0 booke_wdt_setup_options
> + *=A0=A0 @cmd_line : a pointer to kernel command line.
> + *
>  + */
>  +void
>  +booke_wdt_setup_options(char *cmd_line)
>  +{
>  +/*
>  + * Look for wdt=3D option on command line
>  + */
>  +=A0 if (strstr(cmd_line, "wdt=3D")) {
>  +=A0=A0=A0 int valid_wdt =3D 0;
>  +=A0=A0=A0 char *p, *q;
> +
>  +=A0=A0=A0 for (q =3D cmd_line; (p =3D strstr(q, "wdt=3D")) !=3D 0;) =
{
> +=A0=A0=A0=A0=A0 q =3D p + 4;
> +=A0=A0=A0=A0=A0 if (p > cmd_line && p[-1] !=3D ' ')
>  +=A0=A0=A0 continue;
>  +=A0=A0=A0=A0=A0 wdt_period =3D simple_strtoul(q, &q, 0);
>  +=A0=A0=A0=A0=A0 valid_wdt =3D 1;
>  +=A0=A0=A0=A0=A0 ++q;
>  +=A0=A0=A0 }
>  +=A0=A0=A0 wdt_enable =3D valid_wdt;
>  +=A0 }
>  +=A0 return;
>  +}
>  +/**
>  + *=A0=A0=A0 booke_wdt_heartbeat:
> + *=A0=A0=A0=A0=A0 Ping routine called from kernel.
>  + */
>  +void
>  +booke_wdt_heartbeat(void)
> +{
>  +=A0 /* Disable watchdog */
>  +=A0 __booke_wdt_disable();
> +
>  +=A0 /* Write a watchdog value */
>  +=A0 __booke_wdt_clear_int_stat();
> +
>  +=A0 if (!wdt_enable)
>  +=A0=A0=A0 goto out;
>  +
>  +=A0 if=A0 (wdt_heartbeat_count > 0)
>  +=A0=A0=A0 wdt_heartbeat_count--;
>  +=A0 else
>  +=A0=A0=A0 panic(booke_mkmsg("Initiating system reboot.\n"));
>  +
>  +=A0 /* Enable watchdog */
>  +=A0 __booke_wdt_enable();
> + out:
>  +=A0 /*=A0 Reset count=A0 */
>  +=A0 ppc_md.heartbeat_count =3D 0;
>  +}
>  +/**
>  + *=A0=A0=A0 booke_wdt_exception:
> + *=A0=A0=A0=A0=A0 WatchDog Exception handler for PPC4xx/e500.
> + *=A0=A0=A0=A0=A0 @regs : A registers information.
>  + */
>  +void
>  +booke_wdt_exception(struct pt_regs *regs)
>  +{
>  +=A0 wdt_enable=3D0;
> +=A0 __booke_wdt_disable();
> +=A0 printk("WDT Exception at PC: %lx, MSR: %lx, vector=3D%lx=A0=A0=A0 =
%s\n",
>  +=A0=A0=A0=A0=A0=A0=A0 regs->nip, regs->msr, regs->trap, =
print_tainted());
> +=A0 panic(booke_mkmsg("Initiating system reboot.\n"));
>  +}
>  +/*
>  + *=A0=A0=A0 Driver Logic functions
> + */
>  +static __inline__ int
>  +booke_wdt_is_enabled(void)
> +{
>  +=A0 return=A0 __booke_wdt_is_enabled();
> +}
>  +/**
>  + *=A0=A0=A0 booke_wdt_start:
> + *
>  + *=A0=A0=A0 Start the watchdog driver.
>  + */
>  +static __inline__ int
>  +booke_wdt_start(void)
> +{
>  +=A0 __booke_wdt_enable();
> +=A0 return 0;
>  +}
>  +
>  +/**
>  + *=A0=A0=A0 booke_wdt_stop:
> + *
>  + *=A0=A0=A0 Stop the watchdog driver.
>  + */
>  +static __inline__ int
>  +booke_wdt_stop (void)
>  +{
>  +=A0 __booke_wdt_disable();
> +=A0 return 0;
>  +}
>  +/**
>  + *=A0=A0=A0 booke_wdt_ping:
> + *
>  + *=A0=A0=A0 Reload counter one with the watchdog heartbeat. We don't =
=20
> bother reloading
>  + *=A0=A0=A0 the cascade counter.
>  + */
>  +static __inline__ int
>  +booke_wdt_ping(void)
> +{
>  +=A0 /* Disable watchdog */
>  +=A0 __booke_wdt_disable();
> +=A0 /* Write a watchdog value */
>  +=A0 __booke_wdt_clear_int_stat();
> +=A0 /*=A0 Reset count=A0 */
>  +=A0 wdt_heartbeat_count=3Dwdt_count;
> +=A0 /* Enable watchdog */
>  +=A0 __booke_wdt_enable();
> +
>  +=A0 return 0;
>  +}
>  +/**
>  + *=A0=A0=A0 booke_wdt_set_timeout:
> + *=A0=A0=A0 @t:=A0=A0=A0=A0=A0=A0=A0 the new timeout value that needs =
to be set.
>  + *
>  + *=A0=A0=A0 Set a new time out value for the watchdog device.
>  + *=A0=A0=A0=A0=A0 If the heartbeat value is incorrect we keep the =
old value
>  + *=A0=A0=A0=A0=A0 and return -EINVAL. If successfull we return 0.
>  + */
>  +static __inline__ int
>  +booke_wdt_set_timeout(int t)
>  +{
>  +=A0 if ((t < WDT_HEARTBEAT_MIN) || (t > WDT_HEARTBEAT_MAX))
> +=A0=A0=A0 return -EINVAL;
>  +
>  +=A0 wdt_period =3D t;
>  +=A0 __booke_wdt_set_timeout(t);
> +=A0 wdt_heartbeat_count=3Dwdt_count;
> +=A0 booke_wdt_dbg("The WDT counter set %d.\n",wdt_count);
> +
>  +=A0 return 0;
>  +}
>  +
>  +/**
>  + *=A0=A0=A0 booke_wdt_get_status:
> + *=A0=A0=A0 @status: the new status.
>  + *
>  + *=A0=A0=A0 Return the enable/disable card status.
>  + */
>  +static __inline__ int
>  +booke_wdt_get_status(int *status)
>  +{
>  +=A0 if (wdt_enable)
>  +=A0=A0=A0=A0=A0 *status =3D WDIOS_ENABLECARD;
> +=A0 else
>  +=A0=A0=A0=A0=A0 *status =3D WDIOS_DISABLECARD;
> +
>  +=A0 return 0;
>  +}
>  +/*
>  + *=A0=A0=A0 Kernel Interfaces
>  + */
>  +/**
>  + *=A0=A0=A0 booke_wdt_init_device:
> + *
>  + *=A0=A0=A0=A0=A0 Initilize PowerPC 4xx/e500 family Watch Dog =
facility.
>  + */
>  +static void
>  +booke_wdt_init_device(void)
> +{
>  +=A0=A0=A0=A0=A0=A0=A0 /* Hardware WDT provided by the processor.
>  +=A0=A0=A0=A0 * So, we set firmware version as processor version =
number.
>  +=A0=A0=A0=A0 */
>  +=A0=A0=A0 ident.firmware_version=3Dmfspr(PVR);
> +=A0=A0=A0 __booke_wdt_setup_val(WDT_WP,WDT_RESET_NONE);
> +}
>  +/**
>  + *=A0=A0=A0 booke_wdt_write:
> + *=A0=A0=A0 @file: file handle to the watchdog
>  + *=A0=A0=A0 @buf: buffer to write (unused as data does not matter =
here
>  + *=A0=A0=A0 @count: count of bytes
>  + *=A0=A0=A0 @ppos: pointer to the position to write. No seeks =
allowed
>  + *
>  + *=A0=A0=A0 A write to a watchdog device is defined as a keepalive =
signal. =20
> Any
>  + *=A0=A0=A0 write of data will do, as we we don't define content =
meaning =20
> expept
>  + *=A0=A0=A0=A0=A0 'V' character. It is performed as a sign to set =20=

> stop-on-close mode.
>  + */
>  +
>  +static ssize_t
>  +booke_wdt_write(struct file *file, const char *buf, size_t count, =20=

> loff_t *ppos)
>  +{
>  +=A0 size_t i;
>  +
>  +=A0=A0=A0 if (!nowayout) {
>  +=A0=A0=A0=A0=A0 /* In case it was set long ago */
>  +=A0=A0=A0=A0=A0 clear_bit(WDT_STATE_STOP_ON_CLOSE, &driver_state);
> +
>  +=A0=A0=A0=A0=A0 for (i =3D 0; i < count; i++) {
> +=A0=A0=A0 char c;
>  +
>  +=A0=A0=A0 if (get_user(c, buf + i))
>  +=A0=A0=A0=A0=A0 return -EFAULT;
>  +
>  +=A0=A0=A0 if (c =3D=3D 'V') {
>  +=A0=A0=A0=A0=A0 set_bit(WDT_STATE_STOP_ON_CLOSE, &driver_state);
> +=A0=A0=A0 }
>  +=A0=A0=A0=A0=A0 }
>  +=A0=A0=A0 }
>  +=A0=A0=A0 booke_wdt_ping();
> +
>  +=A0 return count;
>  +}
>  +
>  +/**
>  + *=A0=A0=A0 booke_wdt_ioctl:
> + *=A0=A0=A0 @inode: inode of the device
>  + *=A0=A0=A0 @file: file handle to the device
>  + *=A0=A0=A0 @cmd: watchdog command
>  + *=A0=A0=A0 @arg: argument pointer
>  + *
>  + */
>  +static int
>  +booke_wdt_ioctl(struct inode *inode, struct file *file, unsigned int =
=20
> cmd,
>  +=A0=A0=A0 unsigned long arg)
>  +{
>  +=A0=A0=A0 int new_timeout;
>  +=A0=A0=A0 int status;
>  +
>  +=A0=A0=A0 if (!capable(CAP_SYS_ADMIN))
> +=A0=A0=A0=A0=A0=A0=A0 return -EPERM;=A0 /*=A0 It may be too strict =
manner.=A0 */
>  +=A0=A0=A0 switch(cmd)
>  +=A0=A0=A0 {
>  +=A0=A0=A0 default:
>  +=A0=A0=A0=A0=A0=A0=A0 return -ENOIOCTLCMD;
> +=A0=A0=A0 case WDIOC_GETSUPPORT:
> +=A0=A0=A0=A0=A0=A0=A0 if (copy_to_user((struct watchdog_info *)arg, =
&ident, =20
> sizeof(struct watchdog_info)))
> +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 return -EFAULT;
>  +=A0=A0=A0=A0=A0=A0=A0 else
>  +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 break;
>  +=A0=A0=A0 case WDIOC_GETSTATUS:
> +=A0=A0=A0=A0=A0=A0=A0 booke_wdt_get_status(&status);
> +=A0=A0=A0=A0=A0=A0=A0 return put_user(status,(int *)arg);
>  +=A0=A0=A0 case WDIOC_KEEPALIVE:
> +=A0=A0=A0=A0=A0=A0=A0 booke_wdt_ping();
> +=A0=A0=A0=A0=A0=A0=A0 break;
>  +=A0=A0=A0 case WDIOC_SETTIMEOUT:
> +=A0=A0=A0=A0=A0=A0=A0 if (get_user(new_timeout, (int *)arg))
>  +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 return -EFAULT;
>  +=A0=A0=A0=A0=A0=A0=A0 if (booke_wdt_set_timeout(new_timeout))
> +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 return -EINVAL;
>  +=A0=A0=A0=A0=A0=A0=A0 booke_wdt_ping();
> +=A0=A0=A0=A0=A0=A0=A0 break;
>  +=A0=A0=A0 case WDIOC_GETTIMEOUT:
> +=A0=A0=A0=A0=A0=A0=A0 return put_user(wdt_period, (int *)arg);
>  +=A0=A0=A0 case WDIOC_SETOPTIONS:
> +=A0=A0=A0=A0=A0=A0=A0 if (get_user(status, (int *)arg))
>  +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 return -EFAULT;
>  +=A0=A0=A0=A0=A0=A0=A0 /*=A0 Return -EINVAL when the driver can not =
figure out
>  +=A0=A0=A0=A0=A0=A0=A0=A0 *=A0 what it should do. Unknown cases are =
just ignored.
>  +=A0=A0=A0=A0=A0=A0=A0=A0 */
>  +=A0=A0=A0=A0=A0=A0=A0 if ( (status & =
(WDIOS_DISABLECARD|WDIOS_ENABLECARD))
> +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 =3D=3D =
(WDIOS_DISABLECARD|WDIOS_ENABLECARD) )
>  +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 return -EINVAL;
>  +=A0=A0=A0=A0=A0=A0=A0 if (status & WDIOS_DISABLECARD) {
>  +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 wdt_enable =3D 0;
>  +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 booke_wdt_stop();
> +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 booke_wdt_info("Watchdog timer is =
disabled\n");
>  +=A0=A0=A0=A0=A0=A0=A0 }
>  +=A0=A0=A0=A0=A0=A0=A0 if (status & WDIOS_ENABLECARD) {
>  +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 wdt_enable =3D 1;
>  +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 booke_wdt_start();
> +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 booke_wdt_info("Watchdog timer is =
enabled\n");
>  +=A0=A0=A0=A0=A0=A0=A0 }
>  +=A0=A0=A0=A0=A0=A0=A0 break;
>  +=A0=A0=A0 }
>  +=A0=A0=A0 return 0;
>  +}
>  +/**
>  + *=A0=A0=A0 booke_wdt_open:
> + *=A0=A0=A0 @inode: inode of device
>  + *=A0=A0=A0 @file: file handle to device
>  + *
>  + *=A0=A0=A0 The watchdog device has been opened. The watchdog device =
is =20
> single
> + *=A0=A0=A0 open and start the WDT timer.
>  + */
>  +static int
>  +booke_wdt_open(struct inode *inode, struct file *file)
>  +{
>  +=A0=A0=A0 if (!capable(CAP_SYS_ADMIN))
> +=A0=A0=A0=A0=A0=A0=A0 return -EPERM;
>  +
>  +=A0=A0=A0 if (test_and_set_bit(WDT_STATE_OPEN, &driver_state))
> +=A0=A0=A0=A0=A0=A0=A0 return -EBUSY;
>  +=A0=A0=A0 /*
>  +=A0=A0=A0=A0 * Activate
>  +=A0=A0=A0=A0 */
>  +=A0=A0=A0 booke_wdt_start();
> +=A0=A0=A0 wdt_enable=3D1;
> +
>  +=A0=A0=A0 if (nowayout)
>  +=A0=A0=A0=A0=A0 set_bit(WDT_STATE_STOP_ON_CLOSE, &driver_state);
> +
>  +=A0=A0=A0 return 0;
>  +}
>  +
>  +/**
>  + *=A0=A0=A0 booke_wdt_release:
> + *=A0=A0=A0 @inode: inode to board
> + *=A0=A0=A0 @file: file handle to board
>  + *
>  + */
>  +static int
>  +booke_wdt_release(struct inode *inode, struct file *file)
>  +{
>  +=A0 if (test_bit(WDT_STATE_STOP_ON_CLOSE, &driver_state)) {
>  +=A0=A0=A0=A0=A0 booke_wdt_note("WDT device is stopped.\n");
>  +=A0=A0=A0 booke_wdt_stop();
> +=A0=A0=A0 wdt_enable=3D0;
> +=A0 } else {
>  +=A0=A0=A0 if ( (booke_wdt_is_enabled()) && (!nowayout) ) {
>  +=A0=A0=A0=A0=A0 booke_wdt_note("WDT device may be closed =
unexpectedly.=A0 WDT =20
> will not stop!\n");
>  +=A0=A0=A0=A0=A0 booke_wdt_ping();
> +=A0=A0=A0 }
>  +=A0 }
>  +=A0 clear_bit(WDT_STATE_OPEN, &driver_state);
> +
>  +=A0 return 0;
>  +}
>  +/**
>  + *=A0=A0=A0 notify_sys:
>  + *=A0=A0=A0 @this: our notifier block
>  + *=A0=A0=A0 @code: the event being reported
> + *=A0=A0=A0 @unused: unused
>  + *=A0=A0=A0 Note: This function assume that the panic notifier is =
called =20
> with CODE=3D0
>  + *=A0=A0=A0=A0=A0=A0=A0=A0=A0 (see panic function in =
kernel/panic.c).
> + */
>  +static int
>  +booke_wdt_notify_sys(struct notifier_block *this, unsigned long =
code,
>  +=A0=A0=A0 void *unused)
>  +{
>  +
>  +=A0=A0=A0 if (code !=3D SYS_POWER_OFF)=A0=A0 /* Turn the card off */
>  +=A0=A0=A0=A0=A0 booke_wdt_stop();
> +
>  +=A0=A0=A0 return NOTIFY_DONE;
> +}
>  +
>  +static struct file_operations booke_wdt_fops =3D {
>  +=A0=A0=A0 .owner=A0=A0=A0=A0=A0=A0=A0 =3D THIS_MODULE,
> +=A0=A0=A0 .llseek=A0=A0=A0=A0=A0=A0=A0 =3D no_llseek,
>  +=A0=A0=A0 .write=A0=A0=A0=A0=A0=A0=A0 =3D booke_wdt_write,
> +=A0=A0=A0 .ioctl=A0=A0=A0=A0=A0=A0=A0 =3D booke_wdt_ioctl,
> +=A0=A0=A0 .open=A0=A0=A0=A0=A0=A0=A0 =3D booke_wdt_open,
> +=A0=A0=A0 .release=A0=A0=A0 =3D booke_wdt_release,
> +};
>  +
>  +static struct miscdevice booke_wdt_miscdev =3D {
>  +=A0=A0=A0 .minor=A0=A0=A0 =3D WATCHDOG_MINOR,
> +=A0=A0=A0 .name=A0=A0=A0 =3D "watchdog",
>  +=A0=A0=A0 .fops=A0=A0=A0 =3D &booke_wdt_fops,
> +};
>  +
>  +/*
>  + *=A0=A0=A0 The WDT card needs to know about shutdowns in order to
>  + *=A0=A0=A0 turn WDT off.
>  + */
>  +
>  +static struct notifier_block booke_wdt_notifier =3D {
>  +=A0=A0=A0 .notifier_call =3D booke_wdt_notify_sys,
> +};
>  +
>  +/**
>  + *=A0=A0=A0 cleanup_module:
> + *
>  + *=A0=A0=A0 If your watchdog is set to continue ticking on close and =
you =20
> unload
>  + *=A0=A0=A0 it, well it keeps ticking.=A0 You just have to load a =
new
>  + *=A0=A0=A0 module in 60 seconds or reboot.
>  + *=A0=A0=A0=A0=A0 This behavior(more over the comments as above) is =
borrowed =20
> from
>  + *=A0=A0=A0=A0=A0 Alan cox's driver.
>  + */
>  +
>  +static void __exit
>  +booke_wdt_exit(void)
> +{
>  +=A0=A0=A0 misc_deregister(&booke_wdt_miscdev);
> +=A0=A0=A0 unregister_reboot_notifier(&booke_wdt_notifier);
> +=A0=A0=A0 =20
> notifier_chain_unregister(&panic_notifier_list,&booke_wdt_notifier);
> +}
>  +
>  +/**
>  + *=A0=A0=A0=A0 booke_wdt_init:
> + *
>  + *=A0=A0=A0 Set up the WDT relevant timer facility.
>  + */
>  +
>  +static int __init
>  +booke_wdt_init(void)
> +{
>  +=A0=A0=A0 int ret;
>  +=A0=A0=A0 unsigned long flags;
>  +
>  +=A0=A0=A0 ret =3D register_reboot_notifier(&booke_wdt_notifier);
> +=A0=A0=A0 if(ret) {
>  +=A0=A0=A0=A0=A0 booke_wdt_err("Cannot register reboot notifier =
(err=3D%d)\n", =20
> ret);
>  +=A0=A0=A0=A0=A0 return ret;
> +=A0=A0=A0 }
>  +
>  +=A0=A0=A0 /* Register panic notifier=A0 */
>  +=A0=A0=A0 ret =3D =20
> notifier_chain_register(&panic_notifier_list,&booke_wdt_notifier);
> +=A0=A0=A0 if(ret) {
>  +=A0=A0=A0=A0=A0 booke_wdt_err("Cannot register panic notifier =
(err=3D%d)\n", =20
> ret);
>  +=A0=A0=A0=A0=A0 unregister_reboot_notifier(&booke_wdt_notifier);
> +=A0=A0=A0=A0=A0 return ret;
> +=A0=A0=A0 }
>  +
>  +=A0=A0=A0 ret =3D 0;
>  +=A0=A0=A0 booke_wdt_init_device();
> +=A0=A0=A0 /* Check that the heartbeat value is within it's range ; if =
not =20
> reset to the default */
>  +=A0=A0=A0 if (booke_wdt_set_timeout(wdt_period)) {
>  +=A0=A0=A0=A0=A0 if (wdt_period)
>  +=A0=A0=A0=A0=A0=A0=A0 booke_wdt_info("The heartbeat value must be %d =
< wdt_period =20
> < %d, using
> %d\n",WDT_HEARTBEAT_MIN,WDT_HEARTBEAT_MAX,WDT_TIMO);
> +=A0=A0=A0=A0=A0 booke_wdt_set_timeout(WDT_TIMO);
> +=A0=A0=A0 }
>  +
>  +=A0=A0=A0 local_irq_save(flags); /* Prevent timer interrupt */
>  +=A0=A0=A0 ppc_md.heartbeat_count =3D 0;
>  +=A0=A0=A0 ppc_md.heartbeat=3Dbooke_wdt_heartbeat;
> +=A0=A0=A0 local_irq_restore(flags);
> +
>  +=A0=A0=A0 booke_wdt_info("Book E(PPC 4xx/e500) Watchdog Driver. =
period=3D%d =20
> ms (nowayout=3D%d)\n",wdt_period,
>  nowayout);
>  +
>  +=A0=A0=A0 ret =3D misc_register(&booke_wdt_miscdev);
> +=A0=A0=A0 if (ret) {
>  +=A0=A0=A0=A0=A0 booke_wdt_err("Cannot register miscdev on minor=3D%d =
(err=3D%d)\n",
>  +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 WATCHDOG_MINOR, ret);
>  +=A0=A0=A0=A0=A0=A0=A0 goto outmisc;
>  +=A0=A0=A0 }
>  +
>  +=A0=A0=A0 if (wdt_enable) {
>  +=A0=A0=A0=A0=A0 booke_wdt_info("WDT start on boot.\n");
>  +=A0=A0=A0=A0=A0 booke_wdt_start();
> +=A0=A0=A0 }
>  +out:
>  +=A0=A0=A0 return ret;
>  +outmisc:
>  +=A0=A0=A0 unregister_reboot_notifier(&booke_wdt_notifier);
> +=A0=A0=A0 local_irq_save(flags);
> +=A0=A0=A0 ppc_md.heartbeat=3DNULL;
> +=A0=A0=A0 ppc_md.heartbeat_count =3D 0;
>  +=A0=A0=A0 local_irq_restore(flags);
> +=A0=A0=A0 goto out;
>  +}
>  +
>  +device_initcall(booke_wdt_init);
> --- linux-2.6.11/drivers/char/watchdog/booke_wdt.h=A0=A0=A0=A0=A0 =
1970-01-01 =20
> 09:00:00.000000000 +0900
>  +++ linux-2.6.11-booke-wdt/drivers/char/watchdog/booke_wdt.h=A0=A0=A0 =
=20
> 2005-03-04 16:38:58.000000000 +0900
>  @@ -0,0 +1,125 @@
>  +/*
>  + *
>  + *=A0=A0=A0 Copyright (c) 2004 Fujitsu Limited
>  + *
>  + *=A0=A0=A0 Module name: booke_wdt.h
>  + *=A0=A0=A0 Author:=A0=A0=A0=A0=A0 Takeharu =
KATO<kato.takeharu@jp.fujitsu.com>
> + *=A0=A0=A0 Description:
>  + *=A0=A0=A0=A0=A0 Header file for PowerPC Book E(PPC 4xx/e500) =
watchdog driver.
>  + *
>  + *=A0=A0=A0 This program is free software; you can redistribute it =
and/or
>  + *=A0=A0=A0 modify it under the terms of the GNU General Public =
License
> + *=A0=A0=A0 as published by the Free Software Foundation; either =
version 2
>  + *=A0=A0=A0 of the License, or (at your option) any later version.
>  + *
>  + *=A0=A0=A0 Neither Takeharu KATO nor Fujitsu Ltd. admit liability =
nor =20
> provide
>  + *=A0=A0=A0 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>
> +
>  +/*
>  + *=A0 Driver state flags(bit position)
>  + */
>  +#define WDT_STATE_OPEN=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=
=A0 0=A0=A0 /* driver is opend=A0 */
>  +#define WDT_STATE_STOP_ON_CLOSE=A0=A0=A0=A0=A0=A0=A0=A0 1=A0=A0 /* =
Stop with close is =20
> expected */
>  +/*
>  + * Configurations
> + */
>  +#define WDT_TIMO=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 60000=A0=A0=A0 /* =
Default timeout =3D 60000 =20
> ms(1min) */
>  +#define WDT_HEARTBEAT_MIN=A0 100=A0=A0=A0=A0=A0=A0=A0=A0=A0 /* =
Minimum timeout =3D 100 ms =20
> */
>  +#define WDT_HEARTBEAT_MAX=A0 600000=A0=A0=A0=A0=A0=A0 /* Maximum =
timeout =3D =20
> 600000ms(1hour) */
>  +#ifdef __KERNEL__
>  +//#define BOOKE_WDT_DEBUG=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=
=A0=A0=A0=A0=A0 /*=A0 Debug switch */
>  +/*
>  + *=A0 Reset type
> + */
>  +#define WDT_RESET_NONE=A0=A0=A0=A0 0
>  +#define WDT_RESET_CORE=A0=A0=A0=A0 1
>  +#define WDT_RESET_CHIP=A0=A0=A0=A0 2
>  +#define WDT_RESET_SYS=A0=A0=A0=A0=A0 3
>  +/*
>  + *=A0=A0 Bit positions in=A0 TCR register on PPC4xx/e500 series.
>  + */
>  +#define WDT_TCR_WP_BIT=A0=A0=A0=A0 1=A0=A0 /*=A0 WP=A0 bit in TCR =
(bit[0..1])=A0=A0 */
>  +#define WDT_TCR_WRC_BIT=A0=A0=A0 3=A0=A0 /*=A0 WRC bit in TCR =
(bit[2..3])=A0=A0 */
>  +#define WDT_TCR_WIE_BIT=A0=A0=A0 4=A0=A0 /*=A0 WIE bit in TCR =
(bit[4])=A0=A0=A0=A0=A0 */
>  +/*
>  + *=A0 TCR[WP] relevant definitions
>  + */
>  +#define WDT_TCR_WP_SHIFT=A0=A0=A0=A0=A0=A0 (31 - WDT_TCR_WP_BIT)
> +#define WDT_TCR_WRC_SHIFT=A0=A0=A0=A0=A0 (31 - WDT_TCR_WRC_BIT)
> +#define WDT_TCR_WIE_SHIFT=A0=A0=A0=A0=A0 (31 - WDT_TCR_WIE_BIT)
> +#define WDT_TCR_WDT_ENABLE=A0=A0=A0=A0 (1<<WDT_TCR_WIE_SHIFT)
> +/*=A0 MASK value to obatain TCR[WP]=A0 */
>  +#define WDT_TCR_WP_MASK=A0=A0=A0=A0=A0=A0=A0 (3<<(WDT_TCR_WP_SHIFT))
> +
>  +/*=A0 Watchdog timer periods can be set on PPC 4xx cpus. */
>  +#if defined(CONFIG_4xx)
> +/*
>  + *=A0 For PowerPC 4xx
>  + */
>  +#define WDT_WP0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 0
>  +#define WDT_WP1=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 1
>  +#define WDT_WP2=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 2
>  +#define WDT_WP3=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 3
>  +#else
>  +#if defined(CONFIG_E500)
> +/*
>  + *=A0 For e500 CPU
>  + *=A0 Actually, e500 can arbitrary periods can be set,
>  + *=A0 But this driver uses fix period value as same as PPC440
>  + *=A0 on purpose for simplicity.
>  + *=A0 Following values split into WP and WP_EXT parts in =
booke_wdt.c.
>  + */
>  +#define WDT_WP0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 21
>  +#define WDT_WP1=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 25
>  +#define WDT_WP2=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 29
>  +#define WDT_WP3=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 33
>  +#define WDT_TCR_WP_BITMSK=A0=A0=A0=A0 0x3=A0 /*=A0 2bit length=A0 */
>  +#define WDT_TCR_WPEXT_BITMSK=A0 0xf=A0 /*=A0 4bit length=A0 */
>  +#define WDT_TCR_WPEXT_SHIFT=A0 17
>  +#else
>  +#error "Book E WDT detects invalid configuration(Unknown CPU)"
>  +#endif=A0 /*=A0 CONFIG_E500=A0 */
>  +#endif=A0 /*=A0 CONFIG_4xx=A0=A0 */
>  +/*
>  + *=A0 WP relevant values used in our driver.
>  + *=A0 Note:WDT period must be more than HZ(Timer ticks)
> + */
>  +#define WDT_WP=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 =
WDT_WP3
>  +
>  +/*
>  + *=A0 IOCTL commands for comaptiblity for old driver
>  + */
>  +#define WDIOC_GETPERIOD=A0=A0=A0=A0=A0=A0=A0=A0 WDIOC_GETTIMEOUT
> +#define WDIOC_SETPERIOD=A0=A0=A0=A0=A0=A0=A0=A0 WDIOC_SETTIMEOUT
> +
>  +/*
>  + *=A0 output messages
>  + */
>  +#define __BOOKE_WDT_MSG "BookE-WDT : "
>  +#define booke_mkmsg(str) __BOOKE_WDT_MSG str
>  +#define booke_wdt_info(fmt,arg...) \
>  +=A0=A0=A0 printk(KERN_INFO __BOOKE_WDT_MSG fmt,##arg)
>  +#define booke_wdt_note(fmt,arg...) \
>  +=A0=A0=A0 printk(KERN_NOTICE __BOOKE_WDT_MSG fmt,##arg)
>  +#define booke_wdt_err(fmt,arg...) \
>  +=A0=A0=A0 printk(KERN_ALERT __BOOKE_WDT_MSG fmt,##arg)
>  +#define booke_wdt_crit(fmt,arg...) \
>  +=A0=A0=A0 printk(KERN_ALERT __BOOKE_WDT_MSG fmt,##arg)
>  +#if defined(BOOKE_WDT_DEBUG)
> +#define booke_wdt_dbg(fmt,arg...) \
>  +=A0=A0=A0 printk(KERN_ALERT __BOOKE_WDT_MSG fmt,##arg)
>  +#else
>  +#define booke_wdt_dbg(fmt,arg...) \
>  +=A0=A0=A0=A0=A0=A0=A0 do{}while(0)
>  +#endif=A0 /*=A0 WDT_DEBUG=A0 */
>  +
>  +#endif=A0 /* __KERNEL__=A0 */
>  +#endif=A0 /*=A0 _DRIVERS_CHAR_WATCHDOG_BOOKE_WDT_H=A0 */
>
> =20=

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH] WDT Driver for Book-E [2/2] Device driver part.
  2005-03-04 16:02                           ` Kumar Gala
@ 2005-03-04 16:35                             ` Matt Porter
  2005-03-04 16:44                               ` Kumar Gala
  0 siblings, 1 reply; 33+ messages in thread
From: Matt Porter @ 2005-03-04 16:35 UTC (permalink / raw)
  To: Kumar Gala; +Cc: ppcembed

On Fri, Mar 04, 2005 at 10:02:40AM -0600, Kumar Gala wrote:
> 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?

I see the 8xx example, however, there may be a case where somebody
wants to use another hardware watchdog mechanism.  In that case,
they probably don't want this facility automagically being enabled.
I think having the option can't hurt.

-Matt

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH] WDT Driver for Book-E [2/2] Device driver part.
  2005-03-04 16:35                             ` Matt Porter
@ 2005-03-04 16:44                               ` Kumar Gala
  0 siblings, 0 replies; 33+ messages in thread
From: Kumar Gala @ 2005-03-04 16:44 UTC (permalink / raw)
  To: Matt Porter; +Cc: ppcembed

Fair enough, we might actually have multiple watchdogs on some of are=20
parts when the integrate system logic w/its own watchdog.  Makes sense.=20=

  Lets leave it a config option then.

- kumar

On Mar 4, 2005, at 10:35 AM, Matt Porter wrote:

> On Fri, Mar 04, 2005 at 10:02:40AM -0600, Kumar Gala wrote:
>  > Matt,
>  >
> > Do you think this really needs a config option?=A0 Should it not be=A0=

> > sufficient that if you enable watchdog you get this functionality =
on=A0
> > 4xx/e500?
>
> I see the 8xx example, however, there may be a case where somebody
>  wants to use another hardware watchdog mechanism.=A0 In that case,
>  they probably don't want this facility automagically being enabled.
> I think having the option can't hurt.
>
> -Matt

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH] WDT Driver for Book-E [2/2] Device driver part.
  2005-03-04  9:38                         ` [PATCH] WDT Driver for Book-E [2/2] Device driver part Takeharu KATO
  2005-03-04 16:02                           ` Kumar Gala
@ 2005-03-05  0:34                           ` Josh Boyer
  2005-03-05  8:11                             ` Takeharu KATO
  1 sibling, 1 reply; 33+ messages in thread
From: Josh Boyer @ 2005-03-05  0:34 UTC (permalink / raw)
  To: Takeharu KATO; +Cc: ppcembed

On Fri, 2005-03-04 at 18:38 +0900, Takeharu KATO wrote:

Hi Takeharu,

Some comments below.  Looks good overall.

> 
> --- 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 )

This is slightly wrong.  Not all 4xx processors are BOOKE.  403 and 405
aren't to be specific.  But it's not really that big of a deal I guess.

> +
> +#ifdef CONFIG_WATCHDOG_NOWAYOUT
> +static int nowayout = 1;
> +#else
> +static int nowayout = 0;
> +#endif

Couldn't you just use the #ifdef in the release function and not
"disable" the watchdog?  It would save a global variable at least.

> + * 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);

If you order these in the right way, you don't need to declare them in
advance.

> +/**
> + *      __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))));
> +}

These two functions are somewhat misleading.  On 4xx the timer is
essentially always enabled.  The bit you are setting and clearing here
is just to enable the exception after the expiration of the 2nd WP.  The
reason I bring this up is because if you ever set TCR[WRC] to something
non-zero and this bit is off, the processor will just be reset after 3
watchdog periods.  In other words, if TCR[WRC] is ever non-zero there is
no such thing as disabling the timer.  You will always need to do the
ping to keep the processor from resetting.

> +/**
> + *    booke_wdt_stop:
> + *
> + *    Stop the watchdog driver.
> + */
> +static __inline__ int
> +booke_wdt_stop (void)
> +{
> +  __booke_wdt_disable();
> +  return 0;
> +}

This is effectively "stop getting the interrupt" on 4xx for the reasons
I said above.

> +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);
> +}

Since you're using WDT_RESET_NONE, I think what you have here should
work.  

> +/*
> + *  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

Most of this is in include/asm-ppc/reg_booke.h.  Could you use that
instead of redefining most of it?

> +/*
> + *  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  */

In include/linux/device.h there are dev_printk and dev_dbg macros that
do pretty much the same thing.  Could you use those instead?

Overall I think you have a good heartbeat style driver.  Just watch out
if you ever add an ioctl to set the reset type to something other than
none ;).

josh

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH] WDT Driver for Book-E [2/2] Device driver part.
  2005-03-05  0:34                           ` Josh Boyer
@ 2005-03-05  8:11                             ` Takeharu KATO
  2005-03-06 19:15                               ` Takeharu KATO
  0 siblings, 1 reply; 33+ messages in thread
From: Takeharu KATO @ 2005-03-05  8:11 UTC (permalink / raw)
  To: Josh Boyer; +Cc: ppcembed

Dear Josh:

Thank you for your thorough review.

Josh Boyer wrote:
> This is slightly wrong.  Not all 4xx processors are BOOKE.  403 and 405
> aren't to be specific.  But it's not really that big of a deal I guess.
> 
>
I know this.
As you said, I regard this with minor thing.


>>+
>>+#ifdef CONFIG_WATCHDOG_NOWAYOUT
>>+static int nowayout = 1;
>>+#else
>>+static int nowayout = 0;
>>+#endif
> 
> 
> Couldn't you just use the #ifdef in the release function and not
> "disable" the watchdog?  It would save a global variable at least.
> 
At first, I examined to remove the release file operation
to eliminate this global variable.
On second thought, I decided to use this global variable as 
drivers/char/watchdog/wdt.c.
I think that the release file operation is necessary to control
so as not to open the device more than twice.
This behavior is commonly used in other watch dog drivers,
doesn't it?

>>+static int __init booke_wdt_init(void);
>>+static void __exit booke_wdt_exit(void);
> 
> 
> If you order these in the right way, you don't need to declare them in
> advance.
> 
Ok, I'll remove them.

> 
>>+/**
>>+ *      __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))));
>>+}
> 
> 
> These two functions are somewhat misleading.  On 4xx the timer is
> essentially always enabled.  The bit you are setting and clearing here
> is just to enable the exception after the expiration of the 2nd WP.  The
> reason I bring this up is because if you ever set TCR[WRC] to something
> non-zero and this bit is off, the processor will just be reset after 3
> watchdog periods.  In other words, if TCR[WRC] is ever non-zero there is
> no such thing as disabling the timer.  You will always need to do the
> ping to keep the processor from resetting.
> 
  I agree that function names like XXX_wdt_enable(or disable) are not
reflected on precise meaning.

But in this driver, we set TCR[WRC] as zero.It is needed to detect and 
logging WDT timeout with software before MPU reset. I want to leave the 
way to find where the system hang up.
IMHO, this is the reason to use WDT in the system.
So, I will not support non-zero TCR[WRC].

 From the above-mentioned viewpoint, making WDT exception enabled (or 
disabled) means start/stop WDT itself in this driver.
This is the reason to adopt these names.

Please note that the system will panic before the CPU attempt to reset 
CPU when we use this driver.

Please let me hear it if there are some opinions.

> 
> Since you're using WDT_RESET_NONE, I think what you have here should
> work.  
>
Yes, however, it is implemented on purpose.
>>+/*
>>+ *  WP relevant values used in our driver.
>>+ *  Note:WDT period must be more than HZ(Timer ticks)
>>+ */
>>+#define WDT_WP                 WDT_WP3
> 
> 
> Most of this is in include/asm-ppc/reg_booke.h.  Could you use that
> instead of redefining most of it?
>
To tell the truth, this matter has been examined, but I forgot this.
Thank you for making it recall(^^

> 
> In include/linux/device.h there are dev_printk and dev_dbg macros that
> do pretty much the same thing.  Could you use those instead?
>
I did not know such thing.
I'll try to use them.

Regards,

-- 
Takeharu KATO

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH] WDT Driver for Book-E [2/2] Device driver part.
  2005-03-05  8:11                             ` Takeharu KATO
@ 2005-03-06 19:15                               ` Takeharu KATO
  2005-03-06 21:11                                 ` Josh Boyer
  0 siblings, 1 reply; 33+ messages in thread
From: Takeharu KATO @ 2005-03-06 19:15 UTC (permalink / raw)
  To: Takeharu KATO; +Cc: ppcembed

[-- Attachment #1: Type: text/plain, Size: 1176 bytes --]

Hi, Josh:

Takeharu KATO wrote:
>>
>>
>> Most of this is in include/asm-ppc/reg_booke.h.  Could you use that
>> instead of redefining most of it?
>>
> To tell the truth, this matter has been examined, but I forgot this.
> Thank you for making it recall(^^
> 
I performed minor fixes which you pointed out.
But I leaves WDT_WP[0123] on purpose.
The interpretation of this value is different between PPC4xx and e500.
To unite them, I leaves this.

>>
>> In include/linux/device.h there are dev_printk and dev_dbg macros that
>> do pretty much the same thing.  Could you use those instead?
>>
> I did not know such thing.
> I'll try to use them.
> 
On second thought, I found that it is not so good idea.
If I change this according to what you said, it is not
easy to find which driver outputs messages when we can
use multiple WDT in a system.

Macros in include/linux/device.h will use name member in miscdevice 
struct as driver's name, and this is commonly named as "watchdog".

FYI, I show the difference with the patch submitted last time.


Regards,I'll test this driver today, just in case, before I post the 
revised edition of this driver.

Regards,

-- 
Takeharu KATO

[-- Attachment #2: inter-booke_wdt.diff --]
[-- Type: text/plain, Size: 10446 bytes --]

--- linux-2.6.11-booke-wdt/drivers/char/watchdog/booke_wdt.c    2005-03-04 16:38:58.000000000 +0900
+++ linux-2.6.11-wdt/drivers/char/watchdog/booke_wdt.c	2005-03-07 03:35:34.000000000 +0900
@@ -76,86 +76,43 @@
 /*  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...2^17(PPC405) or 2^21(PPC440/e500) clocks
+ *                      1...2^21(PPC405) or 2^25(PPC440/e500) clocks
+ *                      2...2^25(PPC405) or 2^29(PPC440/e500) clocks
+ *                      3...2^25(PPC405) or 2^29(PPC440/e500) 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.
+ *     Note: The meaning of period number is differ PPC405 from PPC440.
+ *           Current version assume that this function called with 
+ *           WRC_NONE as reset, if someone who want to remove this 
+ *           constraint, please note that when we disable WDT, we should
+ *           set WRC with WRC_NONE and s/he should also  modify 
+ *           disable/enable_wdt function. 
+ *           
  */
-#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);
+  val=wdt_calculate_tcr(period,reset)| mfspr(SPRN_TCR);
   /*  Disable WDT  */
-  val &= ~(WDT_TCR_WDT_ENABLE);
+  val &= ~(TCR_WIE);
 
   mtspr(SPRN_TCR,val);
 }
-#endif  /*  CONFIG_E500 */
 /**
  *      __booke_wdt_enable
  *      Enable Watchdog
@@ -163,7 +120,7 @@
 static __inline__ void
 __booke_wdt_enable(void)
 {
-  mtspr(SPRN_TCR,(mfspr(SPRN_TCR)|WDT_TCR_WDT_ENABLE));
+  mtspr(SPRN_TCR,(mfspr(SPRN_TCR)|TCR_WIE));
 }
 /**
  *      __booke_wdt_disable
@@ -172,7 +129,7 @@
 static __inline__ void
 __booke_wdt_disable(void)
 {
-  mtspr(SPRN_TCR,(mfspr(SPRN_TCR)&(~(WDT_TCR_WDT_ENABLE))));
+  mtspr(SPRN_TCR,(mfspr(SPRN_TCR)&(~(TCR_WIE))));
 }
 /**
  *      __booke_wdt_is_enabled
@@ -181,7 +138,7 @@
 static __inline__ int
 __booke_wdt_is_enabled(void)
 {
-  return (mfspr(SPRN_TCR) & WDT_TCR_WDT_ENABLE);
+  return (mfspr(SPRN_TCR) & TCR_WIE);
 }
 /**
  *      __booke_wdt_clear_init_stat
@@ -272,6 +229,7 @@
 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",
@@ -294,6 +252,7 @@
 static __inline__ int
 booke_wdt_start(void)
 {
+
   __booke_wdt_enable();
   return 0;
 }
@@ -306,6 +265,7 @@
 static __inline__ int
 booke_wdt_stop (void)
 {
+
   __booke_wdt_disable();
   return 0;
 }
@@ -318,6 +278,7 @@
 static __inline__ int
 booke_wdt_ping(void)
 {
+
   /* Disable watchdog */
   __booke_wdt_disable();
   /* Write a watchdog value */
@@ -340,6 +301,7 @@
 static __inline__ int
 booke_wdt_set_timeout(int t)
 {
+
   if ((t < WDT_HEARTBEAT_MIN) || (t > WDT_HEARTBEAT_MAX))
     return -EINVAL;
 
@@ -360,6 +322,7 @@
 static __inline__ int
 booke_wdt_get_status(int *status)
 {
+
   if (wdt_enable)
       *status = WDIOS_ENABLECARD;
   else
@@ -378,11 +341,12 @@
 static void
 booke_wdt_init_device(void)
 {
-        /* Hardware WDT provided by the processor.
+
+    /* 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_setup_val(WDT_WP,WRC_NONE);
 }
 /**
  *    booke_wdt_write:
@@ -401,22 +365,22 @@
 {
   size_t i;
 
-    if (!nowayout) {
-      /* In case it was set long ago */
-      clear_bit(WDT_STATE_STOP_ON_CLOSE, &driver_state);
+  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;
+    for (i = 0; i < count; i++) {
+      char c;
 
-    if (get_user(c, buf + i))
-      return -EFAULT;
+      if (get_user(c, buf + i))
+	return -EFAULT;
 
-    if (c == 'V') {
-      set_bit(WDT_STATE_STOP_ON_CLOSE, &driver_state);
-    }
+      if (c == 'V') {
+	set_bit(WDT_STATE_STOP_ON_CLOSE, &driver_state);
       }
     }
-    booke_wdt_ping();
+  }
+  booke_wdt_ping();
 
   return count;
 }
@@ -523,12 +487,12 @@
 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_info("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_info("WDT device may be closed unexpectedly.  WDT will not stop!\n");
       booke_wdt_ping();
     }
   }
--- linux-2.6.11-booke-wdt/drivers/char/watchdog/booke_wdt.h    2005-03-04 16:38:58.000000000 +0900
+++ linux-2.6.11-wdt/drivers/char/watchdog/booke_wdt.h	2005-03-07 04:08:46.702851618 +0900
@@ -22,6 +22,7 @@
 #include <linux/kernel.h>
 #include <linux/ptrace.h>
 #include <linux/watchdog.h>
+#include <asm/reg_booke.h>
 
 /*
  *  Driver state flags(bit position)
@@ -32,32 +33,10 @@
  * 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) */
+#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)
@@ -68,6 +47,7 @@
 #define WDT_WP1               1
 #define WDT_WP2               2
 #define WDT_WP3               3
+#define wdt_calculate_tcr(period,reset) ( TCR_WP(period) | TCR_WRC(reset) ) 
 #else
 #if defined(CONFIG_E500)
 /*
@@ -81,9 +61,16 @@
 #define WDT_WP1               25
 #define WDT_WP2               29
 #define WDT_WP3               33
-#define WDT_TCR_WP_BITMSK     0x3  /*  2bit length  */
+#define WDT_TCR_WP_BITLEN      2 /*  2bit length  */
+#define WDT_TCR_WP_BITMSK     ((1<<(WDT_TCR_WP_BITLEN))-1)  /*  mask  */
 #define WDT_TCR_WPEXT_BITMSK  0xf  /*  4bit length  */
-#define WDT_TCR_WPEXT_SHIFT  17
+#define WDT_TCR_WPEXT_SHIFT   17
+#define WDT_WPEXT_VAL(period) (((period)>>WDT_TCR_WP_BITLEN)&    \
+			       (WDT_TCR_WPEXT_BITMSK))
+#define wdt_calculate_tcr(period,reset) \
+                         ( TCR_WP((period)&(WDT_TCR_WP_BITMSK))  |\
+			   TCR_WRC((reset))                      |\
+		   ( WDT_WPEXT_VAL(period) << WDT_TCR_WPEXT_SHIFT))
 #else
 #error "Book E WDT detects invalid configuration(Unknown CPU)"
 #endif  /*  CONFIG_E500  */
@@ -111,8 +98,6 @@
     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)

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH] WDT Driver for Book-E [2/2] Device driver part.
  2005-03-06 19:15                               ` Takeharu KATO
@ 2005-03-06 21:11                                 ` Josh Boyer
  0 siblings, 0 replies; 33+ messages in thread
From: Josh Boyer @ 2005-03-06 21:11 UTC (permalink / raw)
  To: Takeharu KATO; +Cc: ppcembed

On Mon, 2005-03-07 at 04:15 +0900, Takeharu KATO wrote:
> Hi, Josh:
> 
> Takeharu KATO wrote:
> >>
> > To tell the truth, this matter has been examined, but I forgot this.
> > Thank you for making it recall(^^
> > 
> I performed minor fixes which you pointed out.
> But I leaves WDT_WP[0123] on purpose.
> The interpretation of this value is different between PPC4xx and e500.
> To unite them, I leaves this.

Ok, that makes sense.

> 
> >>
> >> In include/linux/device.h there are dev_printk and dev_dbg macros that
> >> do pretty much the same thing.  Could you use those instead?
> >>
> > I did not know such thing.
> > I'll try to use them.
> > 
> On second thought, I found that it is not so good idea.
> If I change this according to what you said, it is not
> easy to find which driver outputs messages when we can
> use multiple WDT in a system.
> 
> Macros in include/linux/device.h will use name member in miscdevice 
> struct as driver's name, and this is commonly named as "watchdog".
> 

Ok, that's fine too.  No complaints here.

> FYI, I show the difference with the patch submitted last time.
> 
> 
> Regards,I'll test this driver today, just in case, before I post the 
> revised edition of this driver.

Thanks!  Looks good.

josh

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH] WDT Driver for Book-E [1/2] Architecture specific part.
  2005-03-04 15:54                           ` Kumar Gala
@ 2005-03-08 17:08                             ` Takeharu KATO
  0 siblings, 0 replies; 33+ messages in thread
From: Takeharu KATO @ 2005-03-08 17:08 UTC (permalink / raw)
  To: Kumar Gala; +Cc: ppcembed

Hi Kumar:

Kumar Gala wrote:
> Out of interest how did you test this?  If I find some time I will test  
> it on an e500 system, just havent given much thought on how to test the  
> watchdog though.
> 
> - kumar
> 
I tested the WDT driver with folowing test programs:

1) API test program which tests ioctl commands.
2) Test program which tests the behavior of the driver when
    system hung up due to making interrupt disabled(MSR[EE]=0 case).
    This test program is made as a kernel module.

Shall I send these programs off-list?

Regards,
-- 
Takeharu KATO

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH] WDT Driver for Book-E [1/2]  Architecture specific part.
@ 2005-03-09  4:55 Takeharu KATO
  0 siblings, 0 replies; 33+ messages in thread
From: Takeharu KATO @ 2005-03-09  4:55 UTC (permalink / raw)
  To: ppcembed

Matt,Kurmar and Josh:

I performed minor cleanups which Josh pointed out.
It has been fine-tuned that it suits current linux-2.6.11(linus-tree).
(These changes has been performed on architecture specific part.).

I tested the driver on PowerPC440GP(ebony) again and I confirmed
that the driver work.

At first, I post the architecture specific part with this mail.

Please apply.

Regards,

Signed-off-by: Takeharu KATO <kato.takeharu@jp.fujitsu.com>

diff -Nupr linux-2.6.11/arch/ppc/kernel/head_44x.S linux-2.6.11-wdt/arch/ppc/kernel/head_44x.S
--- linux-2.6.11/arch/ppc/kernel/head_44x.S	2005-03-09 12:55:02.725778464 +0900
+++ linux-2.6.11-wdt/arch/ppc/kernel/head_44x.S	2005-03-09 13:07:38.355905224 +0900
@@ -444,8 +444,11 @@ interrupt_base:
 	EXCEPTION(0x1010, FixedIntervalTimer, UnknownException, EXC_XFER_EE)

 	/* Watchdog Timer Interrupt */
-	/* TODO: Add watchdog support */
+#if defined(CONFIG_BOOKE_WDT)
+	CRITICAL_EXCEPTION(0x1020, WatchdogTimer, booke_wdt_exception)
+#else
 	CRITICAL_EXCEPTION(0x1020, WatchdogTimer, UnknownException)
+#endif  /*  CONFIG_BOOKE_WDT  */

 	/* Data TLB Error Interrupt */
 	START_EXCEPTION(DataTLBError)
diff -Nupr linux-2.6.11/arch/ppc/kernel/head_4xx.S linux-2.6.11-wdt/arch/ppc/kernel/head_4xx.S
--- linux-2.6.11/arch/ppc/kernel/head_4xx.S	2005-03-09 12:58:03.942229376 +0900
+++ linux-2.6.11-wdt/arch/ppc/kernel/head_4xx.S	2005-03-09 13:07:38.357904920 +0900
@@ -469,27 +469,24 @@ label:

 /* 0x1000 - Programmable Interval Timer (PIT) Exception */
 	START_EXCEPTION(0x1000, Decrementer)
-	NORMAL_EXCEPTION_PROLOG
-	lis	r0,TSR_PIS@h
-	mtspr	SPRN_TSR,r0		/* Clear the PIT exception */
-	addi	r3,r1,STACK_FRAME_OVERHEAD
-	EXC_XFER_LITE(0x1000, timer_interrupt)
+	b    DecrementerHandler

 #if 0
 /* NOTE:
- * FIT and WDT handlers are not implemented yet.
+ * FIT handler is not implemented yet.
  */

 /* 0x1010 - Fixed Interval Timer (FIT) Exception
 */
 	STND_EXCEPTION(0x1010,	FITException,		UnknownException)

-/* 0x1020 - Watchdog Timer (WDT) Exception
-*/
-
-	CRITICAL_EXCEPTION(0x1020, WDTException, UnknownException)
 #endif

+/* 0x1020 - Watchdog Timer (WDT) Exception
+ */
+	START_EXCEPTION(0x1020, WDTException)
+	b    WatchDogHandler
+
 /* 0x1100 - Data TLB Miss Exception
  * As the name implies, translation is not in the MMU, so search the
  * page tables and fix it.  The only purpose of this function is to
@@ -771,6 +768,13 @@ label:
 		(MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \
 		NOCOPY, crit_transfer_to_handler, ret_from_crit_exc)

+DecrementerHandler:
+	NORMAL_EXCEPTION_PROLOG
+	lis    r0,TSR_PIS@h
+	mtspr    SPRN_TSR,r0        /* Clear the PIT exception */
+	addi    r3,r1,STACK_FRAME_OVERHEAD
+	EXC_XFER_LITE(0x1000, timer_interrupt)
+
 /*
  * The other Data TLB exceptions bail out to this point
  * if they can't resolve the lightweight TLB fault.
@@ -843,6 +847,19 @@ finish_tlb_load:
 	PPC405_ERR77_SYNC
 	rfi			/* Should sync shadow TLBs */
 	b	.		/* prevent prefetch past rfi */
+/*
+ * WatchDog Exception
+ */
+WatchDogHandler:
+	CRITICAL_EXCEPTION_PROLOG;
+	addi    r3,r1,STACK_FRAME_OVERHEAD;
+#if defined(CONFIG_BOOKE_WDT)
+	EXC_XFER_TEMPLATE(booke_wdt_exception, 0x1022, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)),NOCOPY, crit_transfer_to_handler, ret_from_crit_exc)
+
+#else
+	EXC_XFER_TEMPLATE(UnknownException, 0x1022, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)),NOCOPY, crit_transfer_to_handler, ret_from_crit_exc)
+#endif  /*  CONFIG_BOOKE_WDT  */
+

 /* extern void giveup_fpu(struct task_struct *prev)
  *
diff -Nupr linux-2.6.11/arch/ppc/kernel/head_e500.S linux-2.6.11-wdt/arch/ppc/kernel/head_e500.S
--- linux-2.6.11/arch/ppc/kernel/head_e500.S	2005-03-09 12:57:14.058812808 +0900
+++ linux-2.6.11-wdt/arch/ppc/kernel/head_e500.S	2005-03-09 13:07:38.357904920 +0900
@@ -494,8 +494,11 @@ interrupt_base:
 	EXCEPTION(0x3100, FixedIntervalTimer, UnknownException, EXC_XFER_EE)

 	/* Watchdog Timer Interrupt */
-	/* TODO: Add watchdog support */
+#if defined(CONFIG_BOOKE_WDT)
+	CRITICAL_EXCEPTION(0x3200, WatchdogTimer, booke_wdt_exception)
+#else
 	CRITICAL_EXCEPTION(0x3200, WatchdogTimer, UnknownException)
+#endif  /*  CONFIG_BOOKE_WDT  */

 	/* Data TLB Error Interrupt */
 	START_EXCEPTION(DataTLBError)
diff -Nupr linux-2.6.11/arch/ppc/kernel/time.c linux-2.6.11-wdt/arch/ppc/kernel/time.c
diff -Nupr linux-2.6.11/arch/ppc/platforms/85xx/mpc8540_ads.c linux-2.6.11-wdt/arch/ppc/platforms/85xx/mpc8540_ads.c
--- linux-2.6.11/arch/ppc/platforms/85xx/mpc8540_ads.c	2005-03-09 12:55:23.468625072 +0900
+++ linux-2.6.11-wdt/arch/ppc/platforms/85xx/mpc8540_ads.c	2005-03-09 13:07:38.358904768 +0900
@@ -187,6 +187,14 @@ platform_init(unsigned long r3, unsigned
 		strcpy(cmd_line, (char *) (r6 + KERNELBASE));
 	}

+#ifdef CONFIG_BOOKE_WDT
+     {
+       extern void booke_wdt_setup_options(char *cmd_line);
+
+       booke_wdt_setup_options(cmd_line);
+     }
+#endif  /*  CONFIG_BOOKE_WDT  */
+
 	identify_ppc_sys_by_id(mfspr(SVR));

 	/* setup the PowerPC module struct */
diff -Nupr linux-2.6.11/arch/ppc/platforms/85xx/mpc8560_ads.c linux-2.6.11-wdt/arch/ppc/platforms/85xx/mpc8560_ads.c
--- linux-2.6.11/arch/ppc/platforms/85xx/mpc8560_ads.c	2005-03-09 12:59:02.157379328 +0900
+++ linux-2.6.11-wdt/arch/ppc/platforms/85xx/mpc8560_ads.c	2005-03-09 13:07:38.358904768 +0900
@@ -197,6 +197,14 @@ platform_init(unsigned long r3, unsigned
 		strcpy(cmd_line, (char *) (r6 + KERNELBASE));
 	}

+#ifdef CONFIG_BOOKE_WDT
+     {
+       extern void booke_wdt_setup_options(char *cmd_line);
+
+       booke_wdt_setup_options(cmd_line);
+     }
+#endif  /*  CONFIG_BOOKE_WDT  */
+
 	identify_ppc_sys_by_id(mfspr(SVR));

 	/* setup the PowerPC module struct */
diff -Nupr linux-2.6.11/arch/ppc/platforms/85xx/mpc85xx_cds_common.c linux-2.6.11-wdt/arch/ppc/platforms/85xx/mpc85xx_cds_common.c
--- linux-2.6.11/arch/ppc/platforms/85xx/mpc85xx_cds_common.c	2005-03-09 12:57:51.908058848 +0900
+++ linux-2.6.11-wdt/arch/ppc/platforms/85xx/mpc85xx_cds_common.c	2005-03-09 13:07:38.359904616 +0900
@@ -448,6 +448,14 @@ platform_init(unsigned long r3, unsigned
 		strcpy(cmd_line, (char *) (r6 + KERNELBASE));
 	}

+#ifdef CONFIG_BOOKE_WDT
+     {
+       extern void booke_wdt_setup_options(char *cmd_line);
+
+       booke_wdt_setup_options(cmd_line);
+     }
+#endif  /*  CONFIG_BOOKE_WDT  */
+
 	identify_ppc_sys_by_id(mfspr(SVR));

 	/* setup the PowerPC module struct */
diff -Nupr linux-2.6.11/arch/ppc/platforms/85xx/mpc85xx_cds_common.c.orig linux-2.6.11-wdt/arch/ppc/platforms/85xx/mpc85xx_cds_common.c.orig
diff -Nupr linux-2.6.11/arch/ppc/platforms/85xx/sbc8560.c linux-2.6.11-wdt/arch/ppc/platforms/85xx/sbc8560.c
--- linux-2.6.11/arch/ppc/platforms/85xx/sbc8560.c	2005-03-09 12:58:37.742091016 +0900
+++ linux-2.6.11-wdt/arch/ppc/platforms/85xx/sbc8560.c	2005-03-09 13:07:38.360904464 +0900
@@ -198,6 +198,14 @@ platform_init(unsigned long r3, unsigned
 		strcpy(cmd_line, (char *) (r6 + KERNELBASE));
 	}

+#ifdef CONFIG_BOOKE_WDT
+     {
+       extern void booke_wdt_setup_options(char *cmd_line);
+
+       booke_wdt_setup_options(cmd_line);
+     }
+#endif  /*  CONFIG_BOOKE_WDT  */
+
 	identify_ppc_sys_by_id(mfspr(SVR));

 	/* setup the PowerPC module struct */
diff -Nupr linux-2.6.11/arch/ppc/platforms/85xx/stx_gp3.c linux-2.6.11-wdt/arch/ppc/platforms/85xx/stx_gp3.c
--- linux-2.6.11/arch/ppc/platforms/85xx/stx_gp3.c	2005-03-09 12:56:20.477958336 +0900
+++ linux-2.6.11-wdt/arch/ppc/platforms/85xx/stx_gp3.c	2005-03-09 13:07:38.361904312 +0900
@@ -349,6 +349,14 @@ platform_init(unsigned long r3, unsigned
 		strcpy(cmd_line, (char *) (r6 + KERNELBASE));
 	}

+#ifdef CONFIG_BOOKE_WDT
+     {
+       extern void booke_wdt_setup_options(char *cmd_line);
+
+       booke_wdt_setup_options(cmd_line);
+     }
+#endif  /*  CONFIG_BOOKE_WDT  */
+
 	identify_ppc_sys_by_id(mfspr(SVR));

 	/* setup the PowerPC module struct */
diff -Nupr linux-2.6.11/arch/ppc/platforms/85xx/stx_gp3.c.orig linux-2.6.11-wdt/arch/ppc/platforms/85xx/stx_gp3.c.orig
diff -Nupr linux-2.6.11/arch/ppc/syslib/open_pic.c linux-2.6.11-wdt/arch/ppc/syslib/open_pic.c
diff -Nupr linux-2.6.11/arch/ppc/syslib/ppc4xx_setup.c linux-2.6.11-wdt/arch/ppc/syslib/ppc4xx_setup.c
--- linux-2.6.11/arch/ppc/syslib/ppc4xx_setup.c	2005-03-09 12:54:06.589312504 +0900
+++ linux-2.6.11-wdt/arch/ppc/syslib/ppc4xx_setup.c	2005-03-09 13:07:38.361904312 +0900
@@ -48,10 +48,6 @@
 extern void abort(void);
 extern void ppc4xx_find_bridges(void);

-extern void ppc4xx_wdt_heartbeat(void);
-extern int wdt_enable;
-extern unsigned long wdt_period;
-
 /* Global Variables */
 bd_t __res;

@@ -257,22 +253,14 @@ ppc4xx_init(unsigned long r3, unsigned l
 		*(char *) (r7 + KERNELBASE) = 0;
 		strcpy(cmd_line, (char *) (r6 + KERNELBASE));
 	}
-#if defined(CONFIG_PPC405_WDT)
-/* 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;
-	}
-#endif
+
+#ifdef CONFIG_BOOKE_WDT
+     {
+       extern void booke_wdt_setup_options(char *cmd_line);
+
+       booke_wdt_setup_options(cmd_line);
+     }
+#endif  /*  CONFIG_BOOKE_WDT  */

 	/* Initialize machine-dependent vectors */

^ permalink raw reply	[flat|nested] 33+ messages in thread

end of thread, other threads:[~2005-03-09  4:56 UTC | newest]

Thread overview: 33+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-02-23 19:00 PowerPC4xx Watchdog Takeharu KATO
2005-02-23 19:15 ` Takeharu KATO
2005-02-23 21:27   ` Matt Porter
2005-02-23 23:23     ` Takeharu KATO
2005-02-23 23:36       ` Takeharu KATO
2005-03-02 17:52         ` Matt Porter
2005-03-02 23:06           ` Kumar Gala
2005-03-02 23:15             ` Matt Porter
2005-03-03 11:50               ` Takeharu KATO
2005-03-03 12:13                 ` Takeharu KATO
2005-03-03 14:53                   ` Kumar Gala
2005-03-03 15:20                     ` Matt Porter
2005-03-03 15:21                     ` Takeharu KATO
2005-03-03 17:11                       ` Matt Porter
2005-03-04  9:38                         ` [PATCH] WDT Driver for Book-E [1/2] Architecture specific part Takeharu KATO
2005-03-04 15:54                           ` Kumar Gala
2005-03-08 17:08                             ` Takeharu KATO
2005-03-04  9:38                         ` [PATCH] WDT Driver for Book-E [2/2] Device driver part Takeharu KATO
2005-03-04 16:02                           ` Kumar Gala
2005-03-04 16:35                             ` Matt Porter
2005-03-04 16:44                               ` Kumar Gala
2005-03-05  0:34                           ` Josh Boyer
2005-03-05  8:11                             ` Takeharu KATO
2005-03-06 19:15                               ` Takeharu KATO
2005-03-06 21:11                                 ` Josh Boyer
2005-02-25 19:35     ` PowerPC4xx Watchdog Takeharu KATO
2005-02-28 13:18       ` [PATCH 1/3] PowerPC4xx/E500 WatchDogTimerDriver(Core and PPC4xx part) Takeharu KATO
2005-02-28 13:20       ` PowerPC4xx Watchdog Takeharu KATO
2005-02-28 13:27       ` [PATCH 3/3] PowerPC4xx/E500 WatchDogTimerDriver(exception handler part) Takeharu KATO
2005-03-03  7:14         ` Kumar Gala
2005-03-03  7:31           ` Takeharu KATO
2005-03-03 12:07         ` Takeharu KATO
  -- strict thread matches above, loose matches on Subject: below --
2005-03-09  4:55 [PATCH] WDT Driver for Book-E [1/2] Architecture specific part Takeharu KATO

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).