Blame view

drivers/watchdog/sa1100_wdt.c 4.46 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
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
20
21
22
23
24
25
26
27
  #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>
1977f0327   Jiri Slaby   remove asm/bitops...
28
  #include <linux/bitops.h>
f19e03126   Alan Cox   [WATCHDOG 36/57] ...
29
  #include <linux/uaccess.h>
87c52578b   Russell King   [ARM] Remove linu...
30
  #include <linux/timex.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
31
32
  
  #ifdef CONFIG_ARCH_PXA
5bf3df3f0   Eric Miao   [ARM] pxa: separa...
33
  #include <mach/regs-ost.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
34
  #endif
afd2fc02a   Russell King   Merge branch 'for...
35
  #include <mach/reset.h>
a09e64fbc   Russell King   [ARM] Move includ...
36
  #include <mach/hardware.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
37

28a623855   Eric Miao   [ARM] sa1100_wdt:...
38
  static unsigned long oscr_freq;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
39
  static unsigned long sa1100wdt_users;
a6f052e39   Raphael Assenat   [WATCHDOG] SA1100...
40
  static unsigned int pre_margin;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
41
  static int boot_status;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
42
43
44
45
46
47
  
  /*
   *	Allow only one person to hold it open
   */
  static int sa1100dog_open(struct inode *inode, struct file *file)
  {
f19e03126   Alan Cox   [WATCHDOG 36/57] ...
48
  	if (test_and_set_bit(1, &sa1100wdt_users))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
49
50
51
52
53
54
55
  		return -EBUSY;
  
  	/* Activate SA1100 Watchdog timer */
  	OSMR3 = OSCR + pre_margin;
  	OSSR = OSSR_M3;
  	OWER = OWER_WME;
  	OIER |= OIER_E3;
6abe78bf1   Wim Van Sebroeck   [WATCHDOG] Return...
56
  	return nonseekable_open(inode, file);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
57
58
59
  }
  
  /*
9bbd03758   Ian Campbell   [PATCH] ARM: 2833...
60
61
62
63
64
   * 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
65
66
67
   */
  static int sa1100dog_release(struct inode *inode, struct file *file)
  {
9bbd03758   Ian Campbell   [PATCH] ARM: 2833...
68
69
  	printk(KERN_CRIT "WATCHDOG: Device closed - timer will not stop
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
70
  	clear_bit(1, &sa1100wdt_users);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
71
72
  	return 0;
  }
f19e03126   Alan Cox   [WATCHDOG 36/57] ...
73
74
  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
75
  {
9bbd03758   Ian Campbell   [PATCH] ARM: 2833...
76
  	if (len)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
77
78
  		/* Refresh OSMR3 timer. */
  		OSMR3 = OSCR + pre_margin;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
79
80
  	return len;
  }
f19e03126   Alan Cox   [WATCHDOG 36/57] ...
81
82
83
  static const struct watchdog_info ident = {
  	.options	= WDIOF_CARDRESET | WDIOF_SETTIMEOUT
  				| WDIOF_KEEPALIVEPING,
9bbd03758   Ian Campbell   [PATCH] ARM: 2833...
84
  	.identity	= "SA1100/PXA255 Watchdog",
a6f052e39   Raphael Assenat   [WATCHDOG] SA1100...
85
  	.firmware_version	= 1,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
86
  };
f19e03126   Alan Cox   [WATCHDOG 36/57] ...
87
88
  static long sa1100dog_ioctl(struct file *file, unsigned int cmd,
  							unsigned long arg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
89
  {
795b89d20   Samuel Tardieu   [WATCHDOG] use EN...
90
  	int ret = -ENOTTY;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
91
  	int time;
3a69e5791   Ian Campbell   [WATCHDOG] sa1100...
92
93
  	void __user *argp = (void __user *)arg;
  	int __user *p = argp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
94
95
96
  
  	switch (cmd) {
  	case WDIOC_GETSUPPORT:
3a69e5791   Ian Campbell   [WATCHDOG] sa1100...
97
  		ret = copy_to_user(argp, &ident,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
98
99
100
101
  				   sizeof(ident)) ? -EFAULT : 0;
  		break;
  
  	case WDIOC_GETSTATUS:
3a69e5791   Ian Campbell   [WATCHDOG] sa1100...
102
  		ret = put_user(0, p);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
103
104
105
  		break;
  
  	case WDIOC_GETBOOTSTATUS:
3a69e5791   Ian Campbell   [WATCHDOG] sa1100...
106
  		ret = put_user(boot_status, p);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
107
  		break;
0c06090c9   Wim Van Sebroeck   [WATCHDOG] Coding...
108
109
110
111
  	case WDIOC_KEEPALIVE:
  		OSMR3 = OSCR + pre_margin;
  		ret = 0;
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
112
  	case WDIOC_SETTIMEOUT:
3a69e5791   Ian Campbell   [WATCHDOG] sa1100...
113
  		ret = get_user(time, p);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
114
115
  		if (ret)
  			break;
a6f052e39   Raphael Assenat   [WATCHDOG] SA1100...
116
  		if (time <= 0 || (oscr_freq * (long long)time >= 0xffffffff)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
117
118
119
  			ret = -EINVAL;
  			break;
  		}
28a623855   Eric Miao   [ARM] sa1100_wdt:...
120
  		pre_margin = oscr_freq * time;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
121
122
123
124
  		OSMR3 = OSCR + pre_margin;
  		/*fall through*/
  
  	case WDIOC_GETTIMEOUT:
28a623855   Eric Miao   [ARM] sa1100_wdt:...
125
  		ret = put_user(pre_margin / oscr_freq, p);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
126
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
127
128
129
  	}
  	return ret;
  }
f19e03126   Alan Cox   [WATCHDOG 36/57] ...
130
  static const struct file_operations sa1100dog_fops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
131
132
133
  	.owner		= THIS_MODULE,
  	.llseek		= no_llseek,
  	.write		= sa1100dog_write,
f19e03126   Alan Cox   [WATCHDOG 36/57] ...
134
  	.unlocked_ioctl	= sa1100dog_ioctl,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
135
136
137
  	.open		= sa1100dog_open,
  	.release	= sa1100dog_release,
  };
f19e03126   Alan Cox   [WATCHDOG 36/57] ...
138
  static struct miscdevice sa1100dog_miscdev = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
139
  	.minor		= WATCHDOG_MINOR,
9bbd03758   Ian Campbell   [PATCH] ARM: 2833...
140
  	.name		= "watchdog",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
141
142
143
144
145
146
147
148
  	.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:...
149
  	oscr_freq = get_clock_tick_rate();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
150
151
152
153
154
  	/*
  	 * 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:...
155
156
  	boot_status = (reset_status & RESET_STATUS_WATCHDOG) ?
  				WDIOF_CARDRESET : 0;
28a623855   Eric Miao   [ARM] sa1100_wdt:...
157
  	pre_margin = oscr_freq * margin;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
158
159
160
  
  	ret = misc_register(&sa1100dog_miscdev);
  	if (ret == 0)
f19e03126   Alan Cox   [WATCHDOG 36/57] ...
161
162
163
164
  		printk(KERN_INFO
  			"SA1100/PXA2xx Watchdog Timer: timer margin %d sec
  ",
  						margin);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
  	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
181
182
  MODULE_LICENSE("GPL");
  MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);