1 diff -Narup linux-2.4.31-orig/drivers/char/Config.in linux-2.4.31/drivers/char/Config.in
2 --- linux-2.4.31-orig/drivers/char/Config.in 2004-08-07 16:26:04.000000000 -0700
3 +++ linux-2.4.31/drivers/char/Config.in 2005-08-10 15:01:02.000000000 -0700
4 @@ -270,6 +270,7 @@ if [ "$CONFIG_WATCHDOG" != "n" ]; then
7 tristate ' ZF MachZ Watchdog' CONFIG_MACHZ_WDT
8 + dep_tristate ' PPC405 Watchdog Timer' CONFIG_PPC405_WDT $CONFIG_4xx
9 if [ "$CONFIG_SGI_IP22" = "y" ]; then
10 dep_tristate ' Indy/I2 Hardware Watchdog' CONFIG_INDYDOG $CONFIG_SGI_IP22
12 diff -Narup linux-2.4.31-orig/drivers/char/Makefile linux-2.4.31/drivers/char/Makefile
13 --- linux-2.4.31-orig/drivers/char/Makefile 2004-08-07 16:26:04.000000000 -0700
14 +++ linux-2.4.31/drivers/char/Makefile 2005-08-10 15:00:48.000000000 -0700
15 @@ -323,6 +323,7 @@ obj-$(CONFIG_WAFER_WDT) += wafer5823wdt.
16 obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o
17 obj-$(CONFIG_INDYDOG) += indydog.o
18 obj-$(CONFIG_8xx_WDT) += mpc8xx_wdt.o
19 +obj-$(CONFIG_PPC405_WDT) += ppc405_wdt.o
21 subdir-$(CONFIG_MWAVE) += mwave
22 ifeq ($(CONFIG_MWAVE),y)
23 diff -Narup linux-2.4.31-orig/drivers/char/ppc405_wdt.c linux-2.4.31/drivers/char/ppc405_wdt.c
24 --- linux-2.4.31-orig/drivers/char/ppc405_wdt.c 1969-12-31 16:00:00.000000000 -0800
25 +++ linux-2.4.31/drivers/char/ppc405_wdt.c 2005-08-10 14:56:02.000000000 -0700
28 + * IBM PowerPC 405 Watchdog: A Simple Hardware Watchdog Device
29 + * Based on PowerPC 8xx driver by Scott Anderson which was
30 + * based on MixCom driver by Gergely Madarasz which was
31 + * based on Softdog driver by Alan Cox and PC Watchdog driver by Ken Hollis
33 + * FILE NAME ppc405_wdt.c
35 + * Armin Kuster akuster@mvista.com or source@mvista.com
39 + * Author: MontaVista Software, Inc. <source@mvista.com>
40 + * Debbie Chu <debbie_chu@mvista.com>
41 + * Frank Rowand <frank_rowand@mvista.com>
43 + * Copyright 2000 MontaVista Software Inc.
45 + * This program is free software; you can redistribute it and/or modify it
46 + * under the terms of the GNU General Public License as published by the
47 + * Free Software Foundation; either version 2 of the License, or (at your
48 + * option) any later version.
50 + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
51 + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
52 + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
53 + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
54 + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
55 + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
56 + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
57 + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
58 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
59 + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
61 + * You should have received a copy of the GNU General Public License along
62 + * with this program; if not, write to the Free Software Foundation, Inc.,
63 + * 675 Mass Ave, Cambridge, MA 02139, USA.
65 + * Version 0.1 (00/06/05):
66 + * Version 0.2 (00/07/12) by Debbie Chu
67 + * Version 0.4 (01/09/19) by Armin kuster
68 + * Version 0.5 (01/10/10) Akuster
69 + * - removed ppc4xx_restart w/ machine_restart
72 +#define VERSION "0.5"
74 +#define WDT_DEFAULT_PERIOD 120 /* system default 2 minutes */
75 +#define MAXONEHOUR 3600UL /* Max timeout period 60 minutes */
76 +#define TENMSBASE 10000UL /* 10 ms */
77 +#define MICROSECBASE 1000000
79 +#include <linux/module.h>
80 +#include <linux/config.h>
81 +#include <linux/types.h>
82 +#include <linux/kernel.h>
83 +#include <linux/miscdevice.h>
84 +#include <linux/watchdog.h>
85 +#include <linux/reboot.h>
86 +#include <linux/init.h>
87 +#include <asm/uaccess.h>
89 +#include <asm/machdep.h>
91 +#define WDIOC_GETPERIOD _IOR(WATCHDOG_IOCTL_BASE, 6, int)
92 +#define WDIOC_SETPERIOD _IOW(WATCHDOG_IOCTL_BASE, 7, int)
95 +unsigned long wdt_period;
96 +unsigned long wdt_heartbeat_count;
97 +static unsigned long wdt_count;
100 +static int ppc405wd_opened;
103 +ppc405wd_update_timer(void)
105 + wdt_heartbeat_count = wdt_count;
109 +ppc4xx_wdt_heartbeat(void)
112 + /* default used until wdt inits */
113 + wdt_heartbeat_count = wdt_period * HZ;
116 + if ((wdt_heartbeat_count > 0) || ( !wdt_enable )) {
117 + if (wdt_heartbeat_count > 0)
118 + wdt_heartbeat_count--;
119 + mtspr(SPRN_TSR, (TSR_ENW | TSR_WIS));
121 + machine_restart("Watchdog Timer Timed out, system reset!");
122 + ppc_md.heartbeat_count = 0;
126 + * Allow only one person to hold it open
128 +static int ppc405wd_open(struct inode *inode, struct file *file)
130 + unsigned int tcr_value;
132 + if(test_and_set_bit(0,&ppc405wd_opened))
138 + * There are three ways to enable the watchdog timer:
139 + * 1. turn on the watchdog in the bootrom.
140 + * 2. turn on the watchdog using the boot command line option,
141 + * you can specifiy "wdt=<timeout>" on the boot cmdline
142 + * 3. turn on the watchdog in this routine,
143 + * the default timer period is set to 2 minutes.
146 + tcr_value = mfspr(SPRN_TCR);
148 + if ((tcr_value & TCR_WRC_MASK) != TCR_WRC(WRC_SYSTEM)) {
150 + * watchdog reset not enabled yet, enable it
151 + * The default timer period is set to 2 minutes.
155 + (mfspr(SPRN_TCR) & ~TCR_WP_MASK & ~TCR_WRC_MASK) |
157 + TCR_WRC(WRC_SYSTEM));
160 + (mfspr(SPRN_TCR) & ~TCR_WP_MASK & ~TCR_WRC_MASK) |
162 + TCR_WRC(WRC_SYSTEM));
166 + if (wdt_period == 0)
167 + wdt_period = WDT_DEFAULT_PERIOD;
169 + wdt_count = wdt_period * HZ;
170 + ppc405wd_update_timer();
172 + mtspr(SPRN_TSR, (TSR_ENW | TSR_WIS));
176 +static int ppc405wd_release(struct inode *inode, struct file *file)
180 + clear_bit(0,&ppc405wd_opened);
184 +static ssize_t ppc405wd_write(struct file *file, const char *data, size_t len, loff_t *ppos)
186 + /* Can't seek (pwrite) on this device */
187 + if (ppos != &file->f_pos)
191 + ppc405wd_update_timer();
197 +static int ppc405wd_ioctl(struct inode *inode, struct file *file,
198 + unsigned int cmd, unsigned long arg)
200 + unsigned long period;
203 + static struct watchdog_info ident = {
204 + WDIOF_KEEPALIVEPING,
210 + case WDIOC_GETSTATUS:
211 + status = ppc405wd_opened;
213 + if (copy_to_user((int *)arg, &status, sizeof(int)))
216 + case WDIOC_GETSUPPORT:
217 + if (copy_to_user((struct watchdog_info *)arg, &ident,
222 + case WDIOC_KEEPALIVE:
223 + ppc405wd_update_timer();
225 + case WDIOC_SETOPTIONS:
226 + if(copy_from_user(&state, (int*) arg, sizeof(int)))
228 + if (state & WDIOS_DISABLECARD) {
230 + printk(KERN_NOTICE "Soft watchdog timer is disabled\n");
233 + if (state & WDIOS_ENABLECARD) {
234 + ppc405wd_update_timer();
236 + mtspr(SPRN_TSR, (TSR_ENW | TSR_WIS));
237 + printk(KERN_NOTICE "Soft watchdog timer is enabled\n");
240 + case WDIOC_GETPERIOD:
241 + /* return watchdog period (units = microseconds) */
242 + period = (wdt_period / HZ) * MICROSECBASE;
243 + if (copy_to_user((unsigned long *)arg, &period,
248 + case WDIOC_SETPERIOD:
250 + ** set watchdog period (units = microseconds)
251 + ** value of zero means maximum
253 + ** Don't set a watchdog period to a value less than
254 + ** the requested value (period will be rounded up to
255 + ** next available interval the watchdog supports).
257 + ** The software watchdog will expire at some point in
258 + ** the range of (rounded up period) ..
259 + ** (rounded up period + 1 jiffie). If interrupts are
260 + ** disabled so that the software watchdog is unable to
261 + ** reset the system, then the hardware watchdog will
262 + ** eventually reset the system.
264 + if (copy_from_user(&period, (unsigned long *)arg,
270 + ** This code assumes HZ is 100. Need to remove that
275 + ** The minimum period of ppc405wd_timer is a jiffie,
276 + ** which is 10 msec when HZ is 100. The units of
277 + ** wdt_period is jiffies.
279 + ** The new timer period will be used at the next
283 + period = MAXONEHOUR * MICROSECBASE;
285 + wdt_count = (period / TENMSBASE) + (period % TENMSBASE ? 1 : 0);
286 + ppc405wd_update_timer();
290 + return -ENOIOCTLCMD;
296 +static struct file_operations ppc405wd_fops =
298 + owner: THIS_MODULE,
299 + write: ppc405wd_write,
300 + ioctl: ppc405wd_ioctl,
301 + open: ppc405wd_open,
302 + release: ppc405wd_release,
305 +static struct miscdevice ppc405wd_miscdev =
312 +static int __init ppc405wd_init(void)
314 + misc_register(&ppc405wd_miscdev);
315 + printk(KERN_NOTICE "PPC 405 watchdog driver v%s\n", VERSION);
316 + if (wdt_period == 0)
317 + wdt_period = WDT_DEFAULT_PERIOD;
318 + wdt_count = wdt_period * HZ;
319 + ppc405wd_update_timer();
320 + mtspr(SPRN_TSR, (TSR_ENW | TSR_WIS));
321 + mtspr(SPRN_TCR, TCR_PIE | TCR_ARE);
325 +void __exit ppc405wd_exit(void)
327 + misc_deregister(&ppc405wd_miscdev);
330 +module_init(ppc405wd_init);
331 +module_exit(ppc405wd_exit);
332 diff -Narup linux-2.4.31-orig/include/asm-ppc/machdep.h linux-2.4.31/include/asm-ppc/machdep.h
333 --- linux-2.4.31-orig/include/asm-ppc/machdep.h 2003-08-25 04:44:44.000000000 -0700
334 +++ linux-2.4.31/include/asm-ppc/machdep.h 2005-08-10 15:13:37.000000000 -0700
335 @@ -41,6 +41,8 @@ struct machdep_calls {
336 unsigned long (*get_rtc_time)(void);
337 void (*calibrate_decr)(void);
338 void (*heartbeat)(void);
339 + unsigned long heartbeat_reset;
340 + unsigned long heartbeat_count;
342 unsigned long (*find_end_of_memory)(void);
343 void (*setup_io_mappings)(void);
344 diff -Narup linux-2.4.31-orig/include/asm-ppc/processor.h linux-2.4.31/include/asm-ppc/processor.h
345 --- linux-2.4.31-orig/include/asm-ppc/processor.h 2005-04-03 18:42:20.000000000 -0700
346 +++ linux-2.4.31/include/asm-ppc/processor.h 2005-08-10 15:10:17.000000000 -0700
347 @@ -455,11 +455,13 @@
348 #define WP_2_21 1 /* 2^21 clocks */
349 #define WP_2_25 2 /* 2^25 clocks */
350 #define WP_2_29 3 /* 2^29 clocks */
351 +#define TCR_WP_MASK TCR_WP(3)
352 #define TCR_WRC(x) (((x)&0x3)<<28) /* WDT Reset Control */
353 #define WRC_NONE 0 /* No reset will occur */
354 #define WRC_CORE 1 /* Core reset will occur */
355 #define WRC_CHIP 2 /* Chip reset will occur */
356 #define WRC_SYSTEM 3 /* System reset will occur */
357 +#define TCR_WRC_MASK TCR_WRC(3)
358 #define TCR_WIE 0x08000000 /* WDT Interrupt Enable */
359 #define TCR_PIE 0x04000000 /* PIT Interrupt Enable */
360 #define TCR_DIE TCR_PIE /* DEC Interrupt Enable */