aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/watchdog/booke_wdt.c
diff options
context:
space:
mode:
authorKumar Gala <galak@freescale.com>2005-09-03 18:55:33 -0400
committerLinus Torvalds <torvalds@evo.osdl.org>2005-09-05 03:05:56 -0400
commita2f40ccd294d14e5aca464c1913e8e0d8de35fca (patch)
treed900ebdbf37656d77acf7934db40021b21d49fde /drivers/char/watchdog/booke_wdt.c
parent886b9fa49900b055e20cd98f379fda49835d1ee6 (diff)
[PATCH] ppc32: Added support for the Book-E style Watchdog Timer
PowerPC 40x and Book-E processors support a watchdog timer at the processor core level. The timer has implementation dependent timeout frequencies that can be configured by software. One the first Watchdog timeout we get a critical exception. It is left to board specific code to determine what should happen at this point. If nothing is done and another timeout period expires the processor may attempt to reset the machine. Command line parameters: wdt=0 : disable watchdog (default) wdt=1 : enable watchdog wdt_period=N : N sets the value of the Watchdog Timer Period. The Watchdog Timer Period meaning is implementation specific. Check User Manual for the processor for more details. This patch is based off of work done by Takeharu Kato. Signed-off-by: Matt McClintock <msm@freescale.com> Signed-off-by: Kumar Gala <kumar.gala@freescale.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/char/watchdog/booke_wdt.c')
-rw-r--r--drivers/char/watchdog/booke_wdt.c191
1 files changed, 191 insertions, 0 deletions
diff --git a/drivers/char/watchdog/booke_wdt.c b/drivers/char/watchdog/booke_wdt.c
new file mode 100644
index 000000000000..7281f394f682
--- /dev/null
+++ b/drivers/char/watchdog/booke_wdt.c
@@ -0,0 +1,191 @@
1/*
2 * drivers/char/watchdog/booke_wdt.c
3 *
4 * Watchdog timer for PowerPC Book-E systems
5 *
6 * Author: Matthew McClintock
7 * Maintainer: Kumar Gala <kumar.gala@freescale.com>
8 *
9 * Copyright 2005 Freescale Semiconductor Inc.
10 *
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by the
13 * Free Software Foundation; either version 2 of the License, or (at your
14 * option) any later version.
15 */
16
17#include <linux/config.h>
18#include <linux/module.h>
19#include <linux/fs.h>
20#include <linux/miscdevice.h>
21#include <linux/notifier.h>
22#include <linux/watchdog.h>
23
24#include <asm/reg_booke.h>
25#include <asm/uaccess.h>
26
27/* If the kernel parameter wdt_enable=1, the watchdog will be enabled at boot.
28 * Also, the wdt_period sets the watchdog timer period timeout.
29 * For E500 cpus the wdt_period sets which bit changing from 0->1 will
30 * trigger a watchog timeout. This watchdog timeout will occur 3 times, the
31 * first time nothing will happen, the second time a watchdog exception will
32 * occur, and the final time the board will reset.
33 */
34
35#ifdef CONFIG_FSL_BOOKE
36#define WDT_PERIOD_DEFAULT 63 /* Ex. wdt_period=28 bus=333Mhz , reset=~40sec */
37#else
38#define WDT_PERIOD_DEFAULT 4 /* Refer to the PPC40x and PPC4xx manuals */
39#endif /* for timing information */
40
41u32 wdt_enable = 0;
42u32 wdt_period = WDT_PERIOD_DEFAULT;
43
44#ifdef CONFIG_FSL_BOOKE
45#define WDTP(x) ((((63-x)&0x3)<<30)|(((63-x)&0x3c)<<15))
46#else
47#define WDTP(x) (TCR_WP(x))
48#endif
49
50/*
51 * booke_wdt_enable:
52 */
53static __inline__ void booke_wdt_enable(void)
54{
55 u32 val;
56
57 val = mfspr(SPRN_TCR);
58 val |= (TCR_WIE|TCR_WRC(WRC_CHIP)|WDTP(wdt_period));
59
60 mtspr(SPRN_TCR, val);
61}
62
63/*
64 * booke_wdt_ping:
65 */
66static __inline__ void booke_wdt_ping(void)
67{
68 mtspr(SPRN_TSR, TSR_ENW|TSR_WIS);
69}
70
71/*
72 * booke_wdt_write:
73 */
74static ssize_t booke_wdt_write (struct file *file, const char *buf,
75 size_t count, loff_t *ppos)
76{
77 booke_wdt_ping();
78 return count;
79}
80
81static struct watchdog_info ident = {
82 .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
83 .firmware_version = 0,
84 .identity = "PowerPC Book-E Watchdog",
85};
86
87/*
88 * booke_wdt_ioctl:
89 */
90static int booke_wdt_ioctl (struct inode *inode, struct file *file,
91 unsigned int cmd, unsigned long arg)
92{
93 u32 tmp = 0;
94
95 switch (cmd) {
96 case WDIOC_GETSUPPORT:
97 if (copy_to_user ((struct watchdog_info *) arg, &ident,
98 sizeof(struct watchdog_info)))
99 return -EFAULT;
100 case WDIOC_GETSTATUS:
101 return put_user(ident.options, (u32 *) arg);
102 case WDIOC_GETBOOTSTATUS:
103 /* XXX: something is clearing TSR */
104 tmp = mfspr(SPRN_TSR) & TSR_WRS(3);
105 /* returns 1 if last reset was caused by the WDT */
106 return (tmp ? 1 : 0);
107 case WDIOC_KEEPALIVE:
108 booke_wdt_ping();
109 return 0;
110 case WDIOC_SETTIMEOUT:
111 if (get_user(wdt_period, (u32 *) arg))
112 return -EFAULT;
113 mtspr(SPRN_TCR, (mfspr(SPRN_TCR)&~WDTP(0))|WDTP(wdt_period));
114 return 0;
115 case WDIOC_GETTIMEOUT:
116 return put_user(wdt_period, (u32 *) arg);
117 case WDIOC_SETOPTIONS:
118 if (get_user(tmp, (u32 *) arg))
119 return -EINVAL;
120 if (tmp == WDIOS_ENABLECARD) {
121 booke_wdt_ping();
122 break;
123 } else
124 return -EINVAL;
125 return 0;
126 default:
127 return -ENOIOCTLCMD;
128 }
129
130 return 0;
131}
132/*
133 * booke_wdt_open:
134 */
135static int booke_wdt_open (struct inode *inode, struct file *file)
136{
137 if (wdt_enable == 0) {
138 wdt_enable = 1;
139 booke_wdt_enable();
140 printk (KERN_INFO "PowerPC Book-E Watchdog Timer Enabled (wdt_period=%d)\n",
141 wdt_period);
142 }
143
144 return 0;
145}
146
147static struct file_operations booke_wdt_fops = {
148 .owner = THIS_MODULE,
149 .llseek = no_llseek,
150 .write = booke_wdt_write,
151 .ioctl = booke_wdt_ioctl,
152 .open = booke_wdt_open,
153};
154
155static struct miscdevice booke_wdt_miscdev = {
156 .minor = WATCHDOG_MINOR,
157 .name = "watchdog",
158 .fops = &booke_wdt_fops,
159};
160
161static void __exit booke_wdt_exit(void)
162{
163 misc_deregister(&booke_wdt_miscdev);
164}
165
166/*
167 * booke_wdt_init:
168 */
169static int __init booke_wdt_init(void)
170{
171 int ret = 0;
172
173 printk (KERN_INFO "PowerPC Book-E Watchdog Timer Loaded\n");
174 ident.firmware_version = cpu_specs[0].pvr_value;
175
176 ret = misc_register(&booke_wdt_miscdev);
177 if (ret) {
178 printk (KERN_CRIT "Cannot register miscdev on minor=%d (err=%d)\n",
179 WATCHDOG_MINOR, ret);
180 return ret;
181 }
182
183 if (wdt_enable == 1) {
184 printk (KERN_INFO "PowerPC Book-E Watchdog Timer Enabled (wdt_period=%d)\n",
185 wdt_period);
186 booke_wdt_enable();
187 }
188
189 return ret;
190}
191device_initcall(booke_wdt_init);