xref: /openbmc/linux/drivers/watchdog/wm831x_wdt.c (revision 25985edc)
1 /*
2  * Watchdog driver for the wm831x PMICs
3  *
4  * Copyright (C) 2009 Wolfson Microelectronics
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation
9  */
10 
11 #include <linux/module.h>
12 #include <linux/moduleparam.h>
13 #include <linux/types.h>
14 #include <linux/kernel.h>
15 #include <linux/fs.h>
16 #include <linux/miscdevice.h>
17 #include <linux/platform_device.h>
18 #include <linux/watchdog.h>
19 #include <linux/uaccess.h>
20 #include <linux/gpio.h>
21 
22 #include <linux/mfd/wm831x/core.h>
23 #include <linux/mfd/wm831x/pdata.h>
24 #include <linux/mfd/wm831x/watchdog.h>
25 
26 static int nowayout = WATCHDOG_NOWAYOUT;
27 module_param(nowayout, int, 0);
28 MODULE_PARM_DESC(nowayout,
29 		 "Watchdog cannot be stopped once started (default="
30 		 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
31 
32 static unsigned long wm831x_wdt_users;
33 static struct miscdevice wm831x_wdt_miscdev;
34 static int wm831x_wdt_expect_close;
35 static DEFINE_MUTEX(wdt_mutex);
36 static struct wm831x *wm831x;
37 static unsigned int update_gpio;
38 static unsigned int update_state;
39 
40 /* We can't use the sub-second values here but they're included
41  * for completeness.  */
42 static struct {
43 	int time;  /* Seconds */
44 	u16 val;   /* WDOG_TO value */
45 } wm831x_wdt_cfgs[] = {
46 	{  1, 2 },
47 	{  2, 3 },
48 	{  4, 4 },
49 	{  8, 5 },
50 	{ 16, 6 },
51 	{ 32, 7 },
52 	{ 33, 7 },  /* Actually 32.768s so include both, others round down */
53 };
54 
55 static int wm831x_wdt_set_timeout(struct wm831x *wm831x, u16 value)
56 {
57 	int ret;
58 
59 	mutex_lock(&wdt_mutex);
60 
61 	ret = wm831x_reg_unlock(wm831x);
62 	if (ret == 0) {
63 		ret = wm831x_set_bits(wm831x, WM831X_WATCHDOG,
64 				      WM831X_WDOG_TO_MASK, value);
65 		wm831x_reg_lock(wm831x);
66 	} else {
67 		dev_err(wm831x->dev, "Failed to unlock security key: %d\n",
68 			ret);
69 	}
70 
71 	mutex_unlock(&wdt_mutex);
72 
73 	return ret;
74 }
75 
76 static int wm831x_wdt_start(struct wm831x *wm831x)
77 {
78 	int ret;
79 
80 	mutex_lock(&wdt_mutex);
81 
82 	ret = wm831x_reg_unlock(wm831x);
83 	if (ret == 0) {
84 		ret = wm831x_set_bits(wm831x, WM831X_WATCHDOG,
85 				      WM831X_WDOG_ENA, WM831X_WDOG_ENA);
86 		wm831x_reg_lock(wm831x);
87 	} else {
88 		dev_err(wm831x->dev, "Failed to unlock security key: %d\n",
89 			ret);
90 	}
91 
92 	mutex_unlock(&wdt_mutex);
93 
94 	return ret;
95 }
96 
97 static int wm831x_wdt_stop(struct wm831x *wm831x)
98 {
99 	int ret;
100 
101 	mutex_lock(&wdt_mutex);
102 
103 	ret = wm831x_reg_unlock(wm831x);
104 	if (ret == 0) {
105 		ret = wm831x_set_bits(wm831x, WM831X_WATCHDOG,
106 				      WM831X_WDOG_ENA, 0);
107 		wm831x_reg_lock(wm831x);
108 	} else {
109 		dev_err(wm831x->dev, "Failed to unlock security key: %d\n",
110 			ret);
111 	}
112 
113 	mutex_unlock(&wdt_mutex);
114 
115 	return ret;
116 }
117 
118 static int wm831x_wdt_kick(struct wm831x *wm831x)
119 {
120 	int ret;
121 	u16 reg;
122 
123 	mutex_lock(&wdt_mutex);
124 
125 	if (update_gpio) {
126 		gpio_set_value_cansleep(update_gpio, update_state);
127 		update_state = !update_state;
128 		ret = 0;
129 		goto out;
130 	}
131 
132 
133 	reg = wm831x_reg_read(wm831x, WM831X_WATCHDOG);
134 
135 	if (!(reg & WM831X_WDOG_RST_SRC)) {
136 		dev_err(wm831x->dev, "Hardware watchdog update unsupported\n");
137 		ret = -EINVAL;
138 		goto out;
139 	}
140 
141 	reg |= WM831X_WDOG_RESET;
142 
143 	ret = wm831x_reg_unlock(wm831x);
144 	if (ret == 0) {
145 		ret = wm831x_reg_write(wm831x, WM831X_WATCHDOG, reg);
146 		wm831x_reg_lock(wm831x);
147 	} else {
148 		dev_err(wm831x->dev, "Failed to unlock security key: %d\n",
149 			ret);
150 	}
151 
152 out:
153 	mutex_unlock(&wdt_mutex);
154 
155 	return ret;
156 }
157 
158 static int wm831x_wdt_open(struct inode *inode, struct file *file)
159 {
160 	int ret;
161 
162 	if (!wm831x)
163 		return -ENODEV;
164 
165 	if (test_and_set_bit(0, &wm831x_wdt_users))
166 		return -EBUSY;
167 
168 	ret = wm831x_wdt_start(wm831x);
169 	if (ret != 0)
170 		return ret;
171 
172 	return nonseekable_open(inode, file);
173 }
174 
175 static int wm831x_wdt_release(struct inode *inode, struct file *file)
176 {
177 	if (wm831x_wdt_expect_close)
178 		wm831x_wdt_stop(wm831x);
179 	else {
180 		dev_warn(wm831x->dev, "Watchdog device closed uncleanly\n");
181 		wm831x_wdt_kick(wm831x);
182 	}
183 
184 	clear_bit(0, &wm831x_wdt_users);
185 
186 	return 0;
187 }
188 
189 static ssize_t wm831x_wdt_write(struct file *file,
190 				const char __user *data, size_t count,
191 				loff_t *ppos)
192 {
193 	size_t i;
194 
195 	if (count) {
196 		wm831x_wdt_kick(wm831x);
197 
198 		if (!nowayout) {
199 			/* In case it was set long ago */
200 			wm831x_wdt_expect_close = 0;
201 
202 			/* scan to see whether or not we got the magic
203 			   character */
204 			for (i = 0; i != count; i++) {
205 				char c;
206 				if (get_user(c, data + i))
207 					return -EFAULT;
208 				if (c == 'V')
209 					wm831x_wdt_expect_close = 42;
210 			}
211 		}
212 	}
213 	return count;
214 }
215 
216 static const struct watchdog_info ident = {
217 	.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
218 	.identity = "WM831x Watchdog",
219 };
220 
221 static long wm831x_wdt_ioctl(struct file *file, unsigned int cmd,
222 			     unsigned long arg)
223 {
224 	int ret = -ENOTTY, time, i;
225 	void __user *argp = (void __user *)arg;
226 	int __user *p = argp;
227 	u16 reg;
228 
229 	switch (cmd) {
230 	case WDIOC_GETSUPPORT:
231 		ret = copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0;
232 		break;
233 
234 	case WDIOC_GETSTATUS:
235 	case WDIOC_GETBOOTSTATUS:
236 		ret = put_user(0, p);
237 		break;
238 
239 	case WDIOC_SETOPTIONS:
240 	{
241 		int options;
242 
243 		if (get_user(options, p))
244 			return -EFAULT;
245 
246 		ret = -EINVAL;
247 
248 		/* Setting both simultaneously means at least one must fail */
249 		if (options == WDIOS_DISABLECARD)
250 			ret = wm831x_wdt_start(wm831x);
251 
252 		if (options == WDIOS_ENABLECARD)
253 			ret = wm831x_wdt_stop(wm831x);
254 		break;
255 	}
256 
257 	case WDIOC_KEEPALIVE:
258 		ret = wm831x_wdt_kick(wm831x);
259 		break;
260 
261 	case WDIOC_SETTIMEOUT:
262 		ret = get_user(time, p);
263 		if (ret)
264 			break;
265 
266 		if (time == 0) {
267 			if (nowayout)
268 				ret = -EINVAL;
269 			else
270 				wm831x_wdt_stop(wm831x);
271 			break;
272 		}
273 
274 		for (i = 0; i < ARRAY_SIZE(wm831x_wdt_cfgs); i++)
275 			if (wm831x_wdt_cfgs[i].time == time)
276 				break;
277 		if (i == ARRAY_SIZE(wm831x_wdt_cfgs))
278 			ret = -EINVAL;
279 		else
280 			ret = wm831x_wdt_set_timeout(wm831x,
281 						     wm831x_wdt_cfgs[i].val);
282 		break;
283 
284 	case WDIOC_GETTIMEOUT:
285 		reg = wm831x_reg_read(wm831x, WM831X_WATCHDOG);
286 		reg &= WM831X_WDOG_TO_MASK;
287 		for (i = 0; i < ARRAY_SIZE(wm831x_wdt_cfgs); i++)
288 			if (wm831x_wdt_cfgs[i].val == reg)
289 				break;
290 		if (i == ARRAY_SIZE(wm831x_wdt_cfgs)) {
291 			dev_warn(wm831x->dev,
292 				 "Unknown watchdog configuration: %x\n", reg);
293 			ret = -EINVAL;
294 		} else
295 			ret = put_user(wm831x_wdt_cfgs[i].time, p);
296 
297 	}
298 
299 	return ret;
300 }
301 
302 static const struct file_operations wm831x_wdt_fops = {
303 	.owner = THIS_MODULE,
304 	.llseek = no_llseek,
305 	.write = wm831x_wdt_write,
306 	.unlocked_ioctl = wm831x_wdt_ioctl,
307 	.open = wm831x_wdt_open,
308 	.release = wm831x_wdt_release,
309 };
310 
311 static struct miscdevice wm831x_wdt_miscdev = {
312 	.minor = WATCHDOG_MINOR,
313 	.name = "watchdog",
314 	.fops = &wm831x_wdt_fops,
315 };
316 
317 static int __devinit wm831x_wdt_probe(struct platform_device *pdev)
318 {
319 	struct wm831x_pdata *chip_pdata;
320 	struct wm831x_watchdog_pdata *pdata;
321 	int reg, ret;
322 
323 	wm831x = dev_get_drvdata(pdev->dev.parent);
324 
325 	ret = wm831x_reg_read(wm831x, WM831X_WATCHDOG);
326 	if (ret < 0) {
327 		dev_err(wm831x->dev, "Failed to read watchdog status: %d\n",
328 			ret);
329 		goto err;
330 	}
331 	reg = ret;
332 
333 	if (reg & WM831X_WDOG_DEBUG)
334 		dev_warn(wm831x->dev, "Watchdog is paused\n");
335 
336 	/* Apply any configuration */
337 	if (pdev->dev.parent->platform_data) {
338 		chip_pdata = pdev->dev.parent->platform_data;
339 		pdata = chip_pdata->watchdog;
340 	} else {
341 		pdata = NULL;
342 	}
343 
344 	if (pdata) {
345 		reg &= ~(WM831X_WDOG_SECACT_MASK | WM831X_WDOG_PRIMACT_MASK |
346 			 WM831X_WDOG_RST_SRC);
347 
348 		reg |= pdata->primary << WM831X_WDOG_PRIMACT_SHIFT;
349 		reg |= pdata->secondary << WM831X_WDOG_SECACT_SHIFT;
350 		reg |= pdata->software << WM831X_WDOG_RST_SRC_SHIFT;
351 
352 		if (pdata->update_gpio) {
353 			ret = gpio_request(pdata->update_gpio,
354 					   "Watchdog update");
355 			if (ret < 0) {
356 				dev_err(wm831x->dev,
357 					"Failed to request update GPIO: %d\n",
358 					ret);
359 				goto err;
360 			}
361 
362 			ret = gpio_direction_output(pdata->update_gpio, 0);
363 			if (ret != 0) {
364 				dev_err(wm831x->dev,
365 					"gpio_direction_output returned: %d\n",
366 					ret);
367 				goto err_gpio;
368 			}
369 
370 			update_gpio = pdata->update_gpio;
371 
372 			/* Make sure the watchdog takes hardware updates */
373 			reg |= WM831X_WDOG_RST_SRC;
374 		}
375 
376 		ret = wm831x_reg_unlock(wm831x);
377 		if (ret == 0) {
378 			ret = wm831x_reg_write(wm831x, WM831X_WATCHDOG, reg);
379 			wm831x_reg_lock(wm831x);
380 		} else {
381 			dev_err(wm831x->dev,
382 				"Failed to unlock security key: %d\n", ret);
383 			goto err_gpio;
384 		}
385 	}
386 
387 	wm831x_wdt_miscdev.parent = &pdev->dev;
388 
389 	ret = misc_register(&wm831x_wdt_miscdev);
390 	if (ret != 0) {
391 		dev_err(wm831x->dev, "Failed to register miscdev: %d\n", ret);
392 		goto err_gpio;
393 	}
394 
395 	return 0;
396 
397 err_gpio:
398 	if (update_gpio) {
399 		gpio_free(update_gpio);
400 		update_gpio = 0;
401 	}
402 err:
403 	return ret;
404 }
405 
406 static int __devexit wm831x_wdt_remove(struct platform_device *pdev)
407 {
408 	if (update_gpio) {
409 		gpio_free(update_gpio);
410 		update_gpio = 0;
411 	}
412 
413 	misc_deregister(&wm831x_wdt_miscdev);
414 
415 	return 0;
416 }
417 
418 static struct platform_driver wm831x_wdt_driver = {
419 	.probe = wm831x_wdt_probe,
420 	.remove = __devexit_p(wm831x_wdt_remove),
421 	.driver = {
422 		.name = "wm831x-watchdog",
423 	},
424 };
425 
426 static int __init wm831x_wdt_init(void)
427 {
428 	return platform_driver_register(&wm831x_wdt_driver);
429 }
430 module_init(wm831x_wdt_init);
431 
432 static void __exit wm831x_wdt_exit(void)
433 {
434 	platform_driver_unregister(&wm831x_wdt_driver);
435 }
436 module_exit(wm831x_wdt_exit);
437 
438 MODULE_AUTHOR("Mark Brown");
439 MODULE_DESCRIPTION("WM831x Watchdog");
440 MODULE_LICENSE("GPL");
441 MODULE_ALIAS("platform:wm831x-watchdog");
442