aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/watchdog/Kconfig1
-rw-r--r--drivers/watchdog/mpc8xxx_wdt.c110
2 files changed, 38 insertions, 73 deletions
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 833ebe691f9f..8cb4f3dc8c94 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -1202,6 +1202,7 @@ config MPC5200_WDT
1202config 8xxx_WDT 1202config 8xxx_WDT
1203 tristate "MPC8xxx Platform Watchdog Timer" 1203 tristate "MPC8xxx Platform Watchdog Timer"
1204 depends on PPC_8xx || PPC_83xx || PPC_86xx 1204 depends on PPC_8xx || PPC_83xx || PPC_86xx
1205 select WATCHDOG_CORE
1205 help 1206 help
1206 This driver is for a SoC level watchdog that exists on some 1207 This driver is for a SoC level watchdog that exists on some
1207 Freescale PowerPC processors. So far this driver supports: 1208 Freescale PowerPC processors. So far this driver supports:
diff --git a/drivers/watchdog/mpc8xxx_wdt.c b/drivers/watchdog/mpc8xxx_wdt.c
index d82152077fd9..c1f65b4c0aa4 100644
--- a/drivers/watchdog/mpc8xxx_wdt.c
+++ b/drivers/watchdog/mpc8xxx_wdt.c
@@ -73,9 +73,7 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started "
73 * to 0 73 * to 0
74 */ 74 */
75static int prescale = 1; 75static int prescale = 1;
76static unsigned int timeout_sec;
77 76
78static unsigned long wdt_is_open;
79static DEFINE_SPINLOCK(wdt_spinlock); 77static DEFINE_SPINLOCK(wdt_spinlock);
80 78
81static void mpc8xxx_wdt_keepalive(void) 79static void mpc8xxx_wdt_keepalive(void)
@@ -87,39 +85,23 @@ static void mpc8xxx_wdt_keepalive(void)
87 spin_unlock(&wdt_spinlock); 85 spin_unlock(&wdt_spinlock);
88} 86}
89 87
88static struct watchdog_device mpc8xxx_wdt_dev;
90static void mpc8xxx_wdt_timer_ping(unsigned long arg); 89static void mpc8xxx_wdt_timer_ping(unsigned long arg);
91static DEFINE_TIMER(wdt_timer, mpc8xxx_wdt_timer_ping, 0, 0); 90static DEFINE_TIMER(wdt_timer, mpc8xxx_wdt_timer_ping, 0,
91 (unsigned long)&mpc8xxx_wdt_dev);
92 92
93static void mpc8xxx_wdt_timer_ping(unsigned long arg) 93static void mpc8xxx_wdt_timer_ping(unsigned long arg)
94{ 94{
95 struct watchdog_device *w = (struct watchdog_device *)arg;
96
95 mpc8xxx_wdt_keepalive(); 97 mpc8xxx_wdt_keepalive();
96 /* We're pinging it twice faster than needed, just to be sure. */ 98 /* We're pinging it twice faster than needed, just to be sure. */
97 mod_timer(&wdt_timer, jiffies + HZ * timeout_sec / 2); 99 mod_timer(&wdt_timer, jiffies + HZ * w->timeout / 2);
98}
99
100static void mpc8xxx_wdt_pr_warn(const char *msg)
101{
102 pr_crit("%s, expect the %s soon!\n", msg,
103 reset ? "reset" : "machine check exception");
104} 100}
105 101
106static ssize_t mpc8xxx_wdt_write(struct file *file, const char __user *buf, 102static int mpc8xxx_wdt_start(struct watchdog_device *w)
107 size_t count, loff_t *ppos)
108{
109 if (count)
110 mpc8xxx_wdt_keepalive();
111 return count;
112}
113
114static int mpc8xxx_wdt_open(struct inode *inode, struct file *file)
115{ 103{
116 u32 tmp = SWCRR_SWEN; 104 u32 tmp = SWCRR_SWEN;
117 if (test_and_set_bit(0, &wdt_is_open))
118 return -EBUSY;
119
120 /* Once we start the watchdog we can't stop it */
121 if (nowayout)
122 __module_get(THIS_MODULE);
123 105
124 /* Good, fire up the show */ 106 /* Good, fire up the show */
125 if (prescale) 107 if (prescale)
@@ -133,59 +115,37 @@ static int mpc8xxx_wdt_open(struct inode *inode, struct file *file)
133 115
134 del_timer_sync(&wdt_timer); 116 del_timer_sync(&wdt_timer);
135 117
136 return nonseekable_open(inode, file); 118 return 0;
137} 119}
138 120
139static int mpc8xxx_wdt_release(struct inode *inode, struct file *file) 121static int mpc8xxx_wdt_ping(struct watchdog_device *w)
140{ 122{
141 if (!nowayout) 123 mpc8xxx_wdt_keepalive();
142 mpc8xxx_wdt_timer_ping(0);
143 else
144 mpc8xxx_wdt_pr_warn("watchdog closed");
145 clear_bit(0, &wdt_is_open);
146 return 0; 124 return 0;
147} 125}
148 126
149static long mpc8xxx_wdt_ioctl(struct file *file, unsigned int cmd, 127static int mpc8xxx_wdt_stop(struct watchdog_device *w)
150 unsigned long arg)
151{ 128{
152 void __user *argp = (void __user *)arg; 129 mod_timer(&wdt_timer, jiffies);
153 int __user *p = argp; 130 return 0;
154 static const struct watchdog_info ident = {
155 .options = WDIOF_KEEPALIVEPING,
156 .firmware_version = 1,
157 .identity = "MPC8xxx",
158 };
159
160 switch (cmd) {
161 case WDIOC_GETSUPPORT:
162 return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0;
163 case WDIOC_GETSTATUS:
164 case WDIOC_GETBOOTSTATUS:
165 return put_user(0, p);
166 case WDIOC_KEEPALIVE:
167 mpc8xxx_wdt_keepalive();
168 return 0;
169 case WDIOC_GETTIMEOUT:
170 return put_user(timeout_sec, p);
171 default:
172 return -ENOTTY;
173 }
174} 131}
175 132
176static const struct file_operations mpc8xxx_wdt_fops = { 133static struct watchdog_info mpc8xxx_wdt_info = {
177 .owner = THIS_MODULE, 134 .options = WDIOF_KEEPALIVEPING,
178 .llseek = no_llseek, 135 .firmware_version = 1,
179 .write = mpc8xxx_wdt_write, 136 .identity = "MPC8xxx",
180 .unlocked_ioctl = mpc8xxx_wdt_ioctl,
181 .open = mpc8xxx_wdt_open,
182 .release = mpc8xxx_wdt_release,
183}; 137};
184 138
185static struct miscdevice mpc8xxx_wdt_miscdev = { 139static struct watchdog_ops mpc8xxx_wdt_ops = {
186 .minor = WATCHDOG_MINOR, 140 .owner = THIS_MODULE,
187 .name = "watchdog", 141 .start = mpc8xxx_wdt_start,
188 .fops = &mpc8xxx_wdt_fops, 142 .ping = mpc8xxx_wdt_ping,
143 .stop = mpc8xxx_wdt_stop,
144};
145
146static struct watchdog_device mpc8xxx_wdt_dev = {
147 .info = &mpc8xxx_wdt_info,
148 .ops = &mpc8xxx_wdt_ops,
189}; 149};
190 150
191static const struct of_device_id mpc8xxx_wdt_match[]; 151static const struct of_device_id mpc8xxx_wdt_match[];
@@ -197,6 +157,7 @@ static int mpc8xxx_wdt_probe(struct platform_device *ofdev)
197 const struct mpc8xxx_wdt_type *wdt_type; 157 const struct mpc8xxx_wdt_type *wdt_type;
198 u32 freq = fsl_get_sys_freq(); 158 u32 freq = fsl_get_sys_freq();
199 bool enabled; 159 bool enabled;
160 unsigned int timeout_sec;
200 161
201 match = of_match_device(mpc8xxx_wdt_match, &ofdev->dev); 162 match = of_match_device(mpc8xxx_wdt_match, &ofdev->dev);
202 if (!match) 163 if (!match)
@@ -223,6 +184,7 @@ static int mpc8xxx_wdt_probe(struct platform_device *ofdev)
223 else 184 else
224 timeout_sec = timeout / freq; 185 timeout_sec = timeout / freq;
225 186
187 mpc8xxx_wdt_dev.timeout = timeout_sec;
226#ifdef MODULE 188#ifdef MODULE
227 ret = mpc8xxx_wdt_init_late(); 189 ret = mpc8xxx_wdt_init_late();
228 if (ret) 190 if (ret)
@@ -238,7 +200,7 @@ static int mpc8xxx_wdt_probe(struct platform_device *ofdev)
238 * userspace handles it. 200 * userspace handles it.
239 */ 201 */
240 if (enabled) 202 if (enabled)
241 mpc8xxx_wdt_timer_ping(0); 203 mod_timer(&wdt_timer, jiffies);
242 return 0; 204 return 0;
243err_unmap: 205err_unmap:
244 iounmap(wd_base); 206 iounmap(wd_base);
@@ -248,9 +210,10 @@ err_unmap:
248 210
249static int mpc8xxx_wdt_remove(struct platform_device *ofdev) 211static int mpc8xxx_wdt_remove(struct platform_device *ofdev)
250{ 212{
251 mpc8xxx_wdt_pr_warn("watchdog removed"); 213 pr_crit("Watchdog removed, expect the %s soon!\n",
214 reset ? "reset" : "machine check exception");
252 del_timer_sync(&wdt_timer); 215 del_timer_sync(&wdt_timer);
253 misc_deregister(&mpc8xxx_wdt_miscdev); 216 watchdog_unregister_device(&mpc8xxx_wdt_dev);
254 iounmap(wd_base); 217 iounmap(wd_base);
255 218
256 return 0; 219 return 0;
@@ -302,10 +265,11 @@ static int mpc8xxx_wdt_init_late(void)
302 if (!wd_base) 265 if (!wd_base)
303 return -ENODEV; 266 return -ENODEV;
304 267
305 ret = misc_register(&mpc8xxx_wdt_miscdev); 268 watchdog_set_nowayout(&mpc8xxx_wdt_dev, nowayout);
269
270 ret = watchdog_register_device(&mpc8xxx_wdt_dev);
306 if (ret) { 271 if (ret) {
307 pr_err("cannot register miscdev on minor=%d (err=%d)\n", 272 pr_err("cannot register watchdog device (err=%d)\n", ret);
308 WATCHDOG_MINOR, ret);
309 return ret; 273 return ret;
310 } 274 }
311 return 0; 275 return 0;