aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/watchdog
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/watchdog')
-rw-r--r--drivers/watchdog/Kconfig1
-rw-r--r--drivers/watchdog/davinci_wdt.c147
2 files changed, 36 insertions, 112 deletions
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 1491f0f4d41d..b69a0f763a6d 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -271,6 +271,7 @@ config IOP_WATCHDOG
271config DAVINCI_WATCHDOG 271config DAVINCI_WATCHDOG
272 tristate "DaVinci watchdog" 272 tristate "DaVinci watchdog"
273 depends on ARCH_DAVINCI 273 depends on ARCH_DAVINCI
274 select WATCHDOG_CORE
274 help 275 help
275 Say Y here if to include support for the watchdog timer 276 Say Y here if to include support for the watchdog timer
276 in the DaVinci DM644x/DM646x processors. 277 in the DaVinci DM644x/DM646x processors.
diff --git a/drivers/watchdog/davinci_wdt.c b/drivers/watchdog/davinci_wdt.c
index 12591f6596ef..bb8f23cd449a 100644
--- a/drivers/watchdog/davinci_wdt.c
+++ b/drivers/watchdog/davinci_wdt.c
@@ -3,7 +3,7 @@
3 * 3 *
4 * Watchdog driver for DaVinci DM644x/DM646x processors 4 * Watchdog driver for DaVinci DM644x/DM646x processors
5 * 5 *
6 * Copyright (C) 2006 Texas Instruments. 6 * Copyright (C) 2006-2013 Texas Instruments.
7 * 7 *
8 * 2007 (c) MontaVista Software, Inc. This file is licensed under 8 * 2007 (c) MontaVista Software, Inc. This file is licensed under
9 * the terms of the GNU General Public License version 2. This program 9 * the terms of the GNU General Public License version 2. This program
@@ -15,18 +15,12 @@
15#include <linux/moduleparam.h> 15#include <linux/moduleparam.h>
16#include <linux/types.h> 16#include <linux/types.h>
17#include <linux/kernel.h> 17#include <linux/kernel.h>
18#include <linux/fs.h>
19#include <linux/miscdevice.h>
20#include <linux/watchdog.h> 18#include <linux/watchdog.h>
21#include <linux/init.h> 19#include <linux/init.h>
22#include <linux/bitops.h>
23#include <linux/platform_device.h> 20#include <linux/platform_device.h>
24#include <linux/spinlock.h>
25#include <linux/uaccess.h>
26#include <linux/io.h> 21#include <linux/io.h>
27#include <linux/device.h> 22#include <linux/device.h>
28#include <linux/clk.h> 23#include <linux/clk.h>
29#include <linux/slab.h>
30#include <linux/err.h> 24#include <linux/err.h>
31 25
32#define MODULE_NAME "DAVINCI-WDT: " 26#define MODULE_NAME "DAVINCI-WDT: "
@@ -61,31 +55,12 @@
61#define WDKEY_SEQ0 (0xa5c6 << 16) 55#define WDKEY_SEQ0 (0xa5c6 << 16)
62#define WDKEY_SEQ1 (0xda7e << 16) 56#define WDKEY_SEQ1 (0xda7e << 16)
63 57
64static int heartbeat = DEFAULT_HEARTBEAT; 58static int heartbeat;
65
66static DEFINE_SPINLOCK(io_lock);
67static unsigned long wdt_status;
68#define WDT_IN_USE 0
69#define WDT_OK_TO_CLOSE 1
70#define WDT_REGION_INITED 2
71#define WDT_DEVICE_INITED 3
72
73static void __iomem *wdt_base; 59static void __iomem *wdt_base;
74struct clk *wdt_clk; 60struct clk *wdt_clk;
61static struct watchdog_device wdt_wdd;
75 62
76static void wdt_service(void) 63static int davinci_wdt_start(struct watchdog_device *wdd)
77{
78 spin_lock(&io_lock);
79
80 /* put watchdog in service state */
81 iowrite32(WDKEY_SEQ0, wdt_base + WDTCR);
82 /* put watchdog in active state */
83 iowrite32(WDKEY_SEQ1, wdt_base + WDTCR);
84
85 spin_unlock(&io_lock);
86}
87
88static void wdt_enable(void)
89{ 64{
90 u32 tgcr; 65 u32 tgcr;
91 u32 timer_margin; 66 u32 timer_margin;
@@ -93,8 +68,6 @@ static void wdt_enable(void)
93 68
94 wdt_freq = clk_get_rate(wdt_clk); 69 wdt_freq = clk_get_rate(wdt_clk);
95 70
96 spin_lock(&io_lock);
97
98 /* disable, internal clock source */ 71 /* disable, internal clock source */
99 iowrite32(0, wdt_base + TCR); 72 iowrite32(0, wdt_base + TCR);
100 /* reset timer, set mode to 64-bit watchdog, and unreset */ 73 /* reset timer, set mode to 64-bit watchdog, and unreset */
@@ -105,9 +78,9 @@ static void wdt_enable(void)
105 iowrite32(0, wdt_base + TIM12); 78 iowrite32(0, wdt_base + TIM12);
106 iowrite32(0, wdt_base + TIM34); 79 iowrite32(0, wdt_base + TIM34);
107 /* set timeout period */ 80 /* set timeout period */
108 timer_margin = (((u64)heartbeat * wdt_freq) & 0xffffffff); 81 timer_margin = (((u64)wdd->timeout * wdt_freq) & 0xffffffff);
109 iowrite32(timer_margin, wdt_base + PRD12); 82 iowrite32(timer_margin, wdt_base + PRD12);
110 timer_margin = (((u64)heartbeat * wdt_freq) >> 32); 83 timer_margin = (((u64)wdd->timeout * wdt_freq) >> 32);
111 iowrite32(timer_margin, wdt_base + PRD34); 84 iowrite32(timer_margin, wdt_base + PRD34);
112 /* enable run continuously */ 85 /* enable run continuously */
113 iowrite32(ENAMODE12_PERIODIC, wdt_base + TCR); 86 iowrite32(ENAMODE12_PERIODIC, wdt_base + TCR);
@@ -119,84 +92,28 @@ static void wdt_enable(void)
119 iowrite32(WDKEY_SEQ0 | WDEN, wdt_base + WDTCR); 92 iowrite32(WDKEY_SEQ0 | WDEN, wdt_base + WDTCR);
120 /* put watchdog in active state */ 93 /* put watchdog in active state */
121 iowrite32(WDKEY_SEQ1 | WDEN, wdt_base + WDTCR); 94 iowrite32(WDKEY_SEQ1 | WDEN, wdt_base + WDTCR);
122 95 return 0;
123 spin_unlock(&io_lock);
124}
125
126static int davinci_wdt_open(struct inode *inode, struct file *file)
127{
128 if (test_and_set_bit(WDT_IN_USE, &wdt_status))
129 return -EBUSY;
130
131 wdt_enable();
132
133 return nonseekable_open(inode, file);
134} 96}
135 97
136static ssize_t 98static int davinci_wdt_ping(struct watchdog_device *wdd)
137davinci_wdt_write(struct file *file, const char *data, size_t len,
138 loff_t *ppos)
139{ 99{
140 if (len) 100 /* put watchdog in service state */
141 wdt_service(); 101 iowrite32(WDKEY_SEQ0, wdt_base + WDTCR);
142 102 /* put watchdog in active state */
143 return len; 103 iowrite32(WDKEY_SEQ1, wdt_base + WDTCR);
104 return 0;
144} 105}
145 106
146static const struct watchdog_info ident = { 107static const struct watchdog_info davinci_wdt_info = {
147 .options = WDIOF_KEEPALIVEPING, 108 .options = WDIOF_KEEPALIVEPING,
148 .identity = "DaVinci Watchdog", 109 .identity = "DaVinci Watchdog",
149}; 110};
150 111
151static long davinci_wdt_ioctl(struct file *file, 112static const struct watchdog_ops davinci_wdt_ops = {
152 unsigned int cmd, unsigned long arg) 113 .owner = THIS_MODULE,
153{ 114 .start = davinci_wdt_start,
154 int ret = -ENOTTY; 115 .stop = davinci_wdt_ping,
155 116 .ping = davinci_wdt_ping,
156 switch (cmd) {
157 case WDIOC_GETSUPPORT:
158 ret = copy_to_user((struct watchdog_info *)arg, &ident,
159 sizeof(ident)) ? -EFAULT : 0;
160 break;
161
162 case WDIOC_GETSTATUS:
163 case WDIOC_GETBOOTSTATUS:
164 ret = put_user(0, (int *)arg);
165 break;
166
167 case WDIOC_KEEPALIVE:
168 wdt_service();
169 ret = 0;
170 break;
171
172 case WDIOC_GETTIMEOUT:
173 ret = put_user(heartbeat, (int *)arg);
174 break;
175 }
176 return ret;
177}
178
179static int davinci_wdt_release(struct inode *inode, struct file *file)
180{
181 wdt_service();
182 clear_bit(WDT_IN_USE, &wdt_status);
183
184 return 0;
185}
186
187static const struct file_operations davinci_wdt_fops = {
188 .owner = THIS_MODULE,
189 .llseek = no_llseek,
190 .write = davinci_wdt_write,
191 .unlocked_ioctl = davinci_wdt_ioctl,
192 .open = davinci_wdt_open,
193 .release = davinci_wdt_release,
194};
195
196static struct miscdevice davinci_wdt_miscdev = {
197 .minor = WATCHDOG_MINOR,
198 .name = "watchdog",
199 .fops = &davinci_wdt_fops,
200}; 117};
201 118
202static int davinci_wdt_probe(struct platform_device *pdev) 119static int davinci_wdt_probe(struct platform_device *pdev)
@@ -204,6 +121,7 @@ static int davinci_wdt_probe(struct platform_device *pdev)
204 int ret = 0; 121 int ret = 0;
205 struct device *dev = &pdev->dev; 122 struct device *dev = &pdev->dev;
206 struct resource *wdt_mem; 123 struct resource *wdt_mem;
124 struct watchdog_device *wdd;
207 125
208 wdt_clk = devm_clk_get(dev, NULL); 126 wdt_clk = devm_clk_get(dev, NULL);
209 if (WARN_ON(IS_ERR(wdt_clk))) 127 if (WARN_ON(IS_ERR(wdt_clk)))
@@ -211,29 +129,34 @@ static int davinci_wdt_probe(struct platform_device *pdev)
211 129
212 clk_prepare_enable(wdt_clk); 130 clk_prepare_enable(wdt_clk);
213 131
214 if (heartbeat < 1 || heartbeat > MAX_HEARTBEAT) 132 wdd = &wdt_wdd;
215 heartbeat = DEFAULT_HEARTBEAT; 133 wdd->info = &davinci_wdt_info;
134 wdd->ops = &davinci_wdt_ops;
135 wdd->min_timeout = 1;
136 wdd->max_timeout = MAX_HEARTBEAT;
137 wdd->timeout = DEFAULT_HEARTBEAT;
138
139 watchdog_init_timeout(wdd, heartbeat, dev);
140
141 dev_info(dev, "heartbeat %d sec\n", wdd->timeout);
216 142
217 dev_info(dev, "heartbeat %d sec\n", heartbeat); 143 watchdog_set_nowayout(wdd, 1);
218 144
219 wdt_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 145 wdt_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
220 wdt_base = devm_ioremap_resource(dev, wdt_mem); 146 wdt_base = devm_ioremap_resource(dev, wdt_mem);
221 if (IS_ERR(wdt_base)) 147 if (IS_ERR(wdt_base))
222 return PTR_ERR(wdt_base); 148 return PTR_ERR(wdt_base);
223 149
224 ret = misc_register(&davinci_wdt_miscdev); 150 ret = watchdog_register_device(wdd);
225 if (ret < 0) { 151 if (ret < 0)
226 dev_err(dev, "cannot register misc device\n"); 152 dev_err(dev, "cannot register watchdog device\n");
227 } else {
228 set_bit(WDT_DEVICE_INITED, &wdt_status);
229 }
230 153
231 return ret; 154 return ret;
232} 155}
233 156
234static int davinci_wdt_remove(struct platform_device *pdev) 157static int davinci_wdt_remove(struct platform_device *pdev)
235{ 158{
236 misc_deregister(&davinci_wdt_miscdev); 159 watchdog_unregister_device(&wdt_wdd);
237 clk_disable_unprepare(wdt_clk); 160 clk_disable_unprepare(wdt_clk);
238 161
239 return 0; 162 return 0;