PowerPC4xx Watchdog
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
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
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
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
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
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
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
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
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
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
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=20generated.
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
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
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
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.hin 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
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, unsignedstrcpy (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, unsignedstrcpy (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, unsignedstrcpy (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, unsignedstrcpy (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, unsignedstrcpy (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 } + +
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,
Signed-off-by Takeharu KATO <[email protected]>--- 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 */ +#ifdefined(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=A0START_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=A0START_EXCEPTION(0x1000, Decrementer)-=A0=A0=A0=A0=A0=A0NORMAL_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=A0EXC_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 /*=A0CONFIG_BOOKE_WDT=A0*/
+
=A0 /* extern voidgiveup_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 */ +#ifdefined(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=A0START_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.c2005-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=
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
PATCH 1/1 WDT Driver for Book-E [2/2] Device driver part.
In reply to Matt PorterMatt 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
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,
Signed-off-by Takeharu KATO <[email protected]>--- 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 fromdrivers/char/watchdog/wdt.cby 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 */ +
+#ifdefCONFIG_WATCHDOG_NOWAYOUT
+static int nowayout =3D 1;
Quoted 8 lines
+#else
+static int nowayout =3D 0;
+#endif
+
+/*
+ * Global variables
+ */
+static intwdt_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 intwdt_heartbeat_count=3D 0;=A0 /* WDT intrrupt =20=counter(compatible mode)*/
+static unsigned longdriver_state; /* Driver status (see: =20booke_wdt.h) */
+/*
+ *=A0 Identifier for this watchdog
+ */
+static structwatchdog_infoident =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, structpt_regs*regs, int code, =20=unsigned long addr);
+/*=A0 Panic notifier=A0 */
+extern structnotifier_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_tcount,loff_t*ppos);
+static int booke_wdt_ioctl(struct inode *inode, struct file *file, =20=unsigned int cmd,unsigned long arg);
+static intbooke_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__initbooke_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.
+ */
+#ifdefined(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)) << =20WDT_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=A0booke_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=A0booke_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.
+ */
+
+staticssize_t
+booke_wdt_write(struct file *file, const char *buf,size_tcount, =20=
loff_t*ppos)
+{
+=A0size_ti;
++=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=A0booke_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=A0notify_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(structnotifier_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=A0WDIOC_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=
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
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
Re: [PATCH] WDT Driver for Book-E [2/2] Device driver part.
In reply to Takeharu KATOOn 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
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_WP3Most 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.hthere aredev_printkanddev_dbgmacros 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
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.hthere aredev_printkanddev_dbgmacros 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
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.hthere aredev_printkanddev_dbgmacros 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.hwill 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
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 andret_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
@@ -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
@@ -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
@@ -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
@@ -48,9 +48,11 @@extern void abort (void );extern void ppc4xx_find_bridges (void ); +#ifdef CONFIG_PPC4xx_WATCHDOGextern 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
@@ -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
@@ -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
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
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
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
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, unsignedstrcpy (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, unsignedstrcpy (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, unsignedstrcpy (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, unsignedstrcpy (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, unsignedstrcpy (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 */
PATCH 3/3 PowerPC4xx/E500 WatchDogTimerDriver(exception handler part)
In reply to Takeharu KATODear 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
@@ -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
@@ -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); \
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 ofCRITICAL_EXCEPTIONmacro.Signed-off-by Takeharu KATO <[email protected]>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.hlinux-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
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.hup 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
Re: [PATCH 3/3] PowerPC4xx/E500 WatchDogTimerDriver(exception handler part)
In reply to Takeharu KATODear 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
@@ -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
@@ -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
@@ -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