2 * Watchdog driver for the wm8350
4 * Copyright (C) 2007, 2008 Wolfson Microelectronics <linux@wolfsonmicro.com>
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation
11 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
13 #include <linux/module.h>
14 #include <linux/moduleparam.h>
15 #include <linux/types.h>
16 #include <linux/kernel.h>
17 #include <linux/platform_device.h>
18 #include <linux/watchdog.h>
19 #include <linux/uaccess.h>
20 #include <linux/mfd/wm8350/core.h>
22 static bool nowayout
= WATCHDOG_NOWAYOUT
;
23 module_param(nowayout
, bool, 0);
24 MODULE_PARM_DESC(nowayout
,
25 "Watchdog cannot be stopped once started (default="
26 __MODULE_STRING(WATCHDOG_NOWAYOUT
) ")");
28 static DEFINE_MUTEX(wdt_mutex
);
31 unsigned int time
; /* Seconds */
32 u16 val
; /* To be set in WM8350_SYSTEM_CONTROL_2 */
33 } wm8350_wdt_cfgs
[] = {
39 static int wm8350_wdt_set_timeout(struct watchdog_device
*wdt_dev
,
42 struct wm8350
*wm8350
= watchdog_get_drvdata(wdt_dev
);
46 for (i
= 0; i
< ARRAY_SIZE(wm8350_wdt_cfgs
); i
++)
47 if (wm8350_wdt_cfgs
[i
].time
== timeout
)
49 if (i
== ARRAY_SIZE(wm8350_wdt_cfgs
))
52 mutex_lock(&wdt_mutex
);
53 wm8350_reg_unlock(wm8350
);
55 reg
= wm8350_reg_read(wm8350
, WM8350_SYSTEM_CONTROL_2
);
56 reg
&= ~WM8350_WDOG_TO_MASK
;
57 reg
|= wm8350_wdt_cfgs
[i
].val
;
58 ret
= wm8350_reg_write(wm8350
, WM8350_SYSTEM_CONTROL_2
, reg
);
60 wm8350_reg_lock(wm8350
);
61 mutex_unlock(&wdt_mutex
);
63 wdt_dev
->timeout
= timeout
;
67 static int wm8350_wdt_start(struct watchdog_device
*wdt_dev
)
69 struct wm8350
*wm8350
= watchdog_get_drvdata(wdt_dev
);
73 mutex_lock(&wdt_mutex
);
74 wm8350_reg_unlock(wm8350
);
76 reg
= wm8350_reg_read(wm8350
, WM8350_SYSTEM_CONTROL_2
);
77 reg
&= ~WM8350_WDOG_MODE_MASK
;
79 ret
= wm8350_reg_write(wm8350
, WM8350_SYSTEM_CONTROL_2
, reg
);
81 wm8350_reg_lock(wm8350
);
82 mutex_unlock(&wdt_mutex
);
87 static int wm8350_wdt_stop(struct watchdog_device
*wdt_dev
)
89 struct wm8350
*wm8350
= watchdog_get_drvdata(wdt_dev
);
93 mutex_lock(&wdt_mutex
);
94 wm8350_reg_unlock(wm8350
);
96 reg
= wm8350_reg_read(wm8350
, WM8350_SYSTEM_CONTROL_2
);
97 reg
&= ~WM8350_WDOG_MODE_MASK
;
98 ret
= wm8350_reg_write(wm8350
, WM8350_SYSTEM_CONTROL_2
, reg
);
100 wm8350_reg_lock(wm8350
);
101 mutex_unlock(&wdt_mutex
);
106 static int wm8350_wdt_ping(struct watchdog_device
*wdt_dev
)
108 struct wm8350
*wm8350
= watchdog_get_drvdata(wdt_dev
);
112 mutex_lock(&wdt_mutex
);
114 reg
= wm8350_reg_read(wm8350
, WM8350_SYSTEM_CONTROL_2
);
115 ret
= wm8350_reg_write(wm8350
, WM8350_SYSTEM_CONTROL_2
, reg
);
117 mutex_unlock(&wdt_mutex
);
122 static const struct watchdog_info wm8350_wdt_info
= {
123 .options
= WDIOF_SETTIMEOUT
| WDIOF_KEEPALIVEPING
| WDIOF_MAGICCLOSE
,
124 .identity
= "WM8350 Watchdog",
127 static const struct watchdog_ops wm8350_wdt_ops
= {
128 .owner
= THIS_MODULE
,
129 .start
= wm8350_wdt_start
,
130 .stop
= wm8350_wdt_stop
,
131 .ping
= wm8350_wdt_ping
,
132 .set_timeout
= wm8350_wdt_set_timeout
,
135 static struct watchdog_device wm8350_wdt
= {
136 .info
= &wm8350_wdt_info
,
137 .ops
= &wm8350_wdt_ops
,
143 static int wm8350_wdt_probe(struct platform_device
*pdev
)
145 struct wm8350
*wm8350
= platform_get_drvdata(pdev
);
148 pr_err("No driver data supplied\n");
152 watchdog_set_nowayout(&wm8350_wdt
, nowayout
);
153 watchdog_set_drvdata(&wm8350_wdt
, wm8350
);
155 /* Default to 4s timeout */
156 wm8350_wdt_set_timeout(&wm8350_wdt
, 4);
158 return watchdog_register_device(&wm8350_wdt
);
161 static int wm8350_wdt_remove(struct platform_device
*pdev
)
163 watchdog_unregister_device(&wm8350_wdt
);
167 static struct platform_driver wm8350_wdt_driver
= {
168 .probe
= wm8350_wdt_probe
,
169 .remove
= wm8350_wdt_remove
,
171 .name
= "wm8350-wdt",
175 module_platform_driver(wm8350_wdt_driver
);
177 MODULE_AUTHOR("Mark Brown");
178 MODULE_DESCRIPTION("WM8350 Watchdog");
179 MODULE_LICENSE("GPL");
180 MODULE_ALIAS("platform:wm8350-wdt");