Skip to contentSkip to conversation

PowerPC4xx Watchdog

PATCH In review Takeharu KATO 5 participants 32 messages Feb 23, 2005 – Mar 8, 2005 Char and misc drivers

lore
Share & tools
lore
#0 lore raw

Hi

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

Signature · 1 line
Takeharu KATO
#1 lore raw

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?

Quoted 5 lines · Takeharu KATO

Hi

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

Signature · 1 line
Takeharu KATO
#2 lore raw
Quoted 7 lines · Takeharu KATO

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

#3 lore raw

Hi

Quoted 5 lines

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.

Signature · 1 line
Takeharu KATO
#4 lore raw

Hi

Quoted 7 lines
Quoted 4 lines

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?

Signature · 1 line
Takeharu KATO
#5 lore raw
Quoted 6 lines · Takeharu KATO

Hi

Quoted 4 lines
Quoted 4 lines

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?

Quoted 6 lines
Quoted 4 lines

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

#6 lore raw

Matt,

[snip]

Quoted 3 lines

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

#7 lore raw
Quoted 10 lines · Kumar Gala

Matt,

[snip]

Quoted 3 lines

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

#8 lore raw

Matt and Kurmar,

Thank you for your response.

Quoted 4 lines
Quoted 4 lines
Quoted 3 lines

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

Quoted 5 lines

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,

Signature · 3 lines
Takeharu KATO
Fujitsu Limited
Email:kato.takeharu at jp.fujitsu.com
#9 lore raw

Matt and Kurmar:

Sorry to typo:

Quoted 3 lines

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.

Signature · 3 lines
Takeharu KATO
Fujitsu Limited
Email:kato.takeharu at jp.fujitsu.com
#10 lore raw

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

to me for e500 to have 4xx references.

- kumar

Quoted 21 lines · Takeharu KATO

Matt and Kurmar:

Sorry to typo:

Quoted 2 lines

Because the incidence of the problem is very low,
it is important to=A0 the generation part such a problem when=20

generated.

Quoted 1 line

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

#11 lore raw
Quoted 2 lines · Kumar Gala

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

#12 lore raw
In reply to Kumar Gala

Hi Kumar,

Thank you for your suggestion.

Quoted 2 lines · Kumar Gala

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.

Signature · 1 line
Takeharu KATO
#13 lore raw
Quoted 8 lines · Takeharu KATO

Hi Kumar,

Thank you for your suggestion.

Quoted 3 lines · Kumar Gala

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

Quoted 5 lines

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

#14 lore raw

PATCH 1/1 WDT Driver for Book-E [1/2] Architecture specific part.

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,

arch/ppc/kernel/head_44x.S +5 -1
@@ -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)
arch/ppc/kernel/head_4xx.S +28 -11
@@ -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
arch/ppc/kernel/head_e500.S +4 -1
@@ -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)
arch/ppc/platforms/85xx/mpc8540_ads.c +9 -0
@@ -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 */
arch/ppc/platforms/85xx/mpc8560_ads.c +8 -0
@@ -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 */
arch/ppc/platforms/85xx/mpc85xx_cds_common.c +8 -0
@@ -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 */
arch/ppc/platforms/85xx/sbc8560.c +8 -0
@@ -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 */
arch/ppc/platforms/85xx/stx_gp3.c +9 -0
@@ -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 */
arch/ppc/syslib/ppc4xx_setup.c +10 -20
@@ -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
 
 }
+
+
#15 lore raw

Re: [PATCH] WDT Driver for Book-E [1/2] Architecture specific part.

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

Quoted 23 lines · Takeharu KATO

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.

Quoted 7 lines

Regards,

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

Quoted 3 lines

13:21:31.000000000 +0900
@@ -444,8 +444,12 @@ interrupt_base:
=A0 =A0=A0=A0=A0=A0 EXCEPTION(0x1010, FixedIntervalTimer, =

UnknownException, =20

Quoted 6 lines

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)

