diff options
author | Marcelo Tosatti <marcelo.tosatti@cyclades.com> | 2005-11-24 08:32:09 -0500 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2006-01-08 22:50:51 -0500 |
commit | fb64c2446b20bf0206a690e9e1df88b25ac421e6 (patch) | |
tree | 53d6e17957d29d881f8cff83ed952b4229d811bd /arch/ppc | |
parent | 623703f620453c798b6fa3eb79ad8ea27bfd302a (diff) |
[PATCH] ppc32: m8xx watchdog update
This updates m8xx_wdt as follows:
1) Remove now obsolete fpos check in the write() function. The driver is
currently non functional due to this bug.
2) Use in/out macros for register access.
3) Allows m8xx_wdt to use a kernel timer instead of the builtin RTC/PIT
for keep-alive trigger (which is responsible for servicing the watchdog
until an userspace application takes over). For instance Cyclades PRxK
boards (MPC 855T based) have a non-functional internal RTC/PIT unit.
Behaviour for boards with RTC/PIT is unchaged.
4) The last change required moving the RTCSC register setting code
to a weak function which can be overriden by board specific files.
Otherwise the timer init code trashes the register making it impossible
for m8xx_wdt to detect the situation.
Signed-off-by: Marcelo Tosatti <marcelo.tosatti@cyclades.com>
Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/ppc')
-rw-r--r-- | arch/ppc/syslib/m8xx_setup.c | 15 | ||||
-rw-r--r-- | arch/ppc/syslib/m8xx_wdt.c | 92 | ||||
-rw-r--r-- | arch/ppc/syslib/m8xx_wdt.h | 4 |
3 files changed, 82 insertions, 29 deletions
diff --git a/arch/ppc/syslib/m8xx_setup.c b/arch/ppc/syslib/m8xx_setup.c index 1cc3abe6fa43..688616de3cde 100644 --- a/arch/ppc/syslib/m8xx_setup.c +++ b/arch/ppc/syslib/m8xx_setup.c | |||
@@ -135,6 +135,16 @@ static struct irqaction tbint_irqaction = { | |||
135 | .name = "tbint", | 135 | .name = "tbint", |
136 | }; | 136 | }; |
137 | 137 | ||
138 | /* per-board overridable init_internal_rtc() function. */ | ||
139 | void __init __attribute__ ((weak)) | ||
140 | init_internal_rtc(void) | ||
141 | { | ||
142 | /* Disable the RTC one second and alarm interrupts. */ | ||
143 | out_be16(&((immap_t *)IMAP_ADDR)->im_sit.sit_rtcsc, in_be16(&((immap_t *)IMAP_ADDR)->im_sit.sit_rtcsc) & ~(RTCSC_SIE | RTCSC_ALE)); | ||
144 | /* Enable the RTC */ | ||
145 | out_be16(&((immap_t *)IMAP_ADDR)->im_sit.sit_rtcsc, in_be16(&((immap_t *)IMAP_ADDR)->im_sit.sit_rtcsc) | (RTCSC_RTF | RTCSC_RTE)); | ||
146 | } | ||
147 | |||
138 | /* The decrementer counts at the system (internal) clock frequency divided by | 148 | /* The decrementer counts at the system (internal) clock frequency divided by |
139 | * sixteen, or external oscillator divided by four. We force the processor | 149 | * sixteen, or external oscillator divided by four. We force the processor |
140 | * to use system clock divided by sixteen. | 150 | * to use system clock divided by sixteen. |
@@ -183,10 +193,7 @@ void __init m8xx_calibrate_decr(void) | |||
183 | out_be32(&((immap_t *)IMAP_ADDR)->im_sitk.sitk_rtcsck, KAPWR_KEY); | 193 | out_be32(&((immap_t *)IMAP_ADDR)->im_sitk.sitk_rtcsck, KAPWR_KEY); |
184 | out_be32(&((immap_t *)IMAP_ADDR)->im_sitk.sitk_tbk, KAPWR_KEY); | 194 | out_be32(&((immap_t *)IMAP_ADDR)->im_sitk.sitk_tbk, KAPWR_KEY); |
185 | 195 | ||
186 | /* Disable the RTC one second and alarm interrupts. */ | 196 | init_internal_rtc(); |
187 | out_be16(&((immap_t *)IMAP_ADDR)->im_sit.sit_rtcsc, in_be16(&((immap_t *)IMAP_ADDR)->im_sit.sit_rtcsc) & ~(RTCSC_SIE | RTCSC_ALE)); | ||
188 | /* Enable the RTC */ | ||
189 | out_be16(&((immap_t *)IMAP_ADDR)->im_sit.sit_rtcsc, in_be16(&((immap_t *)IMAP_ADDR)->im_sit.sit_rtcsc) | (RTCSC_RTF | RTCSC_RTE)); | ||
190 | 197 | ||
191 | /* Enabling the decrementer also enables the timebase interrupts | 198 | /* Enabling the decrementer also enables the timebase interrupts |
192 | * (or from the other point of view, to get decrementer interrupts | 199 | * (or from the other point of view, to get decrementer interrupts |
diff --git a/arch/ppc/syslib/m8xx_wdt.c b/arch/ppc/syslib/m8xx_wdt.c index a21632d37e5a..df6c9557b86a 100644 --- a/arch/ppc/syslib/m8xx_wdt.c +++ b/arch/ppc/syslib/m8xx_wdt.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <syslib/m8xx_wdt.h> | 19 | #include <syslib/m8xx_wdt.h> |
20 | 20 | ||
21 | static int wdt_timeout; | 21 | static int wdt_timeout; |
22 | int m8xx_has_internal_rtc = 0; | ||
22 | 23 | ||
23 | static irqreturn_t m8xx_wdt_interrupt(int, void *, struct pt_regs *); | 24 | static irqreturn_t m8xx_wdt_interrupt(int, void *, struct pt_regs *); |
24 | static struct irqaction m8xx_wdt_irqaction = { | 25 | static struct irqaction m8xx_wdt_irqaction = { |
@@ -45,35 +46,15 @@ static irqreturn_t m8xx_wdt_interrupt(int irq, void *dev, struct pt_regs *regs) | |||
45 | return IRQ_HANDLED; | 46 | return IRQ_HANDLED; |
46 | } | 47 | } |
47 | 48 | ||
48 | void __init m8xx_wdt_handler_install(bd_t * binfo) | 49 | #define SYPCR_SWP 0x1 |
50 | #define SYPCR_SWE 0x4 | ||
51 | |||
52 | |||
53 | void __init m8xx_wdt_install_irq(volatile immap_t *imap, bd_t *binfo) | ||
49 | { | 54 | { |
50 | volatile immap_t *imap = (volatile immap_t *)IMAP_ADDR; | ||
51 | u32 pitc; | 55 | u32 pitc; |
52 | u32 sypcr; | ||
53 | u32 pitrtclk; | 56 | u32 pitrtclk; |
54 | 57 | ||
55 | sypcr = in_be32(&imap->im_siu_conf.sc_sypcr); | ||
56 | |||
57 | if (!(sypcr & 0x04)) { | ||
58 | printk(KERN_NOTICE "m8xx_wdt: wdt disabled (SYPCR: 0x%08X)\n", | ||
59 | sypcr); | ||
60 | return; | ||
61 | } | ||
62 | |||
63 | m8xx_wdt_reset(); | ||
64 | |||
65 | printk(KERN_NOTICE | ||
66 | "m8xx_wdt: active wdt found (SWTC: 0x%04X, SWP: 0x%01X)\n", | ||
67 | (sypcr >> 16), sypcr & 0x01); | ||
68 | |||
69 | wdt_timeout = (sypcr >> 16) & 0xFFFF; | ||
70 | |||
71 | if (!wdt_timeout) | ||
72 | wdt_timeout = 0xFFFF; | ||
73 | |||
74 | if (sypcr & 0x01) | ||
75 | wdt_timeout *= 2048; | ||
76 | |||
77 | /* | 58 | /* |
78 | * Fire trigger if half of the wdt ticked down | 59 | * Fire trigger if half of the wdt ticked down |
79 | */ | 60 | */ |
@@ -98,6 +79,67 @@ void __init m8xx_wdt_handler_install(bd_t * binfo) | |||
98 | printk(KERN_NOTICE | 79 | printk(KERN_NOTICE |
99 | "m8xx_wdt: keep-alive trigger installed (PITC: 0x%04X)\n", pitc); | 80 | "m8xx_wdt: keep-alive trigger installed (PITC: 0x%04X)\n", pitc); |
100 | 81 | ||
82 | } | ||
83 | |||
84 | static void m8xx_wdt_timer_func(unsigned long data); | ||
85 | |||
86 | static struct timer_list m8xx_wdt_timer = | ||
87 | TIMER_INITIALIZER(m8xx_wdt_timer_func, 0, 0); | ||
88 | |||
89 | void m8xx_wdt_stop_timer(void) | ||
90 | { | ||
91 | del_timer(&m8xx_wdt_timer); | ||
92 | } | ||
93 | |||
94 | void m8xx_wdt_install_timer(void) | ||
95 | { | ||
96 | m8xx_wdt_timer.expires = jiffies + (HZ/2); | ||
97 | add_timer(&m8xx_wdt_timer); | ||
98 | } | ||
99 | |||
100 | static void m8xx_wdt_timer_func(unsigned long data) | ||
101 | { | ||
102 | m8xx_wdt_reset(); | ||
103 | m8xx_wdt_install_timer(); | ||
104 | } | ||
105 | |||
106 | void __init m8xx_wdt_handler_install(bd_t * binfo) | ||
107 | { | ||
108 | volatile immap_t *imap = (volatile immap_t *)IMAP_ADDR; | ||
109 | u32 sypcr; | ||
110 | |||
111 | sypcr = in_be32(&imap->im_siu_conf.sc_sypcr); | ||
112 | |||
113 | if (!(sypcr & SYPCR_SWE)) { | ||
114 | printk(KERN_NOTICE "m8xx_wdt: wdt disabled (SYPCR: 0x%08X)\n", | ||
115 | sypcr); | ||
116 | return; | ||
117 | } | ||
118 | |||
119 | m8xx_wdt_reset(); | ||
120 | |||
121 | printk(KERN_NOTICE | ||
122 | "m8xx_wdt: active wdt found (SWTC: 0x%04X, SWP: 0x%01X)\n", | ||
123 | (sypcr >> 16), sypcr & SYPCR_SWP); | ||
124 | |||
125 | wdt_timeout = (sypcr >> 16) & 0xFFFF; | ||
126 | |||
127 | if (!wdt_timeout) | ||
128 | wdt_timeout = 0xFFFF; | ||
129 | |||
130 | if (sypcr & SYPCR_SWP) | ||
131 | wdt_timeout *= 2048; | ||
132 | |||
133 | m8xx_has_internal_rtc = in_be16(&imap->im_sit.sit_rtcsc) & RTCSC_RTE; | ||
134 | |||
135 | /* if the internal RTC is off use a kernel timer */ | ||
136 | if (!m8xx_has_internal_rtc) { | ||
137 | if (wdt_timeout < (binfo->bi_intfreq/HZ)) | ||
138 | printk(KERN_ERR "m8xx_wdt: timeout too short for ktimer!\n"); | ||
139 | m8xx_wdt_install_timer(); | ||
140 | } else | ||
141 | m8xx_wdt_install_irq(imap, binfo); | ||
142 | |||
101 | wdt_timeout /= binfo->bi_intfreq; | 143 | wdt_timeout /= binfo->bi_intfreq; |
102 | } | 144 | } |
103 | 145 | ||
diff --git a/arch/ppc/syslib/m8xx_wdt.h b/arch/ppc/syslib/m8xx_wdt.h index 0d81a9f8155f..e75835f0012b 100644 --- a/arch/ppc/syslib/m8xx_wdt.h +++ b/arch/ppc/syslib/m8xx_wdt.h | |||
@@ -9,8 +9,12 @@ | |||
9 | #ifndef _PPC_SYSLIB_M8XX_WDT_H | 9 | #ifndef _PPC_SYSLIB_M8XX_WDT_H |
10 | #define _PPC_SYSLIB_M8XX_WDT_H | 10 | #define _PPC_SYSLIB_M8XX_WDT_H |
11 | 11 | ||
12 | extern int m8xx_has_internal_rtc; | ||
13 | |||
12 | extern void m8xx_wdt_handler_install(bd_t * binfo); | 14 | extern void m8xx_wdt_handler_install(bd_t * binfo); |
13 | extern int m8xx_wdt_get_timeout(void); | 15 | extern int m8xx_wdt_get_timeout(void); |
14 | extern void m8xx_wdt_reset(void); | 16 | extern void m8xx_wdt_reset(void); |
17 | extern void m8xx_wdt_install_timer(void); | ||
18 | extern void m8xx_wdt_stop_timer(void); | ||
15 | 19 | ||
16 | #endif /* _PPC_SYSLIB_M8XX_WDT_H */ | 20 | #endif /* _PPC_SYSLIB_M8XX_WDT_H */ |