Linux Audio

Check our new training course

Loading...
v3.1
 
  1/*
  2 * drivers/watchdog/shwdt.c
  3 *
  4 * Watchdog driver for integrated watchdog in the SuperH processors.
  5 *
  6 * Copyright (C) 2001 - 2010  Paul Mundt <lethal@linux-sh.org>
  7 *
  8 * This program is free software; you can redistribute it and/or modify it
  9 * under the terms of the GNU General Public License as published by the
 10 * Free Software Foundation; either version 2 of the License, or (at your
 11 * option) any later version.
 12 *
 13 * 14-Dec-2001 Matt Domsch <Matt_Domsch@dell.com>
 14 *     Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
 15 *
 16 * 19-Apr-2002 Rob Radez <rob@osinvestor.com>
 17 *     Added expect close support, made emulated timeout runtime changeable
 18 *     general cleanups, add some ioctls
 19 */
 
 
 
 20#include <linux/module.h>
 21#include <linux/moduleparam.h>
 22#include <linux/platform_device.h>
 23#include <linux/init.h>
 24#include <linux/types.h>
 25#include <linux/miscdevice.h>
 26#include <linux/watchdog.h>
 27#include <linux/reboot.h>
 28#include <linux/notifier.h>
 29#include <linux/ioport.h>
 30#include <linux/fs.h>
 31#include <linux/mm.h>
 32#include <linux/slab.h>
 33#include <linux/io.h>
 34#include <linux/uaccess.h>
 
 35#include <asm/watchdog.h>
 36
 37#define DRV_NAME "sh-wdt"
 38
 39/*
 40 * Default clock division ratio is 5.25 msecs. For an additional table of
 41 * values, consult the asm-sh/watchdog.h. Overload this at module load
 42 * time.
 43 *
 44 * In order for this to work reliably we need to have HZ set to 1000 or
 45 * something quite higher than 100 (or we need a proper high-res timer
 46 * implementation that will deal with this properly), otherwise the 10ms
 47 * resolution of a jiffy is enough to trigger the overflow. For things like
 48 * the SH-4 and SH-5, this isn't necessarily that big of a problem, though
 49 * for the SH-2 and SH-3, this isn't recommended unless the WDT is absolutely
 50 * necssary.
 51 *
 52 * As a result of this timing problem, the only modes that are particularly
 53 * feasible are the 4096 and the 2048 divisors, which yield 5.25 and 2.62ms
 54 * overflow periods respectively.
 55 *
 56 * Also, since we can't really expect userspace to be responsive enough
 57 * before the overflow happens, we maintain two separate timers .. One in
 58 * the kernel for clearing out WOVF every 2ms or so (again, this depends on
 59 * HZ == 1000), and another for monitoring userspace writes to the WDT device.
 60 *
 61 * As such, we currently use a configurable heartbeat interval which defaults
 62 * to 30s. In this case, the userspace daemon is only responsible for periodic
 63 * writes to the device before the next heartbeat is scheduled. If the daemon
 64 * misses its deadline, the kernel timer will allow the WDT to overflow.
 65 */
 66static int clock_division_ratio = WTCSR_CKS_4096;
 67#define next_ping_period(cks)	(jiffies + msecs_to_jiffies(cks - 4))
 68
 69static const struct watchdog_info sh_wdt_info;
 70static struct platform_device *sh_wdt_dev;
 71static DEFINE_SPINLOCK(shwdt_lock);
 72
 73#define WATCHDOG_HEARTBEAT 30			/* 30 sec default heartbeat */
 74static int heartbeat = WATCHDOG_HEARTBEAT;	/* in seconds */
 75static int nowayout = WATCHDOG_NOWAYOUT;
 76static unsigned long next_heartbeat;
 77
 78struct sh_wdt {
 79	void __iomem		*base;
 80	struct device		*dev;
 
 
 81
 82	struct timer_list	timer;
 83
 84	unsigned long		enabled;
 85	char			expect_close;
 86};
 87
 88static void sh_wdt_start(struct sh_wdt *wdt)
 89{
 
 90	unsigned long flags;
 91	u8 csr;
 92
 93	spin_lock_irqsave(&shwdt_lock, flags);
 
 
 
 94
 95	next_heartbeat = jiffies + (heartbeat * HZ);
 96	mod_timer(&wdt->timer, next_ping_period(clock_division_ratio));
 97
 98	csr = sh_wdt_read_csr();
 99	csr |= WTCSR_WT | clock_division_ratio;
100	sh_wdt_write_csr(csr);
101
102	sh_wdt_write_cnt(0);
103
104	/*
105	 * These processors have a bit of an inconsistent initialization
106	 * process.. starting with SH-3, RSTS was moved to WTCSR, and the
107	 * RSTCSR register was removed.
108	 *
109	 * On the SH-2 however, in addition with bits being in different
110	 * locations, we must deal with RSTCSR outright..
111	 */
112	csr = sh_wdt_read_csr();
113	csr |= WTCSR_TME;
114	csr &= ~WTCSR_RSTS;
115	sh_wdt_write_csr(csr);
116
117#ifdef CONFIG_CPU_SH2
118	csr = sh_wdt_read_rstcsr();
119	csr &= ~RSTCSR_RSTS;
120	sh_wdt_write_rstcsr(csr);
121#endif
122	spin_unlock_irqrestore(&shwdt_lock, flags);
 
 
123}
124
125static void sh_wdt_stop(struct sh_wdt *wdt)
126{
 
127	unsigned long flags;
128	u8 csr;
129
130	spin_lock_irqsave(&shwdt_lock, flags);
131
132	del_timer(&wdt->timer);
133
134	csr = sh_wdt_read_csr();
135	csr &= ~WTCSR_TME;
136	sh_wdt_write_csr(csr);
137
138	spin_unlock_irqrestore(&shwdt_lock, flags);
 
 
 
 
 
139}
140
141static inline void sh_wdt_keepalive(struct sh_wdt *wdt)
142{
 
143	unsigned long flags;
144
145	spin_lock_irqsave(&shwdt_lock, flags);
146	next_heartbeat = jiffies + (heartbeat * HZ);
147	spin_unlock_irqrestore(&shwdt_lock, flags);
 
 
148}
149
150static int sh_wdt_set_heartbeat(int t)
151{
 
152	unsigned long flags;
153
154	if (unlikely(t < 1 || t > 3600)) /* arbitrary upper limit */
155		return -EINVAL;
156
157	spin_lock_irqsave(&shwdt_lock, flags);
158	heartbeat = t;
159	spin_unlock_irqrestore(&shwdt_lock, flags);
 
 
160	return 0;
161}
162
163static void sh_wdt_ping(unsigned long data)
164{
165	struct sh_wdt *wdt = (struct sh_wdt *)data;
166	unsigned long flags;
167
168	spin_lock_irqsave(&shwdt_lock, flags);
169	if (time_before(jiffies, next_heartbeat)) {
170		u8 csr;
171
172		csr = sh_wdt_read_csr();
173		csr &= ~WTCSR_IOVF;
174		sh_wdt_write_csr(csr);
175
176		sh_wdt_write_cnt(0);
177
178		mod_timer(&wdt->timer, next_ping_period(clock_division_ratio));
179	} else
180		dev_warn(wdt->dev, "Heartbeat lost! Will not ping "
181		         "the watchdog\n");
182	spin_unlock_irqrestore(&shwdt_lock, flags);
183}
184
185static int sh_wdt_open(struct inode *inode, struct file *file)
186{
187	struct sh_wdt *wdt = platform_get_drvdata(sh_wdt_dev);
188
189	if (test_and_set_bit(0, &wdt->enabled))
190		return -EBUSY;
191	if (nowayout)
192		__module_get(THIS_MODULE);
193
194	file->private_data = wdt;
195
196	sh_wdt_start(wdt);
197
198	return nonseekable_open(inode, file);
199}
200
201static int sh_wdt_close(struct inode *inode, struct file *file)
202{
203	struct sh_wdt *wdt = file->private_data;
204
205	if (wdt->expect_close == 42) {
206		sh_wdt_stop(wdt);
207	} else {
208		dev_crit(wdt->dev, "Unexpected close, not "
209		         "stopping watchdog!\n");
210		sh_wdt_keepalive(wdt);
211	}
212
213	clear_bit(0, &wdt->enabled);
214	wdt->expect_close = 0;
215
216	return 0;
217}
218
219static ssize_t sh_wdt_write(struct file *file, const char *buf,
220			    size_t count, loff_t *ppos)
221{
222	struct sh_wdt *wdt = file->private_data;
223
224	if (count) {
225		if (!nowayout) {
226			size_t i;
227
228			wdt->expect_close = 0;
229
230			for (i = 0; i != count; i++) {
231				char c;
232				if (get_user(c, buf + i))
233					return -EFAULT;
234				if (c == 'V')
235					wdt->expect_close = 42;
236			}
237		}
238		sh_wdt_keepalive(wdt);
239	}
240
241	return count;
242}
243
244static long sh_wdt_ioctl(struct file *file, unsigned int cmd,
245							unsigned long arg)
246{
247	struct sh_wdt *wdt = file->private_data;
248	int new_heartbeat;
249	int options, retval = -EINVAL;
250
251	switch (cmd) {
252	case WDIOC_GETSUPPORT:
253		return copy_to_user((struct watchdog_info *)arg,
254			  &sh_wdt_info, sizeof(sh_wdt_info)) ? -EFAULT : 0;
255	case WDIOC_GETSTATUS:
256	case WDIOC_GETBOOTSTATUS:
257		return put_user(0, (int *)arg);
258	case WDIOC_SETOPTIONS:
259		if (get_user(options, (int *)arg))
260			return -EFAULT;
261
262		if (options & WDIOS_DISABLECARD) {
263			sh_wdt_stop(wdt);
264			retval = 0;
265		}
266
267		if (options & WDIOS_ENABLECARD) {
268			sh_wdt_start(wdt);
269			retval = 0;
270		}
271
272		return retval;
273	case WDIOC_KEEPALIVE:
274		sh_wdt_keepalive(wdt);
275		return 0;
276	case WDIOC_SETTIMEOUT:
277		if (get_user(new_heartbeat, (int *)arg))
278			return -EFAULT;
279
280		if (sh_wdt_set_heartbeat(new_heartbeat))
281			return -EINVAL;
282
283		sh_wdt_keepalive(wdt);
284		/* Fall */
285	case WDIOC_GETTIMEOUT:
286		return put_user(heartbeat, (int *)arg);
287	default:
288		return -ENOTTY;
289	}
290	return 0;
291}
292
293static int sh_wdt_notify_sys(struct notifier_block *this,
294			     unsigned long code, void *unused)
295{
296	struct sh_wdt *wdt = platform_get_drvdata(sh_wdt_dev);
297
298	if (code == SYS_DOWN || code == SYS_HALT)
299		sh_wdt_stop(wdt);
300
301	return NOTIFY_DONE;
302}
303
304static const struct file_operations sh_wdt_fops = {
305	.owner		= THIS_MODULE,
306	.llseek		= no_llseek,
307	.write		= sh_wdt_write,
308	.unlocked_ioctl	= sh_wdt_ioctl,
309	.open		= sh_wdt_open,
310	.release	= sh_wdt_close,
311};
312
313static const struct watchdog_info sh_wdt_info = {
314	.options		= WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT |
315				  WDIOF_MAGICCLOSE,
316	.firmware_version	= 1,
317	.identity		= "SH WDT",
318};
319
320static struct notifier_block sh_wdt_notifier = {
321	.notifier_call		= sh_wdt_notify_sys,
 
 
 
 
322};
323
324static struct miscdevice sh_wdt_miscdev = {
325	.minor		= WATCHDOG_MINOR,
326	.name		= "watchdog",
327	.fops		= &sh_wdt_fops,
328};
329
330static int __devinit sh_wdt_probe(struct platform_device *pdev)
331{
332	struct sh_wdt *wdt;
333	struct resource *res;
334	int rc;
335
336	/*
337	 * As this driver only covers the global watchdog case, reject
338	 * any attempts to register per-CPU watchdogs.
339	 */
340	if (pdev->id != -1)
341		return -EINVAL;
342
343	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
344	if (unlikely(!res))
345		return -EINVAL;
346
347	if (!devm_request_mem_region(&pdev->dev, res->start,
348				     resource_size(res), DRV_NAME))
349		return -EBUSY;
350
351	wdt = devm_kzalloc(&pdev->dev, sizeof(struct sh_wdt), GFP_KERNEL);
352	if (unlikely(!wdt)) {
353		rc = -ENOMEM;
354		goto out_release;
355	}
356
357	wdt->dev = &pdev->dev;
358
359	wdt->base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
360	if (unlikely(!wdt->base)) {
361		rc = -ENXIO;
362		goto out_err;
 
 
 
363	}
364
365	rc = register_reboot_notifier(&sh_wdt_notifier);
 
 
 
 
 
 
 
 
 
 
366	if (unlikely(rc)) {
367		dev_err(&pdev->dev,
368			"Can't register reboot notifier (err=%d)\n", rc);
369		goto out_unmap;
 
 
 
370	}
371
372	sh_wdt_miscdev.parent = wdt->dev;
 
373
374	rc = misc_register(&sh_wdt_miscdev);
375	if (unlikely(rc)) {
376		dev_err(&pdev->dev,
377			"Can't register miscdev on minor=%d (err=%d)\n",
378						sh_wdt_miscdev.minor, rc);
379		goto out_unreg;
380	}
381
382	init_timer(&wdt->timer);
383	wdt->timer.function	= sh_wdt_ping;
384	wdt->timer.data		= (unsigned long)wdt;
385	wdt->timer.expires	= next_ping_period(clock_division_ratio);
386
387	platform_set_drvdata(pdev, wdt);
388	sh_wdt_dev = pdev;
389
390	dev_info(&pdev->dev, "initialized.\n");
391
392	return 0;
393
394out_unreg:
395	unregister_reboot_notifier(&sh_wdt_notifier);
396out_unmap:
397	devm_iounmap(&pdev->dev, wdt->base);
398out_err:
399	devm_kfree(&pdev->dev, wdt);
400out_release:
401	devm_release_mem_region(&pdev->dev, res->start, resource_size(res));
402
403	return rc;
404}
405
406static int __devexit sh_wdt_remove(struct platform_device *pdev)
407{
408	struct sh_wdt *wdt = platform_get_drvdata(pdev);
409	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
410
411	platform_set_drvdata(pdev, NULL);
412
413	misc_deregister(&sh_wdt_miscdev);
414
415	sh_wdt_dev = NULL;
416
417	unregister_reboot_notifier(&sh_wdt_notifier);
418	devm_release_mem_region(&pdev->dev, res->start, resource_size(res));
419	devm_iounmap(&pdev->dev, wdt->base);
420	devm_kfree(&pdev->dev, wdt);
421
422	return 0;
423}
424
 
 
 
 
 