Quoted 2 lines

+#else
=A0 =A0=A0=A0=A0=A0 CRITICAL_EXCEPTION(0x1020, WatchdogTimer, =

UnknownException)

Quoted 8 lines

+#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

Quoted 8 lines

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

Quoted 10 lines

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

Quoted 3 lines

=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

Quoted 6 lines

UnknownException)

-/* 0x1020 - Watchdog Timer (WDT) Exception
-*/
-
-=A0=A0=A0=A0=A0=A0 CRITICAL_EXCEPTION(0x1020, WDTException, =

UnknownException)

Quoted 9 lines

=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

Quoted 1 line

=A0=A0 * page tables and fix it.=A0 The only purpose of this function =

is to

Quoted 2 lines

@@ -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)), \

Quoted 1 line

=A0 =A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 NOCOPY, =

crit_transfer_to_handler, ret_from_crit_exc)

Quoted 6 lines

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

Quoted 8 lines
 +=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 */

Quoted 1 line

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

Review

Quoted 9 lines
(quoted diff) +5 -0
+/*
 + * 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

Quoted 5 lines

~(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

Quoted 7 lines

~(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

Quoted 8 lines

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

Quoted 6 lines

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)

Quoted 2 lines

+#else
=A0 =A0=A0=A0=A0=A0 CRITICAL_EXCEPTION(0x3200, WatchdogTimer, =

UnknownException)

Quoted 9 lines

+#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

Quoted 8 lines
2005-03-04 13:21:31.000000000 +0900
 @@ -54,6 +54,7 @@

=A0 #include <syslib/ppc85xx_setup.h>

+
=A0 /* =20
=

***********************************************************************=20=

Quoted 5 lines

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

Quoted 5 lines

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

Quoted 7 lines

+

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

Quoted 6 lines

=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

Quoted 3 lines
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));

Quoted 5 lines

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

Quoted 10 lines

+

 +=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=

Quoted 8 lines
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));

Quoted 5 lines

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

Quoted 9 lines

+

 +=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

Quoted 2 lines

17:17:22.985877656 +0900
+++ linux-2.6.11-booke-wdt/arch/ppc/platforms/85xx/sbc8560.c=A0=A0=A0 =

=20

Quoted 3 lines
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));

Quoted 5 lines

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

Quoted 9 lines

+

 +=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

Quoted 2 lines

17:14:12.883777568 +0900
+++ linux-2.6.11-booke-wdt/arch/ppc/platforms/85xx/stx_gp3.c=A0=A0=A0 =

=20

Quoted 10 lines
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

Quoted 3 lines

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

Quoted 5 lines

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

Quoted 11 lines

+

 +=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

Quoted 13 lines
2005-03-04 13:21:31.000000000 +0900
 @@ -48,10 +48,6 @@
 =A0 extern void abort(void);
 =A0 extern void ppc4xx_find_bridges(void);
(quoted diff) +0 -2
-extern void ppc4xx_wdt_heartbeat(void);
-extern int wdt_enable;
 -extern unsigned long wdt_period;
 -
 =A0 /* Global Variables */
 =A0 bd_t __res;

