aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/watchdog
diff options
context:
space:
mode:
authorIvan Khoronzhuk <ivan.khoronzhuk@ti.com>2013-12-05 06:26:24 -0500
committerWim Van Sebroeck <wim@iguana.be>2014-01-28 15:19:52 -0500
commitf48f3ceabf2ce4fb5b8aa0672166e1e9001946b9 (patch)
tree0efd1d7b9622de541506c31697b7104a25298917 /drivers/watchdog
parent6e2ac20e9c47cf26a1dd5a0f05b93ef0afd3c1c5 (diff)
watchdog: davinci: change driver to use WDT core
To reduce code duplicate and increase code readability use WDT core code to handle WDT interface. Remove io_lock as the WDT core uses mutex to lock each wdt device. Remove wdt_state as the WDT core tracks state with its own variable. The watchdog_init_timeout() can read timeout value from timeout-sec property if the passed value is out of bounds. The heartbeat is initialized in next way. If heartbeat is not set thought module parameter, try to read it's value from WDT node timeout-sec property. If node has no one, use default value. The heartbeat is hold in wdd->timeout by WDT core, so use it in order to set timeout period. Davinci WDT can't be stopped and once it's expired - it can be rearmed only after hardware reset, that's why nowayout feature is enforced. Signed-off-by: Ivan Khoronzhuk <ivan.khoronzhuk@ti.com> Acked-by: Santosh Shilimkar <santosh.shilimkar@ti.com> Reviewed-by: Guenter Roeck <linux@roeck-us.net> Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
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;