aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarcelo Tosatti <marcelo.tosatti@cyclades.com>2005-11-24 08:32:09 -0500
committerPaul Mackerras <paulus@samba.org>2006-01-08 22:50:51 -0500
commitfb64c2446b20bf0206a690e9e1df88b25ac421e6 (patch)
tree53d6e17957d29d881f8cff83ed952b4229d811bd
parent623703f620453c798b6fa3eb79ad8ea27bfd302a (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>
-rw-r--r--arch/ppc/syslib/m8xx_setup.c15
-rw-r--r--arch/ppc/syslib/m8xx_wdt.c92
-rw-r--r--arch/ppc/syslib/m8xx_wdt.h4
-rw-r--r--drivers/char/watchdog/mpc8xx_wdt.c13
4 files changed, 90 insertions, 34 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. */
139void __init __attribute__ ((weak))
140init_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
21static int wdt_timeout; 21static int wdt_timeout;
22int m8xx_has_internal_rtc = 0;
22 23
23static irqreturn_t m8xx_wdt_interrupt(int, void *, struct pt_regs *); 24static irqreturn_t m8xx_wdt_interrupt(int, void *, struct pt_regs *);
24static struct irqaction m8xx_wdt_irqaction = { 25static 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
48void __init m8xx_wdt_handler_install(bd_t * binfo) 49#define SYPCR_SWP 0x1
50#define SYPCR_SWE 0x4
51
52
53void __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
84static void m8xx_wdt_timer_func(unsigned long data);
85
86static struct timer_list m8xx_wdt_timer =
87 TIMER_INITIALIZER(m8xx_wdt_timer_func, 0, 0);
88
89void m8xx_wdt_stop_timer(void)
90{
91 del_timer(&m8xx_wdt_timer);
92}
93
94void m8xx_wdt_install_timer(void)
95{
96 m8xx_wdt_timer.expires = jiffies + (HZ/2);
97 add_timer(&m8xx_wdt_timer);
98}
99
100static void m8xx_wdt_timer_func(unsigned long data)
101{
102 m8xx_wdt_reset();
103 m8xx_wdt_install_timer();
104}
105
106void __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
12extern int m8xx_has_internal_rtc;
13
12extern void m8xx_wdt_handler_install(bd_t * binfo); 14extern void m8xx_wdt_handler_install(bd_t * binfo);
13extern int m8xx_wdt_get_timeout(void); 15extern int m8xx_wdt_get_timeout(void);
14extern void m8xx_wdt_reset(void); 16extern void m8xx_wdt_reset(void);
17extern void m8xx_wdt_install_timer(void);
18extern void m8xx_wdt_stop_timer(void);
15 19
16#endif /* _PPC_SYSLIB_M8XX_WDT_H */ 20#endif /* _PPC_SYSLIB_M8XX_WDT_H */
diff --git a/drivers/char/watchdog/mpc8xx_wdt.c b/drivers/char/watchdog/mpc8xx_wdt.c
index 56d62ba7c6ce..ac6fbace4724 100644
--- a/drivers/char/watchdog/mpc8xx_wdt.c
+++ b/drivers/char/watchdog/mpc8xx_wdt.c
@@ -27,7 +27,10 @@ static void mpc8xx_wdt_handler_disable(void)
27{ 27{
28 volatile immap_t *imap = (volatile immap_t *)IMAP_ADDR; 28 volatile immap_t *imap = (volatile immap_t *)IMAP_ADDR;
29 29
30 imap->im_sit.sit_piscr &= ~(PISCR_PIE | PISCR_PTE); 30 if (!m8xx_has_internal_rtc)
31 m8xx_wdt_stop_timer();
32 else
33 out_be32(imap->im_sit.sit_piscr, in_be32(&imap->im_sit.sit_piscr) & ~(PISCR_PIE | PISCR_PTE));
31 34
32 printk(KERN_NOTICE "mpc8xx_wdt: keep-alive handler deactivated\n"); 35 printk(KERN_NOTICE "mpc8xx_wdt: keep-alive handler deactivated\n");
33} 36}
@@ -36,7 +39,10 @@ static void mpc8xx_wdt_handler_enable(void)
36{ 39{
37 volatile immap_t *imap = (volatile immap_t *)IMAP_ADDR; 40 volatile immap_t *imap = (volatile immap_t *)IMAP_ADDR;
38 41
39 imap->im_sit.sit_piscr |= PISCR_PIE | PISCR_PTE; 42 if (!m8xx_has_internal_rtc)
43 m8xx_wdt_install_timer();
44 else
45 out_be32(&imap->im_sit.sit_piscr, in_be32(&imap->im_sit.sit_piscr) | PISCR_PIE | PISCR_PTE);
40 46
41 printk(KERN_NOTICE "mpc8xx_wdt: keep-alive handler activated\n"); 47 printk(KERN_NOTICE "mpc8xx_wdt: keep-alive handler activated\n");
42} 48}
@@ -68,9 +74,6 @@ static int mpc8xx_wdt_release(struct inode *inode, struct file *file)
68static ssize_t mpc8xx_wdt_write(struct file *file, const char *data, size_t len, 74static ssize_t mpc8xx_wdt_write(struct file *file, const char *data, size_t len,
69 loff_t * ppos) 75 loff_t * ppos)
70{ 76{
71 if (ppos != &file->f_pos)
72 return -ESPIPE;
73
74 if (len) 77 if (len)
75 m8xx_wdt_reset(); 78 m8xx_wdt_reset();
76 79