Review ppc4xx_init(unsigned long r3, unsigned l · line 253

Quoted 1 line
(quoted diff) +0 -0
@@ -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;

Review ppc4xx_init(unsigned long r3, unsigned l · line 254

Quoted 1 line
(quoted diff) +0 -0
 =A0 =A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 strcpy(cmd_line, (char *) =

(r6 + KERNELBASE));

Review ppc4xx_init(unsigned long r3, unsigned l · line 260

Quoted 7 lines
(quoted diff) +0 -1
 =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;) {

Review ppc4xx_init(unsigned long r3, unsigned l · line 266

Quoted 1 line
(quoted diff) +0 -1
-=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0 q =3D =

p + 4;

Review ppc4xx_init(unsigned long r3, unsigned l · line 263

Quoted 3 lines
(quoted diff) +0 -0
 -=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;

Review ppc4xx_init(unsigned long r3, unsigned l · line 270

Quoted 1 line
(quoted diff) +0 -1
-=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);

Review ppc4xx_init(unsigned long r3, unsigned l · line 264

Quoted 1 line
(quoted diff) +0 -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;

Review ppc4xx_init(unsigned long r3, unsigned l

Quoted 9 lines
(quoted diff) +1 -0
 -=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);

Quoted 16 lines

+

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

(quoted diff) +0 -0
@@ -319,3 +307,5 @@ void platform_machine_check(struct pt_re
 =A0 #endif
 
 =A0 }
 +
 +

=20=

#16 lore raw

Re: [PATCH] WDT Driver for Book-E [1/2] Architecture specific part.

Hi Kumar:

Quoted 4 lines · Kumar Gala

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,

Signature · 1 line
Takeharu KATO
#17 lore raw

PATCH 1/1 WDT Driver for Book-E [2/2] Device driver part.

In reply to Matt Porter

Matt and Kurmar:

I post the device driver part with this mail.

This is the last part of this driver.

Please apply.

Regards,

drivers/char/watchdog/Kconfig +7 -0
@@ -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
drivers/char/watchdog/Makefile +1 -0
@@ -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
drivers/char/watchdog/booke_wdt.c +664 -0

664 lines not on this page · raw message

drivers/char/watchdog/booke_wdt.h +125 -0

125 lines not on this page · raw message

#18 lore raw

Re: [PATCH] WDT Driver for Book-E [2/2] Device driver part.

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

Quoted 8 lines · Takeharu KATO

Matt and Kurmar:

I post the device driver part with this mail.

This is the last part of this driver.

Please apply.

Quoted 7 lines

Regards,

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

Quoted 11 lines
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.
Quoted 7 lines

+
=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

Quoted 7 lines
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

Quoted 2 lines

09:00:00.000000000 +0900
+++ linux-2.6.11-booke-wdt/drivers/char/watchdog/booke_wdt.c=A0=A0=A0 =

=20

Quoted 7 lines
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<[email protected]>

Quoted 2 lines

+ *
+ *=A0=A0=A0 This program is free software; you can redistribute it =

and/or

Quoted 1 line

+ *=A0=A0=A0 modify it under the terms of the GNU General Public =

License

Quoted 1 line

+ *=A0=A0=A0 as published by the Free Software Foundation; either =

version 2

Quoted 3 lines

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

Quoted 5 lines

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

Quoted 4 lines

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

Quoted 4 lines

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.

Quoted 1 line

+ *=A0=A0=A0=A0 This driver is written according to ``PowerPC e500 =

Core =20

Quoted 16 lines

Complex
+ *=A0=A0=A0=A0 Reference Manual'' for e500 part.
+ */
+#include <linux/config.h>

drivers/char/watchdog/booke_wdt.c +9 -0
+#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>

drivers/char/watchdog/booke_wdt.c

Quoted 10 lines
drivers/char/watchdog/booke_wdt.c +5 -0
+#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 */

Quoted 4 lines

+int wdt_period=3DWDT_TIMO;=A0=A0=A0=A0=A0=A0 /* Time out in ms */ +
+#ifdef CONFIG_WATCHDOG_NOWAYOUT
+static int nowayout =3D 1;

Quoted 8 lines

+#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

Quoted 10 lines

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 {

Quoted 2 lines
 +=A0 .options=3DWDIOF_SETTIMEOUT|WDIOF_KEEPALIVEPING|WDIOF_MAGICCLOSE,
+=A0 .firmware_version =3D=A0=A0=A0 0, /*=A0 This is filled with PVR =

in =20

Quoted 41 lines

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;

(quoted diff) +12 -0
+/*
 + *=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);

Review

Quoted 2 lines
(quoted diff) +2 -0
+static int booke_wdt_release(struct inode *inode, struct file *file);
+static int booke_wdt_notify_sys(struct notifier_block *this, unsigned =

=20

Review

Quoted 11 lines

long code,void *unused);
+static int __init booke_wdt_init(void);

(quoted diff) +3 -0
+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],

Quoted 4 lines

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

Quoted 1 line

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

Quoted 1 line

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

Quoted 1 line

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

Quoted 1 line

+ *=A0=A0=A0=A0=A0 @reset:=A0=A0=A0=A0=A0=A0=A0=A0 Watchdog reset =

control - TCR[WRC]

Quoted 1 line

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

Quoted 1 line

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

Quoted 1 line

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

Quoted 1 line

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

Quoted 1 line

+ *=A0=A0=A0=A0 Note: The meaning of period number is differ PPC440GP =

from =20

Quoted 11 lines

PPC440GX.
+ */
+#if defined(CONFIG_4xx)

(quoted diff) +2 -0
+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=

Quoted 84 lines

TCR);

+=A0 /*=A0 Disable WDT=A0 */
 +=A0 val &=3D ~(WDT_TCR_WDT_ENABLE);
(quoted diff) +4 -0
+
 +=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);
(quoted diff) +22 -0
+
 +=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

Review

Quoted 10 lines
(quoted diff) +1 -0
 +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;) =

{

Quoted 39 lines
+=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)

(quoted diff) +4 -0
+{
 +=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;
 +}
 +/**

Review

Quoted 10 lines
(quoted diff) +4 -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",

Quoted 1 line

+=A0=A0=A0=A0=A0=A0=A0 regs->nip, regs->msr, regs->trap, =

print_tainted());

Quoted 27 lines

+=A0 panic(booke_mkmsg("Initiating system reboot.\n"));
+}
+/*
+ *=A0=A0=A0 Driver Logic functions
+ */
+static __inline__ int +booke_wdt_is_enabled(void)

(quoted diff) +6 -0
+{
 +=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.
 + */

Review

Quoted 10 lines
(quoted diff) +2 -0
 +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

Quoted 10 lines

bother reloading
+ *=A0=A0=A0 the cascade counter.
+ */
+static __inline__ int
+booke_wdt_ping(void)

(quoted diff) +2 -0
+{
 +=A0 /* Disable watchdog */
 +=A0 __booke_wdt_disable();
+=A0 /* Write a watchdog value */
 +=A0 __booke_wdt_clear_int_stat();

Review

Quoted 10 lines
(quoted diff) +4 -0
+=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.

Quoted 3 lines

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

Quoted 29 lines

+ *=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);
(quoted diff) +3 -0
+
 +=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;

Review

Quoted 10 lines
(quoted diff) +2 -0
+
 +=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.

Quoted 6 lines

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

Quoted 8 lines
 +=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

Quoted 2 lines

+ *=A0=A0=A0 @count: count of bytes
+ *=A0=A0=A0 @ppos: pointer to the position to write. No seeks =

allowed

Quoted 2 lines

+ *
+ *=A0=A0=A0 A write to a watchdog device is defined as a keepalive =

signal. =20

Quoted 2 lines

Any
+ *=A0=A0=A0 write of data will do, as we we don't define content =

meaning =20

Quoted 33 lines

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);
(quoted diff) +4 -0
+
 +=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;
 +}
 +

Review

Quoted 10 lines
(quoted diff) +1 -0
 +/**
 + *=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

Quoted 8 lines

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

Quoted 6 lines
 +=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

Quoted 15 lines

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;
Quoted 8 lines
 +=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

Quoted 1 line

+=A0=A0=A0=A0=A0=A0=A0=A0 *=A0 what it should do. Unknown cases are =

just ignored.

Quoted 2 lines
 +=A0=A0=A0=A0=A0=A0=A0=A0 */
 +=A0=A0=A0=A0=A0=A0=A0 if ( (status & =

(WDIOS_DISABLECARD|WDIOS_ENABLECARD))

Quoted 1 line

+=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 =3D=3D =

(WDIOS_DISABLECARD|WDIOS_ENABLECARD) )

Quoted 5 lines
 +=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");

Quoted 5 lines
 +=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");

Quoted 11 lines
 +=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

Quoted 29 lines

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;
(quoted diff) +4 -0
+
 +=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
 + *
 + */

Review

Quoted 10 lines
(quoted diff) +2 -0
 +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

Quoted 5 lines

will not stop!\n");

 +=A0=A0=A0=A0=A0 booke_wdt_ping();
+=A0=A0=A0 }
 +=A0 }
 +=A0 clear_bit(WDT_STATE_OPEN, &driver_state);
Quoted 9 lines

+
+=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

Quoted 2 lines

with CODE=3D0
+ *=A0=A0=A0=A0=A0=A0=A0=A0=A0 (see panic function in =

kernel/panic.c).

Quoted 3 lines

+ */
+static int
+booke_wdt_notify_sys(struct notifier_block *this, unsigned long =

code,

Quoted 27 lines

+=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();
(quoted diff) +9 -0
+
 +=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.

Review

Quoted 10 lines
(quoted diff) +2 -0
 + */
 +
 +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

Quoted 2 lines

unload
+ *=A0=A0=A0 it, well it keeps ticking.=A0 You just have to load a =

new

Quoted 2 lines

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

Quoted 18 lines

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

(quoted diff) +2 -0
+}
 +
 +/**
 + *=A0=A0=A0=A0 booke_wdt_init:
+ *
 + *=A0=A0=A0 Set up the WDT relevant timer facility.
 + */

Review

Quoted 10 lines
(quoted diff) +2 -0
 +
 +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

Quoted 9 lines

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

Quoted 8 lines

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

Quoted 4 lines

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

Quoted 11 lines

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

Quoted 6 lines

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",

Quoted 17 lines
 +=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;
Quoted 4 lines

+}
+
+device_initcall(booke_wdt_init);
--- linux-2.6.11/drivers/char/watchdog/booke_wdt.h=A0=A0=A0=A0=A0 =

