diff options
author | H Hartley Sweeten <hsweeten@visionengravers.com> | 2017-01-31 11:33:30 -0500 |
---|---|---|
committer | Guenter Roeck <linux@roeck-us.net> | 2017-02-24 17:00:23 -0500 |
commit | 8f8dc7bf3e0ab14d1ce1964dbe66ff8acf8779c6 (patch) | |
tree | 1389041a1072d7b61d5e7b56d0a01ab6e16b2ae2 | |
parent | 917003610d178b8bc3cbc63ee9fd203a7b01c444 (diff) |
watchdog: ts72xx_wdt: convert driver to watchdog core
Cleanup this driver and convert it to use the watchdog framework API.
Signed-off-by: H Hartley Sweeten <hsweeten@visionengravers.com>
Cc: Mika Westerberg <mika.westerberg@iki.fi>
[groeck: Dropped initialization of static variable]
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
-rw-r--r-- | drivers/watchdog/ts72xx_wdt.c | 447 |
1 files changed, 89 insertions, 358 deletions
diff --git a/drivers/watchdog/ts72xx_wdt.c b/drivers/watchdog/ts72xx_wdt.c index 4b541934b6c5..17c25daebcce 100644 --- a/drivers/watchdog/ts72xx_wdt.c +++ b/drivers/watchdog/ts72xx_wdt.c | |||
@@ -13,428 +13,159 @@ | |||
13 | * warranty of any kind, whether express or implied. | 13 | * warranty of any kind, whether express or implied. |
14 | */ | 14 | */ |
15 | 15 | ||
16 | #include <linux/fs.h> | ||
17 | #include <linux/io.h> | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/moduleparam.h> | ||
20 | #include <linux/miscdevice.h> | ||
21 | #include <linux/mutex.h> | ||
22 | #include <linux/platform_device.h> | 16 | #include <linux/platform_device.h> |
23 | #include <linux/slab.h> | 17 | #include <linux/module.h> |
24 | #include <linux/watchdog.h> | 18 | #include <linux/watchdog.h> |
25 | #include <linux/uaccess.h> | 19 | #include <linux/io.h> |
26 | 20 | ||
27 | #define TS72XX_WDT_FEED_VAL 0x05 | 21 | #define TS72XX_WDT_DEFAULT_TIMEOUT 30 |
28 | #define TS72XX_WDT_DEFAULT_TIMEOUT 8 | ||
29 | 22 | ||
30 | static int timeout = TS72XX_WDT_DEFAULT_TIMEOUT; | 23 | static int timeout; |
31 | module_param(timeout, int, 0); | 24 | module_param(timeout, int, 0); |
32 | MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. " | 25 | MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds."); |
33 | "(1 <= timeout <= 8, default=" | ||
34 | __MODULE_STRING(TS72XX_WDT_DEFAULT_TIMEOUT) | ||
35 | ")"); | ||
36 | 26 | ||
37 | static bool nowayout = WATCHDOG_NOWAYOUT; | 27 | static bool nowayout = WATCHDOG_NOWAYOUT; |
38 | module_param(nowayout, bool, 0); | 28 | module_param(nowayout, bool, 0); |
39 | MODULE_PARM_DESC(nowayout, "Disable watchdog shutdown on close"); | 29 | MODULE_PARM_DESC(nowayout, "Disable watchdog shutdown on close"); |
40 | 30 | ||
41 | /** | 31 | /* priv->control_reg */ |
42 | * struct ts72xx_wdt - watchdog control structure | 32 | #define TS72XX_WDT_CTRL_DISABLE 0x00 |
43 | * @lock: lock that protects this structure | 33 | #define TS72XX_WDT_CTRL_250MS 0x01 |
44 | * @regval: watchdog timeout value suitable for control register | 34 | #define TS72XX_WDT_CTRL_500MS 0x02 |
45 | * @flags: flags controlling watchdog device state | 35 | #define TS72XX_WDT_CTRL_1SEC 0x03 |
46 | * @control_reg: watchdog control register | 36 | #define TS72XX_WDT_CTRL_RESERVED 0x04 |
47 | * @feed_reg: watchdog feed register | 37 | #define TS72XX_WDT_CTRL_2SEC 0x05 |
48 | * @pdev: back pointer to platform dev | 38 | #define TS72XX_WDT_CTRL_4SEC 0x06 |
49 | */ | 39 | #define TS72XX_WDT_CTRL_8SEC 0x07 |
50 | struct ts72xx_wdt { | 40 | |
51 | struct mutex lock; | 41 | /* priv->feed_reg */ |
52 | int regval; | 42 | #define TS72XX_WDT_FEED_VAL 0x05 |
53 | |||
54 | #define TS72XX_WDT_BUSY_FLAG 1 | ||
55 | #define TS72XX_WDT_EXPECT_CLOSE_FLAG 2 | ||
56 | int flags; | ||
57 | 43 | ||
44 | struct ts72xx_wdt_priv { | ||
58 | void __iomem *control_reg; | 45 | void __iomem *control_reg; |
59 | void __iomem *feed_reg; | 46 | void __iomem *feed_reg; |
60 | 47 | struct watchdog_device wdd; | |
61 | struct platform_device *pdev; | 48 | unsigned char regval; |
62 | }; | 49 | }; |
63 | 50 | ||
64 | static struct platform_device *ts72xx_wdt_pdev; | 51 | static int ts72xx_wdt_start(struct watchdog_device *wdd) |
65 | |||
66 | /* | ||
67 | * TS-72xx Watchdog supports following timeouts (value written | ||
68 | * to control register): | ||
69 | * value description | ||
70 | * ------------------------- | ||
71 | * 0x00 watchdog disabled | ||
72 | * 0x01 250ms | ||
73 | * 0x02 500ms | ||
74 | * 0x03 1s | ||
75 | * 0x04 reserved | ||
76 | * 0x05 2s | ||
77 | * 0x06 4s | ||
78 | * 0x07 8s | ||
79 | * | ||
80 | * Timeouts below 1s are not very usable so we don't | ||
81 | * allow them at all. | ||
82 | * | ||
83 | * We provide two functions that convert between these: | ||
84 | * timeout_to_regval() and regval_to_timeout(). | ||
85 | */ | ||
86 | static const struct { | ||
87 | int timeout; | ||
88 | int regval; | ||
89 | } ts72xx_wdt_map[] = { | ||
90 | { 1, 3 }, | ||
91 | { 2, 5 }, | ||
92 | { 4, 6 }, | ||
93 | { 8, 7 }, | ||
94 | }; | ||
95 | |||
96 | /** | ||
97 | * timeout_to_regval() - converts given timeout to control register value | ||
98 | * @new_timeout: timeout in seconds to be converted | ||
99 | * | ||
100 | * Function converts given @new_timeout into valid value that can | ||
101 | * be programmed into watchdog control register. When conversion is | ||
102 | * not possible, function returns %-EINVAL. | ||
103 | */ | ||
104 | static int timeout_to_regval(int new_timeout) | ||
105 | { | ||
106 | int i; | ||
107 | |||
108 | /* first limit it to 1 - 8 seconds */ | ||
109 | new_timeout = clamp_val(new_timeout, 1, 8); | ||
110 | |||
111 | for (i = 0; i < ARRAY_SIZE(ts72xx_wdt_map); i++) { | ||
112 | if (ts72xx_wdt_map[i].timeout >= new_timeout) | ||
113 | return ts72xx_wdt_map[i].regval; | ||
114 | } | ||
115 | |||
116 | return -EINVAL; | ||
117 | } | ||
118 | |||
119 | /** | ||
120 | * regval_to_timeout() - converts control register value to timeout | ||
121 | * @regval: control register value to be converted | ||
122 | * | ||
123 | * Function converts given @regval to timeout in seconds (1, 2, 4 or 8). | ||
124 | * If @regval cannot be converted, function returns %-EINVAL. | ||
125 | */ | ||
126 | static int regval_to_timeout(int regval) | ||
127 | { | 52 | { |
128 | int i; | 53 | struct ts72xx_wdt_priv *priv = watchdog_get_drvdata(wdd); |
129 | 54 | ||
130 | for (i = 0; i < ARRAY_SIZE(ts72xx_wdt_map); i++) { | 55 | writeb(TS72XX_WDT_FEED_VAL, priv->feed_reg); |
131 | if (ts72xx_wdt_map[i].regval == regval) | 56 | writeb(priv->regval, priv->control_reg); |
132 | return ts72xx_wdt_map[i].timeout; | ||
133 | } | ||
134 | 57 | ||
135 | return -EINVAL; | 58 | return 0; |
136 | } | 59 | } |
137 | 60 | ||
138 | /** | 61 | static int ts72xx_wdt_stop(struct watchdog_device *wdd) |
139 | * ts72xx_wdt_kick() - kick the watchdog | ||
140 | * @wdt: watchdog to be kicked | ||
141 | * | ||
142 | * Called with @wdt->lock held. | ||
143 | */ | ||
144 | static inline void ts72xx_wdt_kick(struct ts72xx_wdt *wdt) | ||
145 | { | 62 | { |
146 | __raw_writeb(TS72XX_WDT_FEED_VAL, wdt->feed_reg); | 63 | struct ts72xx_wdt_priv *priv = watchdog_get_drvdata(wdd); |
147 | } | ||
148 | 64 | ||
149 | /** | 65 | writeb(TS72XX_WDT_FEED_VAL, priv->feed_reg); |
150 | * ts72xx_wdt_start() - starts the watchdog timer | 66 | writeb(TS72XX_WDT_CTRL_DISABLE, priv->control_reg); |
151 | * @wdt: watchdog to be started | ||
152 | * | ||
153 | * This function programs timeout to watchdog timer | ||
154 | * and starts it. | ||
155 | * | ||
156 | * Called with @wdt->lock held. | ||
157 | */ | ||
158 | static void ts72xx_wdt_start(struct ts72xx_wdt *wdt) | ||
159 | { | ||
160 | /* | ||
161 | * To program the wdt, it first must be "fed" and | ||
162 | * only after that (within 30 usecs) the configuration | ||
163 | * can be changed. | ||
164 | */ | ||
165 | ts72xx_wdt_kick(wdt); | ||
166 | __raw_writeb((u8)wdt->regval, wdt->control_reg); | ||
167 | } | ||
168 | 67 | ||
169 | /** | 68 | return 0; |
170 | * ts72xx_wdt_stop() - stops the watchdog timer | ||
171 | * @wdt: watchdog to be stopped | ||
172 | * | ||
173 | * Called with @wdt->lock held. | ||
174 | */ | ||
175 | static void ts72xx_wdt_stop(struct ts72xx_wdt *wdt) | ||
176 | { | ||
177 | ts72xx_wdt_kick(wdt); | ||
178 | __raw_writeb(0, wdt->control_reg); | ||
179 | } | 69 | } |
180 | 70 | ||
181 | static int ts72xx_wdt_open(struct inode *inode, struct file *file) | 71 | static int ts72xx_wdt_ping(struct watchdog_device *wdd) |
182 | { | 72 | { |
183 | struct ts72xx_wdt *wdt = platform_get_drvdata(ts72xx_wdt_pdev); | 73 | struct ts72xx_wdt_priv *priv = watchdog_get_drvdata(wdd); |
184 | int regval; | ||
185 | |||
186 | /* | ||
187 | * Try to convert default timeout to valid register | ||
188 | * value first. | ||
189 | */ | ||
190 | regval = timeout_to_regval(timeout); | ||
191 | if (regval < 0) { | ||
192 | dev_err(&wdt->pdev->dev, | ||
193 | "failed to convert timeout (%d) to register value\n", | ||
194 | timeout); | ||
195 | return regval; | ||
196 | } | ||
197 | |||
198 | if (mutex_lock_interruptible(&wdt->lock)) | ||
199 | return -ERESTARTSYS; | ||
200 | 74 | ||
201 | if ((wdt->flags & TS72XX_WDT_BUSY_FLAG) != 0) { | 75 | writeb(TS72XX_WDT_FEED_VAL, priv->feed_reg); |
202 | mutex_unlock(&wdt->lock); | ||
203 | return -EBUSY; | ||
204 | } | ||
205 | |||
206 | wdt->flags = TS72XX_WDT_BUSY_FLAG; | ||
207 | wdt->regval = regval; | ||
208 | file->private_data = wdt; | ||
209 | |||
210 | ts72xx_wdt_start(wdt); | ||
211 | 76 | ||
212 | mutex_unlock(&wdt->lock); | 77 | return 0; |
213 | return nonseekable_open(inode, file); | ||
214 | } | 78 | } |
215 | 79 | ||
216 | static int ts72xx_wdt_release(struct inode *inode, struct file *file) | 80 | static int ts72xx_wdt_settimeout(struct watchdog_device *wdd, unsigned int to) |
217 | { | 81 | { |
218 | struct ts72xx_wdt *wdt = file->private_data; | 82 | struct ts72xx_wdt_priv *priv = watchdog_get_drvdata(wdd); |
219 | 83 | ||
220 | if (mutex_lock_interruptible(&wdt->lock)) | 84 | if (to == 1) { |
221 | return -ERESTARTSYS; | 85 | priv->regval = TS72XX_WDT_CTRL_1SEC; |
222 | 86 | } else if (to == 2) { | |
223 | if ((wdt->flags & TS72XX_WDT_EXPECT_CLOSE_FLAG) != 0) { | 87 | priv->regval = TS72XX_WDT_CTRL_2SEC; |
224 | ts72xx_wdt_stop(wdt); | 88 | } else if (to <= 4) { |
89 | priv->regval = TS72XX_WDT_CTRL_4SEC; | ||
90 | to = 4; | ||
225 | } else { | 91 | } else { |
226 | dev_warn(&wdt->pdev->dev, | 92 | priv->regval = TS72XX_WDT_CTRL_8SEC; |
227 | "TS-72XX WDT device closed unexpectly. " | 93 | if (to <= 8) |
228 | "Watchdog timer will not stop!\n"); | 94 | to = 8; |
229 | /* | ||
230 | * Kick it one more time, to give userland some time | ||
231 | * to recover (for example, respawning the kicker | ||
232 | * daemon). | ||
233 | */ | ||
234 | ts72xx_wdt_kick(wdt); | ||
235 | } | 95 | } |
236 | 96 | ||
237 | wdt->flags = 0; | 97 | wdd->timeout = to; |
238 | 98 | ||
239 | mutex_unlock(&wdt->lock); | 99 | if (watchdog_active(wdd)) { |
240 | return 0; | 100 | ts72xx_wdt_stop(wdd); |
241 | } | 101 | ts72xx_wdt_start(wdd); |
242 | |||
243 | static ssize_t ts72xx_wdt_write(struct file *file, | ||
244 | const char __user *data, | ||
245 | size_t len, | ||
246 | loff_t *ppos) | ||
247 | { | ||
248 | struct ts72xx_wdt *wdt = file->private_data; | ||
249 | |||
250 | if (!len) | ||
251 | return 0; | ||
252 | |||
253 | if (mutex_lock_interruptible(&wdt->lock)) | ||
254 | return -ERESTARTSYS; | ||
255 | |||
256 | ts72xx_wdt_kick(wdt); | ||
257 | |||
258 | /* | ||
259 | * Support for magic character closing. User process | ||
260 | * writes 'V' into the device, just before it is closed. | ||
261 | * This means that we know that the wdt timer can be | ||
262 | * stopped after user closes the device. | ||
263 | */ | ||
264 | if (!nowayout) { | ||
265 | int i; | ||
266 | |||
267 | for (i = 0; i < len; i++) { | ||
268 | char c; | ||
269 | |||
270 | /* In case it was set long ago */ | ||
271 | wdt->flags &= ~TS72XX_WDT_EXPECT_CLOSE_FLAG; | ||
272 | |||
273 | if (get_user(c, data + i)) { | ||
274 | mutex_unlock(&wdt->lock); | ||
275 | return -EFAULT; | ||
276 | } | ||
277 | if (c == 'V') { | ||
278 | wdt->flags |= TS72XX_WDT_EXPECT_CLOSE_FLAG; | ||
279 | break; | ||
280 | } | ||
281 | } | ||
282 | } | 102 | } |
283 | 103 | ||
284 | mutex_unlock(&wdt->lock); | 104 | return 0; |
285 | return len; | ||
286 | } | 105 | } |
287 | 106 | ||
288 | static const struct watchdog_info winfo = { | 107 | static const struct watchdog_info ts72xx_wdt_ident = { |
289 | .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | | 108 | .options = WDIOF_KEEPALIVEPING | |
109 | WDIOF_SETTIMEOUT | | ||
290 | WDIOF_MAGICCLOSE, | 110 | WDIOF_MAGICCLOSE, |
291 | .firmware_version = 1, | 111 | .firmware_version = 1, |
292 | .identity = "TS-72XX WDT", | 112 | .identity = "TS-72XX WDT", |
293 | }; | 113 | }; |
294 | 114 | ||
295 | static long ts72xx_wdt_ioctl(struct file *file, unsigned int cmd, | 115 | static struct watchdog_ops ts72xx_wdt_ops = { |
296 | unsigned long arg) | ||
297 | { | ||
298 | struct ts72xx_wdt *wdt = file->private_data; | ||
299 | void __user *argp = (void __user *)arg; | ||
300 | int __user *p = (int __user *)argp; | ||
301 | int error = 0; | ||
302 | |||
303 | if (mutex_lock_interruptible(&wdt->lock)) | ||
304 | return -ERESTARTSYS; | ||
305 | |||
306 | switch (cmd) { | ||
307 | case WDIOC_GETSUPPORT: | ||
308 | if (copy_to_user(argp, &winfo, sizeof(winfo))) | ||
309 | error = -EFAULT; | ||
310 | break; | ||
311 | |||
312 | case WDIOC_GETSTATUS: | ||
313 | case WDIOC_GETBOOTSTATUS: | ||
314 | error = put_user(0, p); | ||
315 | break; | ||
316 | |||
317 | case WDIOC_KEEPALIVE: | ||
318 | ts72xx_wdt_kick(wdt); | ||
319 | break; | ||
320 | |||
321 | case WDIOC_SETOPTIONS: { | ||
322 | int options; | ||
323 | |||
324 | error = get_user(options, p); | ||
325 | if (error) | ||
326 | break; | ||
327 | |||
328 | error = -EINVAL; | ||
329 | |||
330 | if ((options & WDIOS_DISABLECARD) != 0) { | ||
331 | ts72xx_wdt_stop(wdt); | ||
332 | error = 0; | ||
333 | } | ||
334 | if ((options & WDIOS_ENABLECARD) != 0) { | ||
335 | ts72xx_wdt_start(wdt); | ||
336 | error = 0; | ||
337 | } | ||
338 | |||
339 | break; | ||
340 | } | ||
341 | |||
342 | case WDIOC_SETTIMEOUT: { | ||
343 | int new_timeout; | ||
344 | int regval; | ||
345 | |||
346 | error = get_user(new_timeout, p); | ||
347 | if (error) | ||
348 | break; | ||
349 | |||
350 | regval = timeout_to_regval(new_timeout); | ||
351 | if (regval < 0) { | ||
352 | error = regval; | ||
353 | break; | ||
354 | } | ||
355 | ts72xx_wdt_stop(wdt); | ||
356 | wdt->regval = regval; | ||
357 | ts72xx_wdt_start(wdt); | ||
358 | |||
359 | /*FALLTHROUGH*/ | ||
360 | } | ||
361 | |||
362 | case WDIOC_GETTIMEOUT: | ||
363 | error = put_user(regval_to_timeout(wdt->regval), p); | ||
364 | break; | ||
365 | |||
366 | default: | ||
367 | error = -ENOTTY; | ||
368 | break; | ||
369 | } | ||
370 | |||
371 | mutex_unlock(&wdt->lock); | ||
372 | return error; | ||
373 | } | ||
374 | |||
375 | static const struct file_operations ts72xx_wdt_fops = { | ||
376 | .owner = THIS_MODULE, | 116 | .owner = THIS_MODULE, |
377 | .llseek = no_llseek, | 117 | .start = ts72xx_wdt_start, |
378 | .open = ts72xx_wdt_open, | 118 | .stop = ts72xx_wdt_stop, |
379 | .release = ts72xx_wdt_release, | 119 | .ping = ts72xx_wdt_ping, |
380 | .write = ts72xx_wdt_write, | 120 | .set_timeout = ts72xx_wdt_settimeout, |
381 | .unlocked_ioctl = ts72xx_wdt_ioctl, | ||
382 | }; | ||
383 | |||
384 | static struct miscdevice ts72xx_wdt_miscdev = { | ||
385 | .minor = WATCHDOG_MINOR, | ||
386 | .name = "watchdog", | ||
387 | .fops = &ts72xx_wdt_fops, | ||
388 | }; | 121 | }; |
389 | 122 | ||
390 | static int ts72xx_wdt_probe(struct platform_device *pdev) | 123 | static int ts72xx_wdt_probe(struct platform_device *pdev) |
391 | { | 124 | { |
392 | struct ts72xx_wdt *wdt; | 125 | struct ts72xx_wdt_priv *priv; |
393 | struct resource *r1, *r2; | 126 | struct watchdog_device *wdd; |
394 | int error = 0; | 127 | struct resource *res; |
128 | int ret; | ||
395 | 129 | ||
396 | wdt = devm_kzalloc(&pdev->dev, sizeof(struct ts72xx_wdt), GFP_KERNEL); | 130 | priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); |
397 | if (!wdt) | 131 | if (!priv) |
398 | return -ENOMEM; | 132 | return -ENOMEM; |
399 | 133 | ||
400 | r1 = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 134 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
401 | wdt->control_reg = devm_ioremap_resource(&pdev->dev, r1); | 135 | priv->control_reg = devm_ioremap_resource(&pdev->dev, res); |
402 | if (IS_ERR(wdt->control_reg)) | 136 | if (IS_ERR(priv->control_reg)) |
403 | return PTR_ERR(wdt->control_reg); | 137 | return PTR_ERR(priv->control_reg); |
404 | 138 | ||
405 | r2 = platform_get_resource(pdev, IORESOURCE_MEM, 1); | 139 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); |
406 | wdt->feed_reg = devm_ioremap_resource(&pdev->dev, r2); | 140 | priv->feed_reg = devm_ioremap_resource(&pdev->dev, res); |
407 | if (IS_ERR(wdt->feed_reg)) | 141 | if (IS_ERR(priv->feed_reg)) |
408 | return PTR_ERR(wdt->feed_reg); | 142 | return PTR_ERR(priv->feed_reg); |
409 | 143 | ||
410 | platform_set_drvdata(pdev, wdt); | 144 | wdd = &priv->wdd; |
411 | ts72xx_wdt_pdev = pdev; | 145 | wdd->info = &ts72xx_wdt_ident; |
412 | wdt->pdev = pdev; | 146 | wdd->ops = &ts72xx_wdt_ops; |
413 | mutex_init(&wdt->lock); | 147 | wdd->min_timeout = 1; |
148 | wdd->max_hw_heartbeat_ms = 8000; | ||
149 | wdd->parent = &pdev->dev; | ||
414 | 150 | ||
415 | /* make sure that the watchdog is disabled */ | 151 | watchdog_set_nowayout(wdd, nowayout); |
416 | ts72xx_wdt_stop(wdt); | ||
417 | 152 | ||
418 | error = misc_register(&ts72xx_wdt_miscdev); | 153 | wdd->timeout = TS72XX_WDT_DEFAULT_TIMEOUT; |
419 | if (error) { | 154 | watchdog_init_timeout(wdd, timeout, &pdev->dev); |
420 | dev_err(&pdev->dev, "failed to register miscdev\n"); | ||
421 | return error; | ||
422 | } | ||
423 | 155 | ||
424 | dev_info(&pdev->dev, "TS-72xx Watchdog driver\n"); | 156 | watchdog_set_drvdata(wdd, priv); |
425 | 157 | ||
426 | return 0; | 158 | ret = devm_watchdog_register_device(&pdev->dev, wdd); |
427 | } | 159 | if (ret) |
160 | return ret; | ||
161 | |||
162 | dev_info(&pdev->dev, "TS-72xx Watchdog driver\n"); | ||
428 | 163 | ||
429 | static int ts72xx_wdt_remove(struct platform_device *pdev) | ||
430 | { | ||
431 | misc_deregister(&ts72xx_wdt_miscdev); | ||
432 | return 0; | 164 | return 0; |
433 | } | 165 | } |
434 | 166 | ||
435 | static struct platform_driver ts72xx_wdt_driver = { | 167 | static struct platform_driver ts72xx_wdt_driver = { |
436 | .probe = ts72xx_wdt_probe, | 168 | .probe = ts72xx_wdt_probe, |
437 | .remove = ts72xx_wdt_remove, | ||
438 | .driver = { | 169 | .driver = { |
439 | .name = "ts72xx-wdt", | 170 | .name = "ts72xx-wdt", |
440 | }, | 171 | }, |