1/*
2 * drivers/watchdog/ubi32_wdt.c
3 *   Ubicom32 Watchdog Driver
4 *
5 * Originally based on softdog.c
6 * Copyright 2006-2007 Analog Devices Inc.
7 * Copyright 2006-2007 Michele d'Amico
8 * Copyright 1996 Alan Cox <alan@lxorguk.ukuu.org.uk>
9 * (C) Copyright 2009, Ubicom, Inc.
10 *
11 * This file is part of the Ubicom32 Linux Kernel Port.
12 *
13 * The Ubicom32 Linux Kernel Port is free software: you can redistribute
14 * it and/or modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation, either version 2 of the
16 * License, or (at your option) any later version.
17 *
18 * The Ubicom32 Linux Kernel Port is distributed in the hope that it
19 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
20 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
21 * the GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with the Ubicom32 Linux Kernel Port.  If not,
25 * see <http://www.gnu.org/licenses/>.
26 *
27 * Ubicom32 implementation derived from (with many thanks):
28 *   arch/m68knommu
29 *   arch/blackfin
30 *   arch/parisc
31 */
32#include <linux/platform_device.h>
33#include <linux/module.h>
34#include <linux/moduleparam.h>
35#include <linux/types.h>
36#include <linux/timer.h>
37#include <linux/miscdevice.h>
38#include <linux/watchdog.h>
39#include <linux/fs.h>
40#include <linux/notifier.h>
41#include <linux/reboot.h>
42#include <linux/init.h>
43#include <linux/interrupt.h>
44#include <linux/uaccess.h>
45#include <asm/ip5000.h>
46
47#define WATCHDOG_NAME "ubi32-wdt"
48#define PFX WATCHDOG_NAME ": "
49
50#define OSC1_FREQ 12000000
51#define WATCHDOG_SEC_TO_CYC(x) (OSC1_FREQ * (x))
52#define WATCHDOG_MAX_SEC (0xffffffff / OSC1_FREQ)
53
54#define MIN_PROCESSOR_ADDRESS 0x03000000
55
56static DEFINE_SPINLOCK(ubi32_wdt_spinlock);
57
58#define WATCHDOG_TIMEOUT 20
59
60#if defined(CONFIG_WATCHDOG_NOWAYOUT)
61#define WATCHDOG_NOWAYOUT 1
62#else
63#define WATCHDOG_NOWAYOUT 0
64#endif
65
66static unsigned int timeout = WATCHDOG_TIMEOUT;
67static int nowayout = WATCHDOG_NOWAYOUT;
68static struct watchdog_info ubi32_wdt_info;
69static unsigned long open_check;
70static char expect_close;
71
72#if !defined(CONFIG_SMP)
73#define UBI32_WDT_LOCK(lock, flags) local_irq_save(flags)
74#define UBI32_WDT_UNLOCK(lock, flags) local_irq_restore(flags)
75#define UBI32_WDT_LOCK_CHECK()
76#else
77#define UBI32_WDT_LOCK(lock, flags) spin_lock_irqsave((lock), (flags));
78#define UBI32_WDT_UNLOCK(lock, flags) spin_unlock_irqrestore((lock), (flags));
79#define UBI32_WDT_LOCK_CHECK() BUG_ON(!spin_is_locked(&ubi32_wdt_spinlock));
80#endif
81
82/*
83 * ubi32_wdt_remaining()
84 * 	Return the approximate number of seconds remaining
85 */
86static int ubi32_wdt_remaining(void)
87{
88	int compare;
89	int curr;
90
91	UBI32_WDT_LOCK_CHECK();
92
93	ubicom32_write_reg(&UBICOM32_IO_TIMER->tkey, TIMER_TKEYVAL);
94	compare = ubicom32_read_reg(&UBICOM32_IO_TIMER->wdcom);
95	curr = ubicom32_read_reg(&UBICOM32_IO_TIMER->mptval);
96	ubicom32_write_reg(&UBICOM32_IO_TIMER->tkey, 0);
97	return (compare - curr) / OSC1_FREQ;
98
99}
100
101/*
102 * ubi32_wdt_keepalive()
103 *	Keep the Userspace Watchdog Alive
104 *
105 * The Userspace watchdog got a KeepAlive: schedule the next timeout.
106 */
107static int ubi32_wdt_keepalive(void)
108{
109	UBI32_WDT_LOCK_CHECK();
110	ubicom32_write_reg(&UBICOM32_IO_TIMER->tkey, TIMER_TKEYVAL);
111	ubicom32_write_reg(&UBICOM32_IO_TIMER->wdcom,
112			ubicom32_read_reg(&UBICOM32_IO_TIMER->mptval)
113			+ WATCHDOG_SEC_TO_CYC(timeout));
114	ubicom32_write_reg(&UBICOM32_IO_TIMER->tkey, 0);
115	return 0;
116}
117
118/*
119 * ubi32_wdt_stop()
120 *	Stop the on-chip Watchdog
121 */
122static int ubi32_wdt_stop(void)
123{
124	UBI32_WDT_LOCK_CHECK();
125	ubicom32_write_reg(&UBICOM32_IO_TIMER->tkey, TIMER_TKEYVAL);
126	ubicom32_write_reg(&UBICOM32_IO_TIMER->wdcfg, TIMER_WATCHDOG_DISABLE);
127	ubicom32_write_reg(&UBICOM32_IO_TIMER->tkey, 0);
128	return 0;
129}
130
131/*
132 * ubi32_wdt_start()
133 *	Start the on-chip Watchdog
134 */
135static int ubi32_wdt_start(void)
136{
137	UBI32_WDT_LOCK_CHECK();
138	ubicom32_write_reg(&UBICOM32_IO_TIMER->tkey, TIMER_TKEYVAL);
139	ubicom32_write_reg(&UBICOM32_IO_TIMER->wdcom,
140			ubicom32_read_reg(&UBICOM32_IO_TIMER->mptval)
141			+ WATCHDOG_SEC_TO_CYC(timeout));
142	ubicom32_write_reg(&UBICOM32_IO_TIMER->wdcfg, ~TIMER_WATCHDOG_DISABLE);
143	ubicom32_write_reg(&UBICOM32_IO_TIMER->tkey, 0);
144	return 0;
145}
146
147/*
148 * ubi32_wdt_running()
149 * 	Return true if the watchdog is configured
150 */
151static int ubi32_wdt_running(void)
152{
153	int enabled;
154
155	UBI32_WDT_LOCK_CHECK();
156	ubicom32_write_reg(&UBICOM32_IO_TIMER->tkey, TIMER_TKEYVAL);
157	enabled = ubicom32_read_reg(&UBICOM32_IO_TIMER->wdcfg) == ~TIMER_WATCHDOG_DISABLE;
158	ubicom32_write_reg(&UBICOM32_IO_TIMER->tkey, 0);
159	return enabled;
160}
161
162/*
163 * ubi32_wdt_set_timeout()
164 *	Set the Userspace Watchdog timeout
165 *
166 * - @t: new timeout value (in seconds)
167 */
168static int ubi32_wdt_set_timeout(unsigned long t)
169{
170	UBI32_WDT_LOCK_CHECK();
171
172	if (t > WATCHDOG_MAX_SEC) {
173		printk(KERN_WARNING PFX "request to large: %ld [1-%d] sec)\n", t, WATCHDOG_MAX_SEC);
174		return -EINVAL;
175	}
176
177	/*
178	 * If we are running, then reset the time value so
179	 * that the new value has an immediate effect.
180	 */
181	timeout = t;
182	if (ubi32_wdt_running()) {
183		ubi32_wdt_keepalive();
184	}
185	return 0;
186}
187
188/*
189 * ubi32_wdt_open()
190 *	Open the Device
191 */
192static int ubi32_wdt_open(struct inode *inode, struct file *file)
193{
194	unsigned long flags;
195
196	if (test_and_set_bit(0, &open_check))
197		return -EBUSY;
198
199	if (nowayout)
200		__module_get(THIS_MODULE);
201
202	spin_lock_irqsave(&ubi32_wdt_spinlock, flags);
203	ubi32_wdt_start();
204	spin_unlock_irqrestore(&ubi32_wdt_spinlock, flags);
205
206	return nonseekable_open(inode, file);
207}
208
209/*
210 * ubi32_wdt_close()
211 *	Close the Device
212 */
213static int ubi32_wdt_release(struct inode *inode, struct file *file)
214{
215	unsigned long flags;
216
217	/*
218	 * If we don't expect a close, then the watchdog continues
219	 * even though the device is closed.  The caller will have
220	 * a full timeout value to reopen the device and continue
221	 * stroking it.
222	 */
223	if (expect_close != 42) {
224		printk(KERN_CRIT PFX
225			"Unexpected close, not stopping watchdog!\n");
226		spin_lock_irqsave(&ubi32_wdt_spinlock, flags);
227		ubi32_wdt_keepalive();
228		spin_unlock_irqrestore(&ubi32_wdt_spinlock, flags);
229	} else {
230		spin_lock_irqsave(&ubi32_wdt_spinlock, flags);
231		ubi32_wdt_stop();
232		spin_unlock_irqrestore(&ubi32_wdt_spinlock, flags);
233	}
234
235	expect_close = 0;
236	clear_bit(0, &open_check);
237	return 0;
238}
239
240/*
241 * ubi32_wdt_write()
242 *	Write to Device
243 *
244 * If the user writes nothing, nothing happens.
245 * If the user writes a V, then we expect a close and allow a release.
246 * If the user writes anything else, it is ignored.
247 */
248static ssize_t ubi32_wdt_write(struct file *file, const char __user *data,
249						size_t len, loff_t *ppos)
250{
251	size_t i;
252	unsigned long flags;
253
254	/*
255	 * Every write resets the expect_close.  The last write
256	 * must be a V to allow shutdown on close.
257	 */
258	expect_close = 0;
259
260	/*
261	 * Empty writes still ping.
262	 */
263	if (!len) {
264		goto ping;
265	}
266
267	/*
268	 * If nowayout is set, it does not matter if the caller
269	 * is trying to send the magic 'V' we will not allow a
270	 * close to stop us.
271	 */
272	if (nowayout) {
273		goto ping;
274	}
275
276	/*
277	 * See if the program wrote a 'V' and if so disable
278	 * the watchdog on release.
279	 */
280	for (i = 0; i < len; i++) {
281		char c;
282		if (get_user(c, data + i)) {
283			return -EFAULT;
284		}
285
286		if (c == 'V') {
287			expect_close = 42;
288		}
289	}
290
291ping:
292	spin_lock_irqsave(&ubi32_wdt_spinlock, flags);
293	ubi32_wdt_keepalive();
294	spin_unlock_irqrestore(&ubi32_wdt_spinlock, flags);
295	return len;
296}
297
298/*
299 * ubi32_wdt_ioctl()
300 *	Query the watchdog device.
301 *
302 * Query basic information from the device or ping it, as outlined by the
303 * watchdog API.
304 */
305static long ubi32_wdt_ioctl(struct file *file,
306				unsigned int cmd, unsigned long arg)
307{
308	void __user *argp = (void __user *)arg;
309	int __user *p = argp;
310
311	switch (cmd) {
312	case WDIOC_GETSUPPORT:
313		if (copy_to_user(argp, &ubi32_wdt_info, sizeof(ubi32_wdt_info))) {
314			return -EFAULT;
315		}
316		return 0;
317
318	case WDIOC_GETSTATUS: {
319		unsigned long flags;
320		int running;
321
322		spin_lock_irqsave(&ubi32_wdt_spinlock, flags);
323		running = ubi32_wdt_running();
324		spin_unlock_irqrestore(&ubi32_wdt_spinlock, flags);
325		return running;
326	}
327
328	case WDIOC_GETBOOTSTATUS:
329		return ubicom32_get_reset_reason();
330
331	case WDIOC_SETOPTIONS: {
332		unsigned long flags;
333		int options, ret = -EINVAL;
334
335		/*
336		 * The sample application does not pass a pointer
337		 * but directly passes a value of 1 or 2; however
338		 * all of the implementations (and thus probably
339		 * the real applications) pass a pointer to a value.
340		 *
341		 * It should be noted that  WDIOC_SETOPTIONS is defined as
342		 * _IOR(WATCHDOG_IOCTL_BASE, 4, int), which means
343		 * that it should be an int and NOT a pointer.
344		 *
345		 * TODO: Examine this code for future chips.
346		 * TODO: Report the sample code defect.
347		 */
348		if ((int)p < MIN_PROCESSOR_ADDRESS) {
349			options = (int)p;
350		} else {
351			if (get_user(options, p))
352			return -EFAULT;
353		}
354
355		spin_lock_irqsave(&ubi32_wdt_spinlock, flags);
356		if (options & WDIOS_DISABLECARD) {
357			ubi32_wdt_stop();
358			ret = 0;
359		}
360		if (options & WDIOS_ENABLECARD) {
361			ubi32_wdt_start();
362			ret = 0;
363		}
364		spin_unlock_irqrestore(&ubi32_wdt_spinlock, flags);
365		return ret;
366	}
367
368	case WDIOC_KEEPALIVE: {
369		unsigned long flags;
370
371		spin_lock_irqsave(&ubi32_wdt_spinlock, flags);
372		ubi32_wdt_keepalive();
373		spin_unlock_irqrestore(&ubi32_wdt_spinlock, flags);
374		return 0;
375	}
376
377	case WDIOC_SETTIMEOUT: {
378		int new_timeout;
379		unsigned long flags;
380		int ret  = 0;
381
382		if (get_user(new_timeout, p))
383			return -EFAULT;
384
385		spin_lock_irqsave(&ubi32_wdt_spinlock, flags);
386		ret = ubi32_wdt_set_timeout(new_timeout);
387		spin_unlock_irqrestore(&ubi32_wdt_spinlock, flags);
388		return ret;
389
390	}
391
392	case WDIOC_GETTIMEOUT:
393		return put_user(timeout, p);
394
395	case WDIOC_GETTIMELEFT: {
396		unsigned long flags;
397		int remaining = 0;
398
399		spin_lock_irqsave(&ubi32_wdt_spinlock, flags);
400		remaining = ubi32_wdt_remaining();
401		spin_unlock_irqrestore(&ubi32_wdt_spinlock, flags);
402		return put_user(remaining, p);
403	}
404
405	default:
406		return -ENOTTY;
407	}
408}
409
410/*
411 * ubi32_wdt_notify_sys()
412 *	Notification callback function for system events.
413 *
414 * Turn off the watchdog during a SYS_DOWN or SYS_HALT.
415 */
416static int ubi32_wdt_notify_sys(struct notifier_block *this,
417					unsigned long code, void *unused)
418{
419	if (code == SYS_DOWN || code == SYS_HALT) {
420		unsigned long flags;
421
422		spin_lock_irqsave(&ubi32_wdt_spinlock, flags);
423		ubi32_wdt_stop();
424		spin_unlock_irqrestore(&ubi32_wdt_spinlock, flags);
425	}
426
427	return NOTIFY_DONE;
428}
429
430#ifdef CONFIG_PM
431static int state_before_suspend;
432
433/*
434 * ubi32_wdt_suspend()
435 * 	suspend the watchdog
436 *
437 * Remember if the watchdog was running and stop it.
438 */
439static int ubi32_wdt_suspend(struct platform_device *pdev, pm_message_t state)
440{
441	unsigned long flags;
442	spin_lock_irqsave(&ubi32_wdt_spinlock, flags);
443	state_before_suspend = ubi32_wdt_running();
444	ubi32_wdt_stop();
445	spin_unlock_irqrestore(&ubi32_wdt_spinlock, flags);
446
447	return 0;
448}
449
450/*
451 * ubi32_wdt_resume()
452 * 	Resume the watchdog
453 *
454 * If the watchdog was running, turn it back on.
455 */
456static int ubi32_wdt_resume(struct platform_device *pdev)
457{
458	if (state_before_suspend) {
459		unsigned long flags;
460		spin_lock_irqsave(&ubi32_wdt_spinlock, flags);
461		ubi32_wdt_set_timeout(timeout);
462		ubi32_wdt_start();
463		spin_unlock_irqrestore(&ubi32_wdt_spinlock, flags);
464	}
465
466	return 0;
467}
468#else
469# define ubi32_wdt_suspend NULL
470# define ubi32_wdt_resume NULL
471#endif
472
473static const struct file_operations ubi32_wdt_fops = {
474	.owner		= THIS_MODULE,
475	.llseek		= no_llseek,
476	.write    	= ubi32_wdt_write,
477	.unlocked_ioctl	= ubi32_wdt_ioctl,
478	.open		= ubi32_wdt_open,
479	.release	= ubi32_wdt_release,
480};
481
482static struct miscdevice ubi32_wdt_miscdev = {
483	.minor    = WATCHDOG_MINOR,
484	.name     = "watchdog",
485	.fops     = &ubi32_wdt_fops,
486};
487
488static struct watchdog_info ubi32_wdt_info = {
489	.identity = "Ubicom32 Watchdog",
490	.options  = WDIOF_SETTIMEOUT |
491		    WDIOF_KEEPALIVEPING |
492		    WDIOF_MAGICCLOSE,
493};
494
495static struct notifier_block ubi32_wdt_notifier = {
496	.notifier_call = ubi32_wdt_notify_sys,
497};
498
499/*
500 * ubi32_wdt_probe()
501 * 	Probe/register the watchdog module
502 *
503 * Registers the misc device and notifier handler.  Actual device
504 * initialization is handled by ubi32_wdt_open().
505 */
506static int __devinit ubi32_wdt_probe(struct platform_device *pdev)
507{
508	int ret;
509
510	ret = register_reboot_notifier(&ubi32_wdt_notifier);
511	if (ret) {
512		printk(KERN_ERR PFX
513			"cannot register reboot notifier (err=%d)\n", ret);
514		return ret;
515	}
516
517	ret = misc_register(&ubi32_wdt_miscdev);
518	if (ret) {
519		printk(KERN_ERR PFX
520			"cannot register miscdev on minor=%d (err=%d)\n",
521				WATCHDOG_MINOR, ret);
522		unregister_reboot_notifier(&ubi32_wdt_notifier);
523		return ret;
524	}
525
526	printk(KERN_INFO PFX "initialized: timeout=%d sec (nowayout=%d)\n",
527	       timeout, nowayout);
528
529	return 0;
530}
531
532/*
533 * ubi32_wdt_remove()
534 * 	Uninstall the module
535 *
536 * Unregisters the misc device and notifier handler.  Actual device
537 * deinitialization is handled by ubi32_wdt_close().
538 */
539static int __devexit ubi32_wdt_remove(struct platform_device *pdev)
540{
541	misc_deregister(&ubi32_wdt_miscdev);
542	unregister_reboot_notifier(&ubi32_wdt_notifier);
543	return 0;
544}
545
546static struct platform_device *ubi32_wdt_device;
547
548static struct platform_driver ubi32_wdt_driver = {
549	.probe     = ubi32_wdt_probe,
550	.remove    = __devexit_p(ubi32_wdt_remove),
551	.suspend   = ubi32_wdt_suspend,
552	.resume    = ubi32_wdt_resume,
553	.driver    = {
554		.name  = WATCHDOG_NAME,
555		.owner = THIS_MODULE,
556	},
557};
558
559/*
560 * ubi32_wdt_init()
561 * 	Initialize the watchdog.
562 *
563 * Checks the module params and registers the platform device & driver.
564 * Real work is in the platform probe function.
565 */
566static int __init ubi32_wdt_init(void)
567{
568	unsigned long flags;
569	int ret;
570
571	/*
572	 * Check that the timeout value is within range
573	 */
574	spin_lock_irqsave(&ubi32_wdt_spinlock, flags);
575	ret = ubi32_wdt_set_timeout(timeout);
576	spin_unlock_irqrestore(&ubi32_wdt_spinlock, flags);
577	if (ret) {
578		return ret;
579	}
580
581	/*
582	 * Since this is an on-chip device and needs no board-specific
583	 * resources, we'll handle all the platform device stuff here.
584	 */
585	ret = platform_driver_register(&ubi32_wdt_driver);
586	if (ret) {
587		printk(KERN_ERR PFX "unable to register driver\n");
588		return ret;
589	}
590
591	ubi32_wdt_device = platform_device_register_simple(WATCHDOG_NAME, -1, NULL, 0);
592	if (IS_ERR(ubi32_wdt_device)) {
593		printk(KERN_ERR PFX "unable to register device\n");
594		platform_driver_unregister(&ubi32_wdt_driver);
595		return PTR_ERR(ubi32_wdt_device);
596	}
597
598	return 0;
599}
600
601/*
602 * ubi32_wdt_exit()
603 * 	Deinitialize module
604 *
605 * Back out the platform device & driver steps.  Real work is in the
606 * platform remove function.
607 */
608static void __exit ubi32_wdt_exit(void)
609{
610	platform_device_unregister(ubi32_wdt_device);
611	platform_driver_unregister(&ubi32_wdt_driver);
612}
613
614module_init(ubi32_wdt_init);
615module_exit(ubi32_wdt_exit);
616
617MODULE_AUTHOR("Sol Kavy<sol@ubicom.com>");
618MODULE_DESCRIPTION("Ubicom32 Watchdog Device Driver");
619MODULE_LICENSE("GPL");
620MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
621
622module_param(timeout, uint, 0);
623MODULE_PARM_DESC(timeout,
624	"Watchdog timeout in seconds. (1<=timeout<=((2^32)/SCLK), default="
625		__MODULE_STRING(WATCHDOG_TIMEOUT) ")");
626
627module_param(nowayout, int, 0);
628MODULE_PARM_DESC(nowayout,
629	"Watchdog cannot be stopped once started (default="
630		__MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
631