1970-01-01 =20

Quoted 2 lines

09:00:00.000000000 +0900
+++ linux-2.6.11-booke-wdt/drivers/char/watchdog/booke_wdt.h=A0=A0=A0 =

=20

Quoted 8 lines
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<[email protected]>

Quoted 2 lines

+ *=A0=A0=A0 Description:
+ *=A0=A0=A0=A0=A0 Header file for PowerPC Book E(PPC 4xx/e500) =

watchdog driver.

Quoted 2 lines

+ *
+ *=A0=A0=A0 This program is free software; you can redistribute it =

and/or

Quoted 1 line

+ *=A0=A0=A0 modify it under the terms of the GNU General Public =

License

Quoted 1 line

+ *=A0=A0=A0 as published by the Free Software Foundation; either =

version 2

Quoted 3 lines

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

Quoted 5 lines

provide
+ *=A0=A0=A0 warranty for any of this software.
+ *
+ */
+#ifndef _DRIVERS_CHAR_WATCHDOG_BOOKE_WDT_H

drivers/char/watchdog/booke_wdt.h

Quoted 10 lines
drivers/char/watchdog/booke_wdt.h +6 -0
+#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 */

Quoted 1 line

+#define WDT_STATE_STOP_ON_CLOSE=A0=A0=A0=A0=A0=A0=A0=A0 1=A0=A0 /* =

