diff options
-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 | ||||
-rw-r--r-- | drivers/char/watchdog/mpc8xx_wdt.c | 13 |
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. */ | ||
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 */ |
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) | |||
68 | static ssize_t mpc8xx_wdt_write(struct file *file, const char *data, size_t len, | 74 | static 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 | ||