425static struct platform_driver sh_wdt_driver = {
426	.driver		= {
427		.name	= DRV_NAME,
428		.owner	= THIS_MODULE,
429	},
430
431	.probe	= sh_wdt_probe,
432	.remove	= __devexit_p(sh_wdt_remove),
 
433};
434
435static int __init sh_wdt_init(void)
436{
437	int rc;
438
439	if (unlikely(clock_division_ratio < 0x5 ||
440		     clock_division_ratio > 0x7)) {
441		clock_division_ratio = WTCSR_CKS_4096;
442
443		pr_info("%s: divisor must be 0x5<=x<=0x7, using %d\n",
444			 DRV_NAME, clock_division_ratio);
445	}
446
447	rc = sh_wdt_set_heartbeat(heartbeat);
448	if (unlikely(rc)) {
449		heartbeat = WATCHDOG_HEARTBEAT;
450
451		pr_info("%s: heartbeat value must be 1<=x<=3600, using %d\n",
452			DRV_NAME, heartbeat);
453	}
454
455	pr_info("%s: configured with heartbeat=%d sec (nowayout=%d)\n",
456		DRV_NAME, heartbeat, nowayout);
457
458	return platform_driver_register(&sh_wdt_driver);
459}
460
461static void __exit sh_wdt_exit(void)
462{
463	platform_driver_unregister(&sh_wdt_driver);
464}
465module_init(sh_wdt_init);
466module_exit(sh_wdt_exit);
467
468MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>");
469MODULE_DESCRIPTION("SuperH watchdog driver");
470MODULE_LICENSE("GPL");
471MODULE_ALIAS("platform:" DRV_NAME);
472MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
473
474module_param(clock_division_ratio, int, 0);
475MODULE_PARM_DESC(clock_division_ratio,
476	"Clock division ratio. Valid ranges are from 0x5 (1.31ms) "
477	"to 0x7 (5.25ms). (default=" __MODULE_STRING(WTCSR_CKS_4096) ")");
478
479module_param(heartbeat, int, 0);
480MODULE_PARM_DESC(heartbeat,
481	"Watchdog heartbeat in seconds. (1 <= heartbeat <= 3600, default="
482				__MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
483
484module_param(nowayout, int, 0);
485MODULE_PARM_DESC(nowayout,
486	"Watchdog cannot be stopped once started (default="
487				__MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
v5.9
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2/*
  3 * drivers/watchdog/shwdt.c
  4 *
  5 * Watchdog driver for integrated watchdog in the SuperH processors.
  6 *
  7 * Copyright (C) 2001 - 2012  Paul Mundt <lethal@linux-sh.org>
 
 
 
 
 
  8 *
  9 * 14-Dec-2001 Matt Domsch <Matt_Domsch@dell.com>
 10 *     Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
 11 *
 12 * 19-Apr-2002 Rob Radez <rob@osinvestor.com>
 13 *     Added expect close support, made emulated timeout runtime changeable
 14 *     general cleanups, add some ioctls
 15 */
 16
 17#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 18
 19#include <linux/module.h>
 20#include <linux/moduleparam.h>
 21#include <linux/platform_device.h>
 22#include <linux/init.h>
 23#include <linux/types.h>
 24#include <linux/spinlock.h>
 25#include <linux/watchdog.h>
 26#include <linux/pm_runtime.h>
 
 
 27#include <linux/fs.h>
 28#include <linux/mm.h>
 29#include <linux/slab.h>
 30#include <linux/io.h>
 31#include <linux/clk.h>
 32#include <linux/err.h>
 33#include <asm/watchdog.h>
 34
 35#define DRV_NAME "sh-wdt"
 36
 37/*
 38 * Default clock division ratio is 5.25 msecs. For an additional table of
 39 * values, consult the asm-sh/watchdog.h. Overload this at module load
 40 * time.
 41 *
 42 * In order for this to work reliably we need to have HZ set to 1000 or
 43 * something quite higher than 100 (or we need a proper high-res timer
 44 * implementation that will deal with this properly), otherwise the 10ms
 45 * resolution of a jiffy is enough to trigger the overflow. For things like
 46 * the SH-4 and SH-5, this isn't necessarily that big of a problem, though
 47 * for the SH-2 and SH-3, this isn't recommended unless the WDT is absolutely
 48 * necssary.
 49 *
 50 * As a result of this timing problem, the only modes that are particularly
 51 * feasible are the 4096 and the 2048 divisors, which yield 5.25 and 2.62ms
 52 * overflow periods respectively.
 53 *
 54 * Also, since we can't really expect userspace to be responsive enough
 55 * before the overflow happens, we maintain two separate timers .. One in
 56 * the kernel for clearing out WOVF every 2ms or so (again, this depends on
 57 * HZ == 1000), and another for monitoring userspace writes to the WDT device.
 58 *
 59 * As such, we currently use a configurable heartbeat interval which defaults
 60 * to 30s. In this case, the userspace daemon is only responsible for periodic
 61 * writes to the device before the next heartbeat is scheduled. If the daemon
 62 * misses its deadline, the kernel timer will allow the WDT to overflow.
 63 */
 64static int clock_division_ratio = WTCSR_CKS_4096;
 65#define next_ping_period(cks)	(jiffies + msecs_to_jiffies(cks - 4))
 66
 
 
 
 
 67#define WATCHDOG_HEARTBEAT 30			/* 30 sec default heartbeat */
 68static int heartbeat = WATCHDOG_HEARTBEAT;	/* in seconds */
 69static bool nowayout = WATCHDOG_NOWAYOUT;
 70static unsigned long next_heartbeat;
 71
 72struct sh_wdt {
 73	void __iomem		*base;
 74	struct device		*dev;
 75	struct clk		*clk;
 76	spinlock_t		lock;
 77
 78	struct timer_list	timer;
 
 
 
 79};
 80
 81static int sh_wdt_start(struct watchdog_device *wdt_dev)
 82{
 83	struct sh_wdt *wdt = watchdog_get_drvdata(wdt_dev);
 84	unsigned long flags;
 85	u8 csr;
 86
 87	pm_runtime_get_sync(wdt->dev);
 88	clk_enable(wdt->clk);
 89
 90	spin_lock_irqsave(&wdt->lock, flags);
 91
 92	next_heartbeat = jiffies + (heartbeat * HZ);
 93	mod_timer(&wdt->timer, next_ping_period(clock_division_ratio));
 94
 95	csr = sh_wdt_read_csr();
 96	csr |= WTCSR_WT | clock_division_ratio;
 97	sh_wdt_write_csr(csr);
 98
 99	sh_wdt_write_cnt(0);
100
101	/*
102	 * These processors have a bit of an inconsistent initialization
103	 * process.. starting with SH-3, RSTS was moved to WTCSR, and the
104	 * RSTCSR register was removed.
105	 *
106	 * On the SH-2 however, in addition with bits being in different
107	 * locations, we must deal with RSTCSR outright..
108	 */
109	csr = sh_wdt_read_csr();
110	csr |= WTCSR_TME;
111	csr &= ~WTCSR_RSTS;
112	sh_wdt_write_csr(csr);
113
114#ifdef CONFIG_CPU_SH2
115	csr = sh_wdt_read_rstcsr();
116	csr &= ~RSTCSR_RSTS;
117	sh_wdt_write_rstcsr(csr);
118#endif
119	spin_unlock_irqrestore(&wdt->lock, flags);
120
121	return 0;
122}
123
124static int sh_wdt_stop(struct watchdog_device *wdt_dev)
125{
126	struct sh_wdt *wdt = watchdog_get_drvdata(wdt_dev);
127	unsigned long flags;
128	u8 csr;
129
130	spin_lock_irqsave(&wdt->lock, flags);
131
132	del_timer(&wdt->timer);
133
134	csr = sh_wdt_read_csr();
135	csr &= ~WTCSR_TME;
136	sh_wdt_write_csr(csr);
137
138	spin_unlock_irqrestore(&wdt->lock, flags);
139
140	clk_disable(wdt->clk);
141	pm_runtime_put_sync(wdt->dev);
142
143	return 0;
144}
145
146static int sh_wdt_keepalive(struct watchdog_device *wdt_dev)
147{
148	struct sh_wdt *wdt = watchdog_get_drvdata(wdt_dev);
149	unsigned long flags;
150
151	spin_lock_irqsave(&wdt->lock, flags);
152	next_heartbeat = jiffies + (heartbeat * HZ);
153	spin_unlock_irqrestore(&wdt->lock, flags);
154
155	return 0;
156}
157
158static int sh_wdt_set_heartbeat(struct watchdog_device *wdt_dev, unsigned t)
159{
160	struct sh_wdt *wdt = watchdog_get_drvdata(wdt_dev);
161	unsigned long flags;
162
163	if (unlikely(t < 1 || t > 3600)) /* arbitrary upper limit */
164		return -EINVAL;
165
166	spin_lock_irqsave(&wdt->lock, flags);
167	heartbeat = t;
168	wdt_dev->timeout = t;
169	spin_unlock_irqrestore(&wdt->lock, flags);
170
171	return 0;
172}
173
174static void sh_wdt_ping(struct timer_list *t)
175{
176	struct sh_wdt *wdt = from_timer(wdt, t, timer);
177	unsigned long flags;
178
179	spin_lock_irqsave(&wdt->lock, flags);
180	if (time_before(jiffies, next_heartbeat)) {
181		u8 csr;
182
183		csr = sh_wdt_read_csr();
184		csr &= ~WTCSR_IOVF;
185		sh_wdt_write_csr(csr);
186
187		sh_wdt_write_cnt(0);
188
189		mod_timer(&wdt->timer, next_ping_period(clock_division_ratio));
190	} else
191		dev_warn(wdt->dev, "Heartbeat lost! Will not ping "
192		         "the watchdog\n");
193	spin_unlock_irqrestore(&wdt->lock, flags);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
194}
195
 
 
 
 
 
 
 
 
 
196static const struct watchdog_info sh_wdt_info = {
197	.options		= WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT |
198				  WDIOF_MAGICCLOSE,
199	.firmware_version	= 1,
200	.identity		= "SH WDT",
201};
202
203static const struct watchdog_ops sh_wdt_ops = {
204	.owner		= THIS_MODULE,
205	.start		= sh_wdt_start,
206	.stop		= sh_wdt_stop,
207	.ping		= sh_wdt_keepalive,
208	.set_timeout	= sh_wdt_set_heartbeat,
209};
210
211static struct watchdog_device sh_wdt_dev = {
212	.info	= &sh_wdt_info,
213	.ops	= &sh_wdt_ops,
 
214};
215
216static int sh_wdt_probe(struct platform_device *pdev)
217{
218	struct sh_wdt *wdt;
 
219	int rc;
220
221	/*
222	 * As this driver only covers the global watchdog case, reject
223	 * any attempts to register per-CPU watchdogs.
224	 */
225	if (pdev->id != -1)
226		return -EINVAL;
227
 
 
 
 
 
 
 
 
228	wdt = devm_kzalloc(&pdev->dev, sizeof(struct sh_wdt), GFP_KERNEL);
229	if (unlikely(!wdt))
230		return -ENOMEM;
 
 
231
232	wdt->dev = &pdev->dev;
233
234	wdt->clk = devm_clk_get(&pdev->dev, NULL);
235	if (IS_ERR(wdt->clk)) {
236		/*
237		 * Clock framework support is optional, continue on
238		 * anyways if we don't find a matching clock.
239		 */
240		wdt->clk = NULL;
241	}
242
243	wdt->base = devm_platform_ioremap_resource(pdev, 0);
244	if (IS_ERR(wdt->base))
245		return PTR_ERR(wdt->base);
246
247	watchdog_set_nowayout(&sh_wdt_dev, nowayout);
248	watchdog_set_drvdata(&sh_wdt_dev, wdt);
249	sh_wdt_dev.parent = &pdev->dev;
250
251	spin_lock_init(&wdt->lock);
252
253	rc = sh_wdt_set_heartbeat(&sh_wdt_dev, heartbeat);
254	if (unlikely(rc)) {
255		/* Default timeout if invalid */
256		sh_wdt_set_heartbeat(&sh_wdt_dev, WATCHDOG_HEARTBEAT);
257
258		dev_warn(&pdev->dev,
259			 "heartbeat value must be 1<=x<=3600, using %d\n",
260			 sh_wdt_dev.timeout);
261	}
262
263	dev_info(&pdev->dev, "configured with heartbeat=%d sec (nowayout=%d)\n",
264		 sh_wdt_dev.timeout, nowayout);
265
266	rc = watchdog_register_device(&sh_wdt_dev);
267	if (unlikely(rc)) {
268		dev_err(&pdev->dev, "Can't register watchdog (err=%d)\n", rc);
269		return rc;
 
 
270	}
271
272	timer_setup(&wdt->timer, sh_wdt_ping, 0);
 
 
273	wdt->timer.expires	= next_ping_period(clock_division_ratio);
274
 
 
 
275	dev_info(&pdev->dev, "initialized.\n");
276
277	pm_runtime_enable(&pdev->dev);
278
279	return 0;
 
 
 
 
 
 
 
 
 
280}
281
282static int sh_wdt_remove(struct platform_device *pdev)
283{
284	watchdog_unregister_device(&sh_wdt_dev);
 
285
286	pm_runtime_disable(&pdev->dev);
 
 
 
 
 
 
 
 
 
287
288	return 0;
289}
290
291static void sh_wdt_shutdown(struct platform_device *pdev)
292{
293	sh_wdt_stop(&sh_wdt_dev);
294}
295
296static struct platform_driver sh_wdt_driver = {
297	.driver		= {
298		.name	= DRV_NAME,
 
299	},
300
301	.probe		= sh_wdt_probe,
302	.remove		= sh_wdt_remove,
303	.shutdown	= sh_wdt_shutdown,
304};
305
306static int __init sh_wdt_init(void)
307{
 
 
308	if (unlikely(clock_division_ratio < 0x5 ||
309		     clock_division_ratio > 0x7)) {
310		clock_division_ratio = WTCSR_CKS_4096;
311
312		pr_info("divisor must be 0x5<=x<=0x7, using %d\n",
313			clock_division_ratio);
314	}
315
 
 
 
 
 
 
 
 
 
 
 
316	return platform_driver_register(&sh_wdt_driver);
317}
318
319static void __exit sh_wdt_exit(void)
320{
321	platform_driver_unregister(&sh_wdt_driver);
322}
323module_init(sh_wdt_init);
324module_exit(sh_wdt_exit);
325
326MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>");
327MODULE_DESCRIPTION("SuperH watchdog driver");
328MODULE_LICENSE("GPL");
329MODULE_ALIAS("platform:" DRV_NAME);
 
330
331module_param(clock_division_ratio, int, 0);
332MODULE_PARM_DESC(clock_division_ratio,
333	"Clock division ratio. Valid ranges are from 0x5 (1.31ms) "
334	"to 0x7 (5.25ms). (default=" __MODULE_STRING(WTCSR_CKS_4096) ")");
335
336module_param(heartbeat, int, 0);
337MODULE_PARM_DESC(heartbeat,
338	"Watchdog heartbeat in seconds. (1 <= heartbeat <= 3600, default="
339				__MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
340
341module_param(nowayout, bool, 0);
342MODULE_PARM_DESC(nowayout,
343	"Watchdog cannot be stopped once started (default="
344				__MODULE_STRING(WATCHDOG_NOWAYOUT) ")");