Stop with close is =20

Quoted 5 lines

expected */
+/*
+ * Configurations
+ */
+#define WDT_TIMO=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 60000=A0=A0=A0 /* =

Default timeout =3D 60000 =20

Quoted 2 lines

ms(1min) */
+#define WDT_HEARTBEAT_MIN=A0 100=A0=A0=A0=A0=A0=A0=A0=A0=A0 /* =

Minimum timeout =3D 100 ms =20

Quoted 2 lines

*/
+#define WDT_HEARTBEAT_MAX=A0 600000=A0=A0=A0=A0=A0=A0 /* Maximum =

timeout =3D =20

Quoted 3 lines

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

Quoted 11 lines

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

Quoted 1 line

+#define WDT_TCR_WRC_BIT=A0=A0=A0 3=A0=A0 /*=A0 WRC bit in TCR =

(bit[2..3])=A0=A0 */

Quoted 1 line

+#define WDT_TCR_WIE_BIT=A0=A0=A0 4=A0=A0 /*=A0 WIE bit in TCR =

(bit[4])=A0=A0=A0=A0=A0 */

Quoted 17 lines

+/*
+ *=A0 TCR[WP] relevant definitions
+ */
+#define WDT_TCR_WP_SHIFT=A0=A0=A0=A0=A0=A0 (31 - WDT_TCR_WP_BIT)

