Blame view

drivers/watchdog/sa1100_wdt.c 4.64 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
  /*
   *	Watchdog driver for the SA11x0/PXA2xx
   *
143a2e54b   Wim Van Sebroeck   [WATCHDOG] More c...
4
5
   *	(c) Copyright 2000 Oleg Drokin <green@crimea.edu>
   *	    Based on SoftDog driver by Alan Cox <alan@lxorguk.ukuu.org.uk>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6
7
8
9
10
11
12
13
14
15
16
17
   *
   *	This program is free software; you can redistribute it and/or
   *	modify it under the terms of the GNU General Public License
   *	as published by the Free Software Foundation; either version
   *	2 of the License, or (at your option) any later version.
   *
   *	Neither Oleg Drokin nor iXcelerator.com admit liability nor provide
   *	warranty for any of this software. This material is provided
   *	"AS-IS" and at no charge.
   *
   *	(c) Copyright 2000           Oleg Drokin <green@crimea.edu>
   *
143a2e54b   Wim Van Sebroeck   [WATCHDOG] More c...
18
   *	27/11/2000 Initial release
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
19
   */
27c766aaa   Joe Perches   watchdog: Use pr_...
20
21
  
  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
22
23
24
25
26
27
28
29
  #include <linux/module.h>
  #include <linux/moduleparam.h>
  #include <linux/types.h>
  #include <linux/kernel.h>
  #include <linux/fs.h>
  #include <linux/miscdevice.h>
  #include <linux/watchdog.h>
  #include <linux/init.h>
23019a733   Rob Herring   ARM: pxa: use com...
30
  #include <linux/io.h>
1977f0327   Jiri Slaby   remove asm/bitops...
31
  #include <linux/bitops.h>
f19e03126   Alan Cox   [WATCHDOG 36/57] ...
32
  #include <linux/uaccess.h>
87c52578b   Russell King   [ARM] Remove linu...
33
  #include <linux/timex.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
34
35
  
  #ifdef CONFIG_ARCH_PXA
5bf3df3f0   Eric Miao   [ARM] pxa: separa...
36
  #include <mach/regs-ost.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
37
  #endif
afd2fc02a   Russell King   Merge branch 'for...
38
  #include <mach/reset.h>
a09e64fbc   Russell King   [ARM] Move includ...
39
  #include <mach/hardware.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
40

28a623855   Eric Miao   [ARM] sa1100_wdt:...
41
  static unsigned long oscr_freq;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
42
  static unsigned long sa1100wdt_users;
a6f052e39   Raphael Assenat   [WATCHDOG] SA1100...
43
  static unsigned int pre_margin;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
44
  static int boot_status;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
