• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Kontron PLD watchdog driver
4  *
5  * Copyright (c) 2010-2013 Kontron Europe GmbH
6  * Author: Michael Brunner <michael.brunner@kontron.com>
7  *
8  * Note: From the PLD watchdog point of view timeout and pretimeout are
9  *       defined differently than in the kernel.
10  *       First the pretimeout stage runs out before the timeout stage gets
11  *       active.
12  *
13  * Kernel/API:                     P-----| pretimeout
14  *               |-----------------------T timeout
15  * Watchdog:     |-----------------P       pretimeout_stage
16  *                                 |-----T timeout_stage
17  */
18 
19 #include <linux/module.h>
20 #include <linux/moduleparam.h>
21 #include <linux/uaccess.h>
22 #include <linux/watchdog.h>
23 #include <linux/platform_device.h>
24 #include <linux/mfd/kempld.h>
25 
26 #define KEMPLD_WDT_STAGE_TIMEOUT(x)	(0x1b + (x) * 4)
27 #define KEMPLD_WDT_STAGE_CFG(x)		(0x18 + (x))
28 #define STAGE_CFG_GET_PRESCALER(x)	(((x) & 0x30) >> 4)
29 #define STAGE_CFG_SET_PRESCALER(x)	(((x) & 0x3) << 4)
30 #define STAGE_CFG_PRESCALER_MASK	0x30
31 #define STAGE_CFG_ACTION_MASK		0x7
32 #define STAGE_CFG_ASSERT		(1 << 3)
33 
34 #define KEMPLD_WDT_MAX_STAGES		2
35 #define KEMPLD_WDT_KICK			0x16
36 #define KEMPLD_WDT_CFG			0x17
37 #define KEMPLD_WDT_CFG_ENABLE		0x10
38 #define KEMPLD_WDT_CFG_ENABLE_LOCK	0x8
39 #define KEMPLD_WDT_CFG_GLOBAL_LOCK	0x80
40 
41 enum {
42 	ACTION_NONE = 0,
43 	ACTION_RESET,
44 	ACTION_NMI,
45 	ACTION_SMI,
46 	ACTION_SCI,
47 	ACTION_DELAY,
48 };
49 
50 enum {
51 	STAGE_TIMEOUT = 0,
52 	STAGE_PRETIMEOUT,
53 };
54 
55 enum {
56 	PRESCALER_21 = 0,
57 	PRESCALER_17,
58 	PRESCALER_12,
59 };
60 
61 static const u32 kempld_prescaler[] = {
62 	[PRESCALER_21] = (1 << 21) - 1,
63 	[PRESCALER_17] = (1 << 17) - 1,
64 	[PRESCALER_12] = (1 << 12) - 1,
65 	0,
66 };
67 
68 struct kempld_wdt_stage {
69 	unsigned int	id;
70 	u32		mask;
71 };
72 
73 struct kempld_wdt_data {
74 	struct kempld_device_data	*pld;
75 	struct watchdog_device		wdd;
76 	unsigned int			pretimeout;
77 	struct kempld_wdt_stage		stage[KEMPLD_WDT_MAX_STAGES];
78 #ifdef CONFIG_PM
79 	u8				pm_status_store;
80 #endif
81 };
82 
83 #define DEFAULT_TIMEOUT		30 /* seconds */
84 #define DEFAULT_PRETIMEOUT	0
85 
86 static unsigned int timeout = DEFAULT_TIMEOUT;
87 module_param(timeout, uint, 0);
88 MODULE_PARM_DESC(timeout,
89 	"Watchdog timeout in seconds. (>=0, default="
90 	__MODULE_STRING(DEFAULT_TIMEOUT) ")");
91 
92 static unsigned int pretimeout = DEFAULT_PRETIMEOUT;
93 module_param(pretimeout, uint, 0);
94 MODULE_PARM_DESC(pretimeout,
95 	"Watchdog pretimeout in seconds. (>=0, default="
96 	__MODULE_STRING(DEFAULT_PRETIMEOUT) ")");
97 
98 static bool nowayout = WATCHDOG_NOWAYOUT;
99 module_param(nowayout, bool, 0);
100 MODULE_PARM_DESC(nowayout,
101 	"Watchdog cannot be stopped once started (default="
102 	__MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
103 
kempld_wdt_set_stage_action(struct kempld_wdt_data * wdt_data,struct kempld_wdt_stage * stage,u8 action)104 static int kempld_wdt_set_stage_action(struct kempld_wdt_data *wdt_data,
105 					struct kempld_wdt_stage *stage,
106 					u8 action)
107 {
108 	struct kempld_device_data *pld = wdt_data->pld;
109 	u8 stage_cfg;
110 
111 	if (!stage || !stage->mask)
112 		return -EINVAL;
113 
114 	kempld_get_mutex(pld);
115 	stage_cfg = kempld_read8(pld, KEMPLD_WDT_STAGE_CFG(stage->id));
116 	stage_cfg &= ~STAGE_CFG_ACTION_MASK;
117 	stage_cfg |= (action & STAGE_CFG_ACTION_MASK);
118 
119 	if (action == ACTION_RESET)
120 		stage_cfg |= STAGE_CFG_ASSERT;
121 	else
122 		stage_cfg &= ~STAGE_CFG_ASSERT;
123 
124 	kempld_write8(pld, KEMPLD_WDT_STAGE_CFG(stage->id), stage_cfg);
125 	kempld_release_mutex(pld);
126 
127 	return 0;
128 }
129 
kempld_wdt_set_stage_timeout(struct kempld_wdt_data * wdt_data,struct kempld_wdt_stage * stage,unsigned int timeout)130 static int kempld_wdt_set_stage_timeout(struct kempld_wdt_data *wdt_data,
131 					struct kempld_wdt_stage *stage,
132 					unsigned int timeout)
133 {
134 	struct kempld_device_data *pld = wdt_data->pld;
135 	u32 prescaler;
136 	u64 stage_timeout64;
137 	u32 stage_timeout;
138 	u32 remainder;
139 	u8 stage_cfg;
140 
141 	prescaler = kempld_prescaler[PRESCALER_21];
142 
143 	if (!stage)
144 		return -EINVAL;
145 
146 	stage_timeout64 = (u64)timeout * pld->pld_clock;
147 	remainder = do_div(stage_timeout64, prescaler);
148 	if (remainder)
149 		stage_timeout64++;
150 
151 	if (stage_timeout64 > stage->mask)
152 		return -EINVAL;
153 
154 	stage_timeout = stage_timeout64 & stage->mask;
155 
156 	kempld_get_mutex(pld);
157 	stage_cfg = kempld_read8(pld, KEMPLD_WDT_STAGE_CFG(stage->id));
158 	stage_cfg &= ~STAGE_CFG_PRESCALER_MASK;
159 	stage_cfg |= STAGE_CFG_SET_PRESCALER(PRESCALER_21);
160 	kempld_write8(pld, KEMPLD_WDT_STAGE_CFG(stage->id), stage_cfg);
161 	kempld_write32(pld, KEMPLD_WDT_STAGE_TIMEOUT(stage->id),
162 			stage_timeout);
163 	kempld_release_mutex(pld);
164 
165 	return 0;
166 }
167 
168 /*
169  * kempld_get_mutex must be called prior to calling this function.
170  */
kempld_wdt_get_timeout(struct kempld_wdt_data * wdt_data,struct kempld_wdt_stage * stage)171 static unsigned int kempld_wdt_get_timeout(struct kempld_wdt_data *wdt_data,
172 						struct kempld_wdt_stage *stage)
173 {
174 	struct kempld_device_data *pld = wdt_data->pld;
175 	unsigned int timeout;
176 	u64 stage_timeout;
177 	u32 prescaler;
178 	u32 remainder;
179 	u8 stage_cfg;
180 
181 	if (!stage->mask)
182 		return 0;
183 
184 	stage_cfg = kempld_read8(pld, KEMPLD_WDT_STAGE_CFG(stage->id));
185 	stage_timeout = kempld_read32(pld, KEMPLD_WDT_STAGE_TIMEOUT(stage->id));
186 	prescaler = kempld_prescaler[STAGE_CFG_GET_PRESCALER(stage_cfg)];
187 
188 	stage_timeout = (stage_timeout & stage->mask) * prescaler;
189 	remainder = do_div(stage_timeout, pld->pld_clock);
190 	if (remainder)
191 		stage_timeout++;
192 
193 	timeout = stage_timeout;
194 	WARN_ON_ONCE(timeout != stage_timeout);
195 
196 	return timeout;
197 }
198 
kempld_wdt_set_timeout(struct watchdog_device * wdd,unsigned int timeout)199 static int kempld_wdt_set_timeout(struct watchdog_device *wdd,
200 					unsigned int timeout)
201 {
202 	struct kempld_wdt_data *wdt_data = watchdog_get_drvdata(wdd);
203 	struct kempld_wdt_stage *pretimeout_stage;
204 	struct kempld_wdt_stage *timeout_stage;
205 	int ret;
206 
207 	timeout_stage = &wdt_data->stage[STAGE_TIMEOUT];
208 	pretimeout_stage = &wdt_data->stage[STAGE_PRETIMEOUT];
209 
210 	if (pretimeout_stage->mask && wdt_data->pretimeout > 0)
211 		timeout = wdt_data->pretimeout;
212 
213 	ret = kempld_wdt_set_stage_action(wdt_data, timeout_stage,
214 						ACTION_RESET);
215 	if (ret)
216 		return ret;
217 	ret = kempld_wdt_set_stage_timeout(wdt_data, timeout_stage,
218 						timeout);
219 	if (ret)
220 		return ret;
221 
222 	wdd->timeout = timeout;
223 	return 0;
224 }
225 
kempld_wdt_set_pretimeout(struct watchdog_device * wdd,unsigned int pretimeout)226 static int kempld_wdt_set_pretimeout(struct watchdog_device *wdd,
227 					unsigned int pretimeout)
228 {
229 	struct kempld_wdt_data *wdt_data = watchdog_get_drvdata(wdd);
230 	struct kempld_wdt_stage *pretimeout_stage;
231 	u8 action = ACTION_NONE;
232 	int ret;
233 
234 	pretimeout_stage = &wdt_data->stage[STAGE_PRETIMEOUT];
235 
236 	if (!pretimeout_stage->mask)
237 		return -ENXIO;
238 
239 	if (pretimeout > wdd->timeout)
240 		return -EINVAL;
241 
242 	if (pretimeout > 0)
243 		action = ACTION_NMI;
244 
245 	ret = kempld_wdt_set_stage_action(wdt_data, pretimeout_stage,
246 						action);
247 	if (ret)
248 		return ret;
249 	ret = kempld_wdt_set_stage_timeout(wdt_data, pretimeout_stage,
250 						wdd->timeout - pretimeout);
251 	if (ret)
252 		return ret;
253 
254 	wdt_data->pretimeout = pretimeout;
255 	return 0;
256 }
257 
kempld_wdt_update_timeouts(struct kempld_wdt_data * wdt_data)258 static void kempld_wdt_update_timeouts(struct kempld_wdt_data *wdt_data)
259 {
260 	struct kempld_device_data *pld = wdt_data->pld;
261 	struct kempld_wdt_stage *pretimeout_stage;
262 	struct kempld_wdt_stage *timeout_stage;
263 	unsigned int pretimeout, timeout;
264 
265 	pretimeout_stage = &wdt_data->stage[STAGE_PRETIMEOUT];
266 	timeout_stage = &wdt_data->stage[STAGE_TIMEOUT];
267 
268 	kempld_get_mutex(pld);
269 	pretimeout = kempld_wdt_get_timeout(wdt_data, pretimeout_stage);
270 	timeout = kempld_wdt_get_timeout(wdt_data, timeout_stage);
271 	kempld_release_mutex(pld);
272 
273 	if (pretimeout)
274 		wdt_data->pretimeout = timeout;
275 	else
276 		wdt_data->pretimeout = 0;
277 
278 	wdt_data->wdd.timeout = pretimeout + timeout;
279 }
280 
kempld_wdt_start(struct watchdog_device * wdd)281 static int kempld_wdt_start(struct watchdog_device *wdd)
282 {
283 	struct kempld_wdt_data *wdt_data = watchdog_get_drvdata(wdd);
284 	struct kempld_device_data *pld = wdt_data->pld;
285 	u8 status;
286 	int ret;
287 
288 	ret = kempld_wdt_set_timeout(wdd, wdd->timeout);
289 	if (ret)
290 		return ret;
291 
292 	kempld_get_mutex(pld);
293 	status = kempld_read8(pld, KEMPLD_WDT_CFG);
294 	status |= KEMPLD_WDT_CFG_ENABLE;
295 	kempld_write8(pld, KEMPLD_WDT_CFG, status);
296 	status = kempld_read8(pld, KEMPLD_WDT_CFG);
297 	kempld_release_mutex(pld);
298 
299 	/* Check if the watchdog was enabled */
300 	if (!(status & KEMPLD_WDT_CFG_ENABLE))
301 		return -EACCES;
302 
303 	return 0;
304 }
305 
kempld_wdt_stop(struct watchdog_device * wdd)306 static int kempld_wdt_stop(struct watchdog_device *wdd)
307 {
308 	struct kempld_wdt_data *wdt_data = watchdog_get_drvdata(wdd);
309 	struct kempld_device_data *pld = wdt_data->pld;
310 	u8 status;
311 
312 	kempld_get_mutex(pld);
313 	status = kempld_read8(pld, KEMPLD_WDT_CFG);
314 	status &= ~KEMPLD_WDT_CFG_ENABLE;
315 	kempld_write8(pld, KEMPLD_WDT_CFG, status);
316 	status = kempld_read8(pld, KEMPLD_WDT_CFG);
317 	kempld_release_mutex(pld);
318 
319 	/* Check if the watchdog was disabled */
320 	if (status & KEMPLD_WDT_CFG_ENABLE)
321 		return -EACCES;
322 
323 	return 0;
324 }
325 
kempld_wdt_keepalive(struct watchdog_device * wdd)326 static int kempld_wdt_keepalive(struct watchdog_device *wdd)
327 {
328 	struct kempld_wdt_data *wdt_data = watchdog_get_drvdata(wdd);
329 	struct kempld_device_data *pld = wdt_data->pld;
330 
331 	kempld_get_mutex(pld);
332 	kempld_write8(pld, KEMPLD_WDT_KICK, 'K');
333 	kempld_release_mutex(pld);
334 
335 	return 0;
336 }
337 
kempld_wdt_ioctl(struct watchdog_device * wdd,unsigned int cmd,unsigned long arg)338 static long kempld_wdt_ioctl(struct watchdog_device *wdd, unsigned int cmd,
339 				unsigned long arg)
340 {
341 	struct kempld_wdt_data *wdt_data = watchdog_get_drvdata(wdd);
342 	void __user *argp = (void __user *)arg;
343 	int ret = -ENOIOCTLCMD;
344 	int __user *p = argp;
345 	int new_value;
346 
347 	switch (cmd) {
348 	case WDIOC_SETPRETIMEOUT:
349 		if (get_user(new_value, p))
350 			return -EFAULT;
351 		ret = kempld_wdt_set_pretimeout(wdd, new_value);
352 		if (ret)
353 			return ret;
354 		ret = kempld_wdt_keepalive(wdd);
355 		break;
356 	case WDIOC_GETPRETIMEOUT:
357 		ret = put_user(wdt_data->pretimeout, (int __user *)arg);
358 		break;
359 	}
360 
361 	return ret;
362 }
363 
kempld_wdt_probe_stages(struct watchdog_device * wdd)364 static int kempld_wdt_probe_stages(struct watchdog_device *wdd)
365 {
366 	struct kempld_wdt_data *wdt_data = watchdog_get_drvdata(wdd);
367 	struct kempld_device_data *pld = wdt_data->pld;
368 	struct kempld_wdt_stage *pretimeout_stage;
369 	struct kempld_wdt_stage *timeout_stage;
370 	u8 index, data, data_orig;
371 	u32 mask;
372 	int i, j;
373 
374 	pretimeout_stage = &wdt_data->stage[STAGE_PRETIMEOUT];
375 	timeout_stage = &wdt_data->stage[STAGE_TIMEOUT];
376 
377 	pretimeout_stage->mask = 0;
378 	timeout_stage->mask = 0;
379 
380 	for (i = 0; i < 3; i++) {
381 		index = KEMPLD_WDT_STAGE_TIMEOUT(i);
382 		mask = 0;
383 
384 		kempld_get_mutex(pld);
385 		/* Probe each byte individually. */
386 		for (j = 0; j < 4; j++) {
387 			data_orig = kempld_read8(pld, index + j);
388 			kempld_write8(pld, index + j, 0x00);
389 			data = kempld_read8(pld, index + j);
390 			/* A failed write means this byte is reserved */
391 			if (data != 0x00)
392 				break;
393 			kempld_write8(pld, index + j, data_orig);
394 			mask |= 0xff << (j * 8);
395 		}
396 		kempld_release_mutex(pld);
397 
398 		/* Assign available stages to timeout and pretimeout */
399 		if (!timeout_stage->mask) {
400 			timeout_stage->mask = mask;
401 			timeout_stage->id = i;
402 		} else {
403 			if (pld->feature_mask & KEMPLD_FEATURE_BIT_NMI) {
404 				pretimeout_stage->mask = timeout_stage->mask;
405 				timeout_stage->mask = mask;
406 				pretimeout_stage->id = timeout_stage->id;
407 				timeout_stage->id = i;
408 			}
409 			break;
410 		}
411 	}
412 
413 	if (!timeout_stage->mask)
414 		return -ENODEV;
415 
416 	return 0;
417 }
418 
419 static const struct watchdog_info kempld_wdt_info = {
420 	.identity	= "KEMPLD Watchdog",
421 	.options	= WDIOF_SETTIMEOUT |
422 			WDIOF_KEEPALIVEPING |
423 			WDIOF_MAGICCLOSE |
424 			WDIOF_PRETIMEOUT
425 };
426 
427 static const struct watchdog_ops kempld_wdt_ops = {
428 	.owner		= THIS_MODULE,
429 	.start		= kempld_wdt_start,
430 	.stop		= kempld_wdt_stop,
431 	.ping		= kempld_wdt_keepalive,
432 	.set_timeout	= kempld_wdt_set_timeout,
433 	.ioctl		= kempld_wdt_ioctl,
434 };
435 
kempld_wdt_probe(struct platform_device * pdev)436 static int kempld_wdt_probe(struct platform_device *pdev)
437 {
438 	struct kempld_device_data *pld = dev_get_drvdata(pdev->dev.parent);
439 	struct kempld_wdt_data *wdt_data;
440 	struct device *dev = &pdev->dev;
441 	struct watchdog_device *wdd;
442 	u8 status;
443 	int ret = 0;
444 
445 	wdt_data = devm_kzalloc(dev, sizeof(*wdt_data), GFP_KERNEL);
446 	if (!wdt_data)
447 		return -ENOMEM;
448 
449 	wdt_data->pld = pld;
450 	wdd = &wdt_data->wdd;
451 	wdd->parent = dev;
452 
453 	kempld_get_mutex(pld);
454 	status = kempld_read8(pld, KEMPLD_WDT_CFG);
455 	kempld_release_mutex(pld);
456 
457 	/* Enable nowayout if watchdog is already locked */
458 	if (status & (KEMPLD_WDT_CFG_ENABLE_LOCK |
459 			KEMPLD_WDT_CFG_GLOBAL_LOCK)) {
460 		if (!nowayout)
461 			dev_warn(dev,
462 				 "Forcing nowayout - watchdog lock enabled!\n");
463 		nowayout = true;
464 	}
465 
466 	wdd->info = &kempld_wdt_info;
467 	wdd->ops = &kempld_wdt_ops;
468 
469 	watchdog_set_drvdata(wdd, wdt_data);
470 	watchdog_set_nowayout(wdd, nowayout);
471 
472 	ret = kempld_wdt_probe_stages(wdd);
473 	if (ret)
474 		return ret;
475 
476 	kempld_wdt_set_timeout(wdd, timeout);
477 	kempld_wdt_set_pretimeout(wdd, pretimeout);
478 
479 	/* Check if watchdog is already enabled */
480 	if (status & KEMPLD_WDT_CFG_ENABLE) {
481 		/* Get current watchdog settings */
482 		kempld_wdt_update_timeouts(wdt_data);
483 		dev_info(dev, "Watchdog was already enabled\n");
484 	}
485 
486 	platform_set_drvdata(pdev, wdt_data);
487 	watchdog_stop_on_reboot(wdd);
488 	watchdog_stop_on_unregister(wdd);
489 	ret = devm_watchdog_register_device(dev, wdd);
490 	if (ret)
491 		return ret;
492 
493 	dev_info(dev, "Watchdog registered with %ds timeout\n", wdd->timeout);
494 
495 	return 0;
496 }
497 
498 #ifdef CONFIG_PM
499 /* Disable watchdog if it is active during suspend */
kempld_wdt_suspend(struct platform_device * pdev,pm_message_t message)500 static int kempld_wdt_suspend(struct platform_device *pdev,
501 				pm_message_t message)
502 {
503 	struct kempld_wdt_data *wdt_data = platform_get_drvdata(pdev);
504 	struct kempld_device_data *pld = wdt_data->pld;
505 	struct watchdog_device *wdd = &wdt_data->wdd;
506 
507 	kempld_get_mutex(pld);
508 	wdt_data->pm_status_store = kempld_read8(pld, KEMPLD_WDT_CFG);
509 	kempld_release_mutex(pld);
510 
511 	kempld_wdt_update_timeouts(wdt_data);
512 
513 	if (wdt_data->pm_status_store & KEMPLD_WDT_CFG_ENABLE)
514 		return kempld_wdt_stop(wdd);
515 
516 	return 0;
517 }
518 
519 /* Enable watchdog and configure it if necessary */
kempld_wdt_resume(struct platform_device * pdev)520 static int kempld_wdt_resume(struct platform_device *pdev)
521 {
522 	struct kempld_wdt_data *wdt_data = platform_get_drvdata(pdev);
523 	struct watchdog_device *wdd = &wdt_data->wdd;
524 
525 	/*
526 	 * If watchdog was stopped before suspend be sure it gets disabled
527 	 * again, for the case BIOS has enabled it during resume
528 	 */
529 	if (wdt_data->pm_status_store & KEMPLD_WDT_CFG_ENABLE)
530 		return kempld_wdt_start(wdd);
531 	else
532 		return kempld_wdt_stop(wdd);
533 }
534 #else
535 #define kempld_wdt_suspend	NULL
536 #define kempld_wdt_resume	NULL
537 #endif
538 
539 static struct platform_driver kempld_wdt_driver = {
540 	.driver		= {
541 		.name	= "kempld-wdt",
542 	},
543 	.probe		= kempld_wdt_probe,
544 	.suspend	= kempld_wdt_suspend,
545 	.resume		= kempld_wdt_resume,
546 };
547 
548 module_platform_driver(kempld_wdt_driver);
549 
550 MODULE_DESCRIPTION("KEM PLD Watchdog Driver");
551 MODULE_AUTHOR("Michael Brunner <michael.brunner@kontron.com>");
552 MODULE_LICENSE("GPL");
553