(quoted diff) +6 -0
+#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

Review

Quoted 10 lines
(quoted diff) +1 -0
 +#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.

Quoted 9 lines

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

Quoted 8 lines

+#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

Quoted 32 lines

+
+/*
+ *=A0 IOCTL commands for comaptiblity for old driver
+ */
+#define WDIOC_GETPERIOD=A0=A0=A0=A0=A0=A0=A0=A0 WDIOC_GETTIMEOUT

(quoted diff) +3 -0
+#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=

#19 lore raw

Re: [PATCH] WDT Driver for Book-E [2/2] Device driver part.

Quoted 5 lines · Kumar Gala

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

#20 lore raw

Re: [PATCH] WDT Driver for Book-E [2/2] Device driver part.

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

Quoted 6 lines · Matt Porter
Quoted 5 lines · Kumar Gala

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

Quoted 8 lines
Quoted 1 line

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

#21 lore raw

Re: [PATCH] WDT Driver for Book-E [2/2] Device driver part.

In reply to Takeharu KATO

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

Hi Takeharu,

Some comments below. Looks good overall.

drivers/char/watchdog/Kconfig config 8xx_WDT · line 351

Quoted 10 lines
drivers/char/watchdog/Kconfig +3 -0
@@ -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.

drivers/char/watchdog/Kconfig config 8xx_WDT · line 357

Quoted 6 lines
drivers/char/watchdog/Kconfig +6 -0
+
+#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.

Quoted 12 lines
drivers/char/watchdog/Kconfig +12 -0
+ * 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);

drivers/char/watchdog/Kconfig config 8xx_WDT

Quoted 10 lines
drivers/char/watchdog/Kconfig +10 -0
+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.

Quoted 8 lines
drivers/char/watchdog/Kconfig +8 -0
+/**
+ *      __booke_wdt_enable
+ *      Enable Watchdog
+ */
+static __inline__ void
+__booke_wdt_enable(void)
+{
+  mtspr(SPRN_TCR,(mfspr(SPRN_TCR)|WDT_TCR_WDT_ENABLE));

drivers/char/watchdog/Kconfig

Quoted 10 lines
drivers/char/watchdog/Kconfig +10 -0
+}
+/**
+ *      __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.

drivers/char/watchdog/Kconfig

Quoted 11 lines
drivers/char/watchdog/Kconfig +11 -0
+/**
+ *    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.

drivers/char/watchdog/Kconfig

Quoted 9 lines
drivers/char/watchdog/Kconfig +9 -0
+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.

Quoted 47 lines
drivers/char/watchdog/Kconfig +47 -0
+/*
+ *  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  */

drivers/char/watchdog/Kconfig

Quoted 10 lines
drivers/char/watchdog/Kconfig +10 -0
+#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?