45
46
47
48
49
50
  
  /*
   *	Allow only one person to hold it open
   */
  static int sa1100dog_open(struct inode *inode, struct file *file)
  {
f19e03126   Alan Cox   [WATCHDOG 36/57] ...
51
  	if (test_and_set_bit(1, &sa1100wdt_users))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
52
53
54
  		return -EBUSY;
  
  	/* Activate SA1100 Watchdog timer */
3169663ac   Russell King   ARM: sa11x0/pxa: ...
55
56
57
58
  	writel_relaxed(readl_relaxed(OSCR) + pre_margin, OSMR3);
  	writel_relaxed(OSSR_M3, OSSR);
  	writel_relaxed(OWER_WME, OWER);
  	writel_relaxed(readl_relaxed(OIER) | OIER_E3, OIER);
6abe78bf1   Wim Van Sebroeck   [WATCHDOG] Return...
59
  	return nonseekable_open(inode, file);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
60
61
62
  }
  
  /*
9bbd03758   Ian Campbell   [PATCH] ARM: 2833...
63
64
65
66
67
   * The watchdog cannot be disabled.
   *
   * Previous comments suggested that turning off the interrupt by
   * clearing OIER[E3] would prevent the watchdog timing out but this
   * does not appear to be true (at least on the PXA255).
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
68
69
70
   */
  static int sa1100dog_release(struct inode *inode, struct file *file)
  {
27c766aaa   Joe Perches   watchdog: Use pr_...
71
72
  	pr_crit("Device closed - timer will not stop
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
73
  	clear_bit(1, &sa1100wdt_users);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
74
75
  	return 0;
  }
f19e03126   Alan Cox   [WATCHDOG 36/57] ...
76
77
  static ssize_t sa1100dog_write(struct file *file, const char __user *data,
  						size_t len, loff_t *ppos)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
78
  {
9bbd03758   Ian Campbell   [PATCH] ARM: 2833...
79
  	if (len)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
80
  		/* Refresh OSMR3 timer. */
3169663ac   Russell King   ARM: sa11x0/pxa: ...
81
  		writel_relaxed(readl_relaxed(OSCR) + pre_margin, OSMR3);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
82
83
  	return len;
  }
f19e03126   Alan Cox   [WATCHDOG 36/57] ...
84
85
86
  static const struct watchdog_info ident = {
  	.options	= WDIOF_CARDRESET | WDIOF_SETTIMEOUT
  				| WDIOF_KEEPALIVEPING,
9bbd03758   Ian Campbell   [PATCH] ARM: 2833...
87
  	.identity	= "SA1100/PXA255 Watchdog",
a6f052e39   Raphael Assenat   [WATCHDOG] SA1100...
88
  	.firmware_version	= 1,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
89
  };
f19e03126   Alan Cox   [WATCHDOG 36/57] ...
90
91
  static long sa1100dog_ioctl(struct file *file, unsigned int cmd,
  							unsigned long arg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
92
  {
795b89d20   Samuel Tardieu   [WATCHDOG] use EN...
93
  	int ret = -ENOTTY;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
94
  	int time;
3a69e5791   Ian Campbell   [WATCHDOG] sa1100...
95
96
  	void __user *argp = (void __user *)arg;
  	int __user *p = argp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
97
98
99
  
  	switch (cmd) {
  	case WDIOC_GETSUPPORT:
3a69e5791   Ian Campbell   [WATCHDOG] sa1100...
100
  		ret = copy_to_user(argp, &ident,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
101
102
103
104
  				   sizeof(ident)) ? -EFAULT : 0;
  		break;
  
  	case WDIOC_GETSTATUS:
3a69e5791   Ian Campbell   [WATCHDOG] sa1100...
105
  		ret = put_user(0, p);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
106
107
108
  		break;
  
  	case WDIOC_GETBOOTSTATUS:
3a69e5791   Ian Campbell   [WATCHDOG] sa1100...
109
  		ret = put_user(boot_status, p);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
110
  		break;
0c06090c9   Wim Van Sebroeck   [WATCHDOG] Coding...
111
  	case WDIOC_KEEPALIVE:
3169663ac   Russell King   ARM: sa11x0/pxa: ...
112
  		writel_relaxed(readl_relaxed(OSCR) + pre_margin, OSMR3);
0c06090c9   Wim Van Sebroeck   [WATCHDOG] Coding...
113
114
  		ret = 0;
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
115
  	case WDIOC_SETTIMEOUT:
3a69e5791   Ian Campbell   [WATCHDOG] sa1100...
116
  		ret = get_user(time, p);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
117
118
  		if (ret)
  			break;
a6f052e39   Raphael Assenat   [WATCHDOG] SA1100...
119
  		if (time <= 0 || (oscr_freq * (long long)time >= 0xffffffff)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
120
121
122
  			ret = -EINVAL;
  			break;
  		}
28a623855   Eric Miao   [ARM] sa1100_wdt:...
123
  		pre_margin = oscr_freq * time;
3169663ac   Russell King   ARM: sa11x0/pxa: ...
124
  		writel_relaxed(readl_relaxed(OSCR) + pre_margin, OSMR3);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
125
126
127
  		/*fall through*/
  
  	case WDIOC_GETTIMEOUT:
28a623855   Eric Miao   [ARM] sa1100_wdt:...
128
  		ret = put_user(pre_margin / oscr_freq, p);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
129
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
130
131
132
  	}
  	return ret;
  }
f19e03126   Alan Cox   [WATCHDOG 36/57] ...
133
  static const struct file_operations sa1100dog_fops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
134
135
136
  	.owner		= THIS_MODULE,
  	.llseek		= no_llseek,
  	.write		= sa1100dog_write,
f19e03126   Alan Cox   [WATCHDOG 36/57] ...
137
  	.unlocked_ioctl	= sa1100dog_ioctl,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
138
139
140
  	.open		= sa1100dog_open,
  	.release	= sa1100dog_release,
  };
f19e03126   Alan Cox   [WATCHDOG 36/57] ...
141
  static struct miscdevice sa1100dog_miscdev = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
142
  	.minor		= WATCHDOG_MINOR,
9bbd03758   Ian Campbell   [PATCH] ARM: 2833...
143
  	.name		= "watchdog",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
144
145
146
147
148
149
150
151
  	.fops		= &sa1100dog_fops,
  };
  
  static int margin __initdata = 60;		/* (secs) Default is 1 minute */
  
  static int __init sa1100dog_init(void)
  {
  	int ret;
28a623855   Eric Miao   [ARM] sa1100_wdt:...
152
  	oscr_freq = get_clock_tick_rate();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
153
154
155
156
157
  	/*
  	 * Read the reset status, and save it for later.  If
  	 * we suspend, RCSR will be cleared, and the watchdog
  	 * reset reason will be lost.
  	 */
214c6a7ed   Eric Miao   [ARM] sa1100_wdt:...
158
159
  	boot_status = (reset_status & RESET_STATUS_WATCHDOG) ?
  				WDIOF_CARDRESET : 0;
28a623855   Eric Miao   [ARM] sa1100_wdt:...
160
  	pre_margin = oscr_freq * margin;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
161
162
163
  
  	ret = misc_register(&sa1100dog_miscdev);
  	if (ret == 0)
27c766aaa   Joe Perches   watchdog: Use pr_...
164
165
166
  		pr_info("SA1100/PXA2xx Watchdog Timer: timer margin %d sec
  ",
  			margin);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
  	return ret;
  }
  
  static void __exit sa1100dog_exit(void)
  {
  	misc_deregister(&sa1100dog_miscdev);
  }
  
  module_init(sa1100dog_init);
  module_exit(sa1100dog_exit);
  
  MODULE_AUTHOR("Oleg Drokin <green@crimea.edu>");
  MODULE_DESCRIPTION("SA1100/PXA2xx Watchdog");
  
  module_param(margin, int, 0);
  MODULE_PARM_DESC(margin, "Watchdog margin in seconds (default 60s)");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
183
  MODULE_LICENSE("GPL");