aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/watchdog/Kconfig9
-rw-r--r--drivers/watchdog/Makefile1
-rw-r--r--drivers/watchdog/stmp3xxx_wdt.c288
3 files changed, 0 insertions, 298 deletions
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 879232186ca6..100caabf7fc8 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -317,15 +317,6 @@ config TWL4030_WATCHDOG
317 Support for TI TWL4030 watchdog. Say 'Y' here to enable the 317 Support for TI TWL4030 watchdog. Say 'Y' here to enable the
318 watchdog timer support for TWL4030 chips. 318 watchdog timer support for TWL4030 chips.
319 319
320config STMP3XXX_WATCHDOG
321 tristate "Freescale STMP3XXX watchdog"
322 depends on ARCH_STMP3XXX
323 help
324 Say Y here if to include support for the watchdog timer
325 for the Sigmatel STMP37XX/378X SoC.
326 To compile this driver as a module, choose M here: the
327 module will be called stmp3xxx_wdt.
328
329config STMP3XXX_RTC_WATCHDOG 320config STMP3XXX_RTC_WATCHDOG
330 tristate "Freescale STMP3XXX & i.MX23/28 watchdog" 321 tristate "Freescale STMP3XXX & i.MX23/28 watchdog"
331 depends on RTC_DRV_STMP 322 depends on RTC_DRV_STMP
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index f1fc6a1d92ca..a300b948f254 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -48,7 +48,6 @@ obj-$(CONFIG_IOP_WATCHDOG) += iop_wdt.o
48obj-$(CONFIG_DAVINCI_WATCHDOG) += davinci_wdt.o 48obj-$(CONFIG_DAVINCI_WATCHDOG) += davinci_wdt.o
49obj-$(CONFIG_ORION_WATCHDOG) += orion_wdt.o 49obj-$(CONFIG_ORION_WATCHDOG) += orion_wdt.o
50obj-$(CONFIG_COH901327_WATCHDOG) += coh901327_wdt.o 50obj-$(CONFIG_COH901327_WATCHDOG) += coh901327_wdt.o
51obj-$(CONFIG_STMP3XXX_WATCHDOG) += stmp3xxx_wdt.o
52obj-$(CONFIG_STMP3XXX_RTC_WATCHDOG) += stmp3xxx_rtc_wdt.o 51obj-$(CONFIG_STMP3XXX_RTC_WATCHDOG) += stmp3xxx_rtc_wdt.o
53obj-$(CONFIG_NUC900_WATCHDOG) += nuc900_wdt.o 52obj-$(CONFIG_NUC900_WATCHDOG) += nuc900_wdt.o
54obj-$(CONFIG_TS72XX_WATCHDOG) += ts72xx_wdt.o 53obj-$(CONFIG_TS72XX_WATCHDOG) += ts72xx_wdt.o
diff --git a/drivers/watchdog/stmp3xxx_wdt.c b/drivers/watchdog/stmp3xxx_wdt.c
deleted file mode 100644
index 1f4f69728fee..000000000000
--- a/drivers/watchdog/stmp3xxx_wdt.c
+++ /dev/null
@@ -1,288 +0,0 @@
1/*
2 * Watchdog driver for Freescale STMP37XX/STMP378X
3 *
4 * Author: Vitaly Wool <vital@embeddedalley.com>
5 *
6 * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
7 * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
8 */
9
10#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
11
12#include <linux/init.h>
13#include <linux/kernel.h>
14#include <linux/fs.h>
15#include <linux/miscdevice.h>
16#include <linux/watchdog.h>
17#include <linux/platform_device.h>
18#include <linux/spinlock.h>
19#include <linux/uaccess.h>
20#include <linux/module.h>
21
22#include <mach/platform.h>
23#include <mach/regs-rtc.h>
24
25#define DEFAULT_HEARTBEAT 19
26#define MAX_HEARTBEAT (0x10000000 >> 6)
27
28/* missing bitmask in headers */
29#define BV_RTC_PERSISTENT1_GENERAL__RTC_FORCE_UPDATER 0x80000000
30
31#define WDT_IN_USE 0
32#define WDT_OK_TO_CLOSE 1
33
34#define WDOG_COUNTER_RATE 1000 /* 1 kHz clock */
35
36static DEFINE_SPINLOCK(stmp3xxx_wdt_io_lock);
37static unsigned long wdt_status;
38static const bool nowayout = WATCHDOG_NOWAYOUT;
39static int heartbeat = DEFAULT_HEARTBEAT;
40static unsigned long boot_status;
41
42static void wdt_enable(u32 value)
43{
44 spin_lock(&stmp3xxx_wdt_io_lock);
45 __raw_writel(value, REGS_RTC_BASE + HW_RTC_WATCHDOG);
46 stmp3xxx_setl(BM_RTC_CTRL_WATCHDOGEN, REGS_RTC_BASE + HW_RTC_CTRL);
47 stmp3xxx_setl(BV_RTC_PERSISTENT1_GENERAL__RTC_FORCE_UPDATER,
48 REGS_RTC_BASE + HW_RTC_PERSISTENT1);
49 spin_unlock(&stmp3xxx_wdt_io_lock);
50}
51
52static void wdt_disable(void)
53{
54 spin_lock(&stmp3xxx_wdt_io_lock);
55 stmp3xxx_clearl(BV_RTC_PERSISTENT1_GENERAL__RTC_FORCE_UPDATER,
56 REGS_RTC_BASE + HW_RTC_PERSISTENT1);
57 stmp3xxx_clearl(BM_RTC_CTRL_WATCHDOGEN, REGS_RTC_BASE + HW_RTC_CTRL);
58 spin_unlock(&stmp3xxx_wdt_io_lock);
59}
60
61static void wdt_ping(void)
62{
63 wdt_enable(heartbeat * WDOG_COUNTER_RATE);
64}
65
66static int stmp3xxx_wdt_open(struct inode *inode, struct file *file)
67{
68 if (test_and_set_bit(WDT_IN_USE, &wdt_status))
69 return -EBUSY;
70
71 clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
72 wdt_ping();
73
74 return nonseekable_open(inode, file);
75}
76
77static ssize_t stmp3xxx_wdt_write(struct file *file, const char __user *data,
78 size_t len, loff_t *ppos)
79{
80 if (len) {
81 if (!nowayout) {
82 size_t i;
83
84 clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
85
86 for (i = 0; i != len; i++) {
87 char c;
88
89 if (get_user(c, data + i))
90 return -EFAULT;
91 if (c == 'V')
92 set_bit(WDT_OK_TO_CLOSE, &wdt_status);
93 }
94 }
95 wdt_ping();
96 }
97
98 return len;
99}
100
101static const struct watchdog_info ident = {
102 .options = WDIOF_CARDRESET |
103 WDIOF_MAGICCLOSE |
104 WDIOF_SETTIMEOUT |
105 WDIOF_KEEPALIVEPING,
106 .identity = "STMP3XXX Watchdog",
107};
108
109static long stmp3xxx_wdt_ioctl(struct file *file, unsigned int cmd,
110 unsigned long arg)
111{
112 void __user *argp = (void __user *)arg;
113 int __user *p = argp;
114 int new_heartbeat, opts;
115 int ret = -ENOTTY;
116
117 switch (cmd) {
118 case WDIOC_GETSUPPORT:
119 ret = copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0;
120 break;
121
122 case WDIOC_GETSTATUS:
123 ret = put_user(0, p);
124 break;
125
126 case WDIOC_GETBOOTSTATUS:
127 ret = put_user(boot_status, p);
128 break;
129
130 case WDIOC_SETOPTIONS:
131 if (get_user(opts, p)) {
132 ret = -EFAULT;
133 break;
134 }
135 if (opts & WDIOS_DISABLECARD)
136 wdt_disable();
137 else if (opts & WDIOS_ENABLECARD)
138 wdt_ping();
139 else {
140 pr_debug("%s: unknown option 0x%x\n", __func__, opts);
141 ret = -EINVAL;
142 break;
143 }
144 ret = 0;
145 break;
146
147 case WDIOC_KEEPALIVE:
148 wdt_ping();
149 ret = 0;
150 break;
151
152 case WDIOC_SETTIMEOUT:
153 if (get_user(new_heartbeat, p)) {
154 ret = -EFAULT;
155 break;
156 }
157 if (new_heartbeat <= 0 || new_heartbeat > MAX_HEARTBEAT) {
158 ret = -EINVAL;
159 break;
160 }
161
162 heartbeat = new_heartbeat;
163 wdt_ping();
164 /* Fall through */
165
166 case WDIOC_GETTIMEOUT:
167 ret = put_user(heartbeat, p);
168 break;
169 }
170 return ret;
171}
172
173static int stmp3xxx_wdt_release(struct inode *inode, struct file *file)
174{
175 int ret = 0;
176
177 if (!nowayout) {
178 if (!test_bit(WDT_OK_TO_CLOSE, &wdt_status)) {
179 wdt_ping();
180 pr_debug("%s: Device closed unexpectedly\n", __func__);
181 ret = -EINVAL;
182 } else {
183 wdt_disable();
184 clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
185 }
186 }
187 clear_bit(WDT_IN_USE, &wdt_status);
188
189 return ret;
190}
191
192static const struct file_operations stmp3xxx_wdt_fops = {
193 .owner = THIS_MODULE,
194 .llseek = no_llseek,
195 .write = stmp3xxx_wdt_write,
196 .unlocked_ioctl = stmp3xxx_wdt_ioctl,
197 .open = stmp3xxx_wdt_open,
198 .release = stmp3xxx_wdt_release,
199};
200
201static struct miscdevice stmp3xxx_wdt_miscdev = {
202 .minor = WATCHDOG_MINOR,
203 .name = "watchdog",
204 .fops = &stmp3xxx_wdt_fops,
205};
206
207static int stmp3xxx_wdt_probe(struct platform_device *pdev)
208{
209 int ret = 0;
210
211 if (heartbeat < 1 || heartbeat > MAX_HEARTBEAT)
212 heartbeat = DEFAULT_HEARTBEAT;
213
214 boot_status = __raw_readl(REGS_RTC_BASE + HW_RTC_PERSISTENT1) &
215 BV_RTC_PERSISTENT1_GENERAL__RTC_FORCE_UPDATER;
216 boot_status = !!boot_status;
217 stmp3xxx_clearl(BV_RTC_PERSISTENT1_GENERAL__RTC_FORCE_UPDATER,
218 REGS_RTC_BASE + HW_RTC_PERSISTENT1);
219 wdt_disable(); /* disable for now */
220
221 ret = misc_register(&stmp3xxx_wdt_miscdev);
222 if (ret < 0) {
223 dev_err(&pdev->dev, "cannot register misc device\n");
224 return ret;
225 }
226
227 pr_info("initialized, heartbeat %d sec\n", heartbeat);
228
229 return ret;
230}
231
232static int stmp3xxx_wdt_remove(struct platform_device *pdev)
233{
234 misc_deregister(&stmp3xxx_wdt_miscdev);
235 return 0;
236}
237
238#ifdef CONFIG_PM
239static int wdt_suspended;
240static u32 wdt_saved_time;
241
242static int stmp3xxx_wdt_suspend(struct platform_device *pdev,
243 pm_message_t state)
244{
245 if (__raw_readl(REGS_RTC_BASE + HW_RTC_CTRL) &
246 BM_RTC_CTRL_WATCHDOGEN) {
247 wdt_suspended = 1;
248 wdt_saved_time = __raw_readl(REGS_RTC_BASE + HW_RTC_WATCHDOG);
249 wdt_disable();
250 }
251 return 0;
252}
253
254static int stmp3xxx_wdt_resume(struct platform_device *pdev)
255{
256 if (wdt_suspended) {
257 wdt_enable(wdt_saved_time);
258 wdt_suspended = 0;
259 }
260 return 0;
261}
262#else
263#define stmp3xxx_wdt_suspend NULL
264#define stmp3xxx_wdt_resume NULL
265#endif
266
267static struct platform_driver platform_wdt_driver = {
268 .driver = {
269 .name = "stmp3xxx_wdt",
270 },
271 .probe = stmp3xxx_wdt_probe,
272 .remove = stmp3xxx_wdt_remove,
273 .suspend = stmp3xxx_wdt_suspend,
274 .resume = stmp3xxx_wdt_resume,
275};
276
277module_platform_driver(platform_wdt_driver);
278
279MODULE_DESCRIPTION("STMP3XXX Watchdog Driver");
280MODULE_LICENSE("GPL");
281
282module_param(heartbeat, int, 0);
283MODULE_PARM_DESC(heartbeat,
284 "Watchdog heartbeat period in seconds from 1 to "
285 __MODULE_STRING(MAX_HEARTBEAT) ", default "
286 __MODULE_STRING(DEFAULT_HEARTBEAT));
287
288MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);