Quoted 10 lines
drivers/char/watchdog/Kconfig +10 -0
+/*
+ *  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...) \

drivers/char/watchdog/Kconfig

Quoted 10 lines
drivers/char/watchdog/Kconfig +10 -0
+    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

#22 lore raw

Re: [PATCH] WDT Driver for Book-E [2/2] Device driver part.

Dear Josh:

Thank you for your thorough review.

Quoted 4 lines · Josh Boyer

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.

Quoted 11 lines

drivers/char/watchdog/booke_wdt.c line 55

Quoted 6 lines
drivers/char/watchdog/booke_wdt.c +6 -0
+
+#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?

Quoted 7 lines

drivers/char/watchdog/booke_wdt.c line 106

Quoted 2 lines
drivers/char/watchdog/booke_wdt.c +2 -0
+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.

Quoted 21 lines
Quoted 9 lines
drivers/char/watchdog/booke_wdt.c +8 -0
+/**
+ *      __booke_wdt_enable
+ *      Enable Watchdog
+ */
+static __inline__ void
+__booke_wdt_enable(void)
+{
+  mtspr(SPRN_TCR,(mfspr(SPRN_TCR)|WDT_TCR_WDT_ENABLE));

drivers/char/watchdog/booke_wdt.c line 176

Quoted 10 lines
drivers/char/watchdog/booke_wdt.c +10 -0
+}
+/**
+ *      __booke_wdt_disable
+ *      Disable Watchdog
+ */
+static __inline__ void
+__booke_wdt_disable(void)
+{
+  mtspr(SPRN_TCR,(mfspr(SPRN_TCR)&(~(WDT_TCR_WDT_ENABLE))));
+}
Quoted 9 lines

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.

Quoted 4 lines

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

Yes, however, it is implemented on purpose.

Quoted 10 lines

drivers/char/watchdog/booke_wdt.h line 95

Quoted 5 lines
drivers/char/watchdog/booke_wdt.h +5 -0
+/*
+ *  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(^^

Quoted 4 lines

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,

Signature · 1 line
Takeharu KATO
#23 lore raw

Re: [PATCH] WDT Driver for Book-E [2/2] Device driver part.

Hi, Josh:

Quoted 8 lines · Takeharu KATO
Quoted 5 lines

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.

Quoted 7 lines
Quoted 4 lines

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,

Signature · 1 line
Takeharu KATO
drivers/char/watchdog/booke_wdt.c renamed from drivers/char/watchdog/booke_wdt.c 2005-03-04 16:38:58.000000000 +0900 +39 -75
@@ -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();
     }
   }
drivers/char/watchdog/booke_wdt.h renamed from drivers/char/watchdog/booke_wdt.h 2005-03-04 16:38:58.000000000 +0900 +13 -28

74 lines not on this page · raw message

#24 lore raw

Re: [PATCH] WDT Driver for Book-E [2/2] Device driver part.

Quoted 11 lines · Takeharu KATO

Hi, Josh:

Quoted 4 lines · Takeharu KATO
Quoted 1 line

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.

Quoted 8 lines
Quoted 8 lines
Quoted 5 lines

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.

Quoted 8 lines

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.

Quoted 5 lines

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

#25 lore raw
In reply to Matt Porter

Hi Matt

Quoted 4 lines

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,

Signature · 1 line
Takeharu KATO
arch/ppc/kernel/head_44x.S +6 -1
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
@@ -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)
arch/ppc/kernel/head_4xx.S +7 -3
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
@@ -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
arch/ppc/kernel/head_booke.h +2 -2
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
@@ -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);					\
arch/ppc/syslib/ppc4xx_setup.c +6 -4
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
@@ -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;
drivers/char/watchdog/Kconfig +19 -0
diff -uprN linux-2.6.11-rc4.orig/drivers/char/watchdog/Kconfig linux-2.6.11-rc4/drivers/char/watchdog/Kconfig
@@ -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
drivers/char/watchdog/Makefile +1 -0
diff -uprN linux-2.6.11-rc4.orig/drivers/char/watchdog/Makefile linux-2.6.11-rc4/drivers/char/watchdog/Makefile
@@ -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
drivers/char/watchdog/ppc4xx_wdt.c +717 -0

717 lines not on this page · raw message

drivers/char/watchdog/ppc4xx_wdt.h +131 -0

131 lines not on this page · raw message

#26 lore raw

PATCH 1/3 PowerPC4xx/E500 WatchDogTimerDriver(Core and PPC4xx part)

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,

arch/ppc/syslib/ppc4xx_setup.c +10 -21
@@ -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
 
 }
+
+
drivers/char/watchdog/Kconfig +7 -0
@@ -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
drivers/char/watchdog/Makefile +1 -0
@@ -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
drivers/char/watchdog/ppc4xx_wdt.c +635 -0

635 lines not on this page · raw message

drivers/char/watchdog/ppc4xx_wdt.h +125 -0

125 lines not on this page · raw message

#27 lore raw
In reply to Takeharu KATO

Dear Matt and all:

This is PowerPC e500 part.

arch/ppc/platforms/85xx/mpc8540_ads.c +9 -0
@@ -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 */
arch/ppc/platforms/85xx/mpc8560_ads.c +8 -0
@@ -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 */
arch/ppc/platforms/85xx/mpc85xx_cds_common.c +8 -0
@@ -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 */
arch/ppc/platforms/85xx/sbc8560.c +8 -0
@@ -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 */
arch/ppc/platforms/85xx/stx_gp3.c +9 -0
@@ -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 */
#28 lore raw

PATCH 3/3 PowerPC4xx/E500 WatchDogTimerDriver(exception handler part)

In reply to Takeharu KATO

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.

arch/ppc/kernel/head_4xx.S +1 -1
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
@@ -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
arch/ppc/kernel/head_booke.h +2 -2
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
@@ -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);					\
#29 lore raw

Re: [PATCH 3/3] PowerPC4xx/E500 WatchDogTimerDriver(exception handler part)

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

to andrew.

- kumar

Quoted 10 lines · Takeharu KATO

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.

Quoted 10 lines

2) Trivial bug fix in head_booke.h
=A0=A0=A0 Trivial bug fix of CRITICAL_EXCEPTION macro.

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

Quoted 7 lines

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

Quoted 7 lines

UnknownException)

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

=A0 =A0=A0=A0=A0=A0 CRITICAL_EXCEPTION(0x1020, WDTException, =

UnknownException)

Quoted 4 lines

-#endif

=A0 /* 0x1100 - Data TLB Miss Exception
=A0=A0 * As the name implies, translation is not in the MMU, so =

search the

Quoted 6 lines

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

Quoted 3 lines
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 \

Quoted 1 line

=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 \

Quoted 3 lines

=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, \

Quoted 1 line

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

Quoted 1 line

+=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, \

Quoted 1 line

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

Quoted 2 lines

=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 \

Quoted 1 line

=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 \

Quoted 7 lines

_______________________________________________
Linuxppc-embedded mailing list
[email protected]
https://ozlabs.org/mailman/listinfo/linuxppc-embedded

#30 lore raw

Re: [PATCH 3/3] PowerPC4xx/E500 WatchDogTimerDriver(exception handler part)

Hi

Quoted 4 lines · Kumar Gala

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.

Signature · 3 lines
Takeharu KATO
Fujitsu Limited
Email:kato.takeharu at jp.fujitsu.com
#31 lore raw

Re: [PATCH 3/3] PowerPC4xx/E500 WatchDogTimerDriver(exception handler part)

In reply to Takeharu KATO

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.

arch/ppc/kernel/head_44x.S +4 -1
@@ -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)
arch/ppc/kernel/head_4xx.S +7 -3
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
@@ -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
arch/ppc/kernel/head_e500.S +5 -1
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
@@ -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)
drivers/char/watchdog/ppc4xx_wdt.c +33 -5
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
@@ -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"));
+}
 
 /*
  *	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 */
Signature · 3 lines
Takeharu KATO
Fujitsu Limited
Email:kato.takeharu at jp.fujitsu.com