提交 2e51d90f 编写于 作者: A Axel Lin 提交者: Wim Van Sebroeck

watchdog: Convert wm8350_wdt driver to watchdog core

This patch converts wm8350_wdt driver to use watchdog core APIs.
Signed-off-by: NAxel Lin <axel.lin@gmail.com>
Signed-off-by: NWim Van Sebroeck <wim@iguana.be>
上级 85f6df14
...@@ -74,6 +74,7 @@ config WM831X_WATCHDOG ...@@ -74,6 +74,7 @@ config WM831X_WATCHDOG
config WM8350_WATCHDOG config WM8350_WATCHDOG
tristate "WM8350 watchdog" tristate "WM8350 watchdog"
depends on MFD_WM8350 depends on MFD_WM8350
select WATCHDOG_CORE
help help
Support for the watchdog in the WM8350 AudioPlus PMIC. When Support for the watchdog in the WM8350 AudioPlus PMIC. When
the watchdog triggers the system will be reset. the watchdog triggers the system will be reset.
......
...@@ -14,8 +14,6 @@ ...@@ -14,8 +14,6 @@
#include <linux/moduleparam.h> #include <linux/moduleparam.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/watchdog.h> #include <linux/watchdog.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
...@@ -27,13 +25,10 @@ MODULE_PARM_DESC(nowayout, ...@@ -27,13 +25,10 @@ MODULE_PARM_DESC(nowayout,
"Watchdog cannot be stopped once started (default=" "Watchdog cannot be stopped once started (default="
__MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
static unsigned long wm8350_wdt_users;
static struct miscdevice wm8350_wdt_miscdev;
static int wm8350_wdt_expect_close;
static DEFINE_MUTEX(wdt_mutex); static DEFINE_MUTEX(wdt_mutex);
static struct { static struct {
int time; /* Seconds */ unsigned int time; /* Seconds */
u16 val; /* To be set in WM8350_SYSTEM_CONTROL_2 */ u16 val; /* To be set in WM8350_SYSTEM_CONTROL_2 */
} wm8350_wdt_cfgs[] = { } wm8350_wdt_cfgs[] = {
{ 1, 0x02 }, { 1, 0x02 },
...@@ -41,22 +36,25 @@ static struct { ...@@ -41,22 +36,25 @@ static struct {
{ 4, 0x05 }, { 4, 0x05 },
}; };
static struct wm8350 *get_wm8350(void) static int wm8350_wdt_set_timeout(struct watchdog_device *wdt_dev,
unsigned int timeout)
{ {
return dev_get_drvdata(wm8350_wdt_miscdev.parent); struct wm8350 *wm8350 = watchdog_get_drvdata(wdt_dev);
} int ret, i;
static int wm8350_wdt_set_timeout(struct wm8350 *wm8350, u16 value)
{
int ret;
u16 reg; u16 reg;
for (i = 0; i < ARRAY_SIZE(wm8350_wdt_cfgs); i++)
if (wm8350_wdt_cfgs[i].time == timeout)
break;
if (i == ARRAY_SIZE(wm8350_wdt_cfgs))
return -EINVAL;
mutex_lock(&wdt_mutex); mutex_lock(&wdt_mutex);
wm8350_reg_unlock(wm8350); wm8350_reg_unlock(wm8350);
reg = wm8350_reg_read(wm8350, WM8350_SYSTEM_CONTROL_2); reg = wm8350_reg_read(wm8350, WM8350_SYSTEM_CONTROL_2);
reg &= ~WM8350_WDOG_TO_MASK; reg &= ~WM8350_WDOG_TO_MASK;
reg |= value; reg |= wm8350_wdt_cfgs[i].val;
ret = wm8350_reg_write(wm8350, WM8350_SYSTEM_CONTROL_2, reg); ret = wm8350_reg_write(wm8350, WM8350_SYSTEM_CONTROL_2, reg);
wm8350_reg_lock(wm8350); wm8350_reg_lock(wm8350);
...@@ -65,8 +63,9 @@ static int wm8350_wdt_set_timeout(struct wm8350 *wm8350, u16 value) ...@@ -65,8 +63,9 @@ static int wm8350_wdt_set_timeout(struct wm8350 *wm8350, u16 value)
return ret; return ret;
} }
static int wm8350_wdt_start(struct wm8350 *wm8350) static int wm8350_wdt_start(struct watchdog_device *wdt_dev)
{ {
struct wm8350 *wm8350 = watchdog_get_drvdata(wdt_dev);
int ret; int ret;
u16 reg; u16 reg;
...@@ -84,8 +83,9 @@ static int wm8350_wdt_start(struct wm8350 *wm8350) ...@@ -84,8 +83,9 @@ static int wm8350_wdt_start(struct wm8350 *wm8350)
return ret; return ret;
} }
static int wm8350_wdt_stop(struct wm8350 *wm8350) static int wm8350_wdt_stop(struct watchdog_device *wdt_dev)
{ {
struct wm8350 *wm8350 = watchdog_get_drvdata(wdt_dev);
int ret; int ret;
u16 reg; u16 reg;
...@@ -102,8 +102,9 @@ static int wm8350_wdt_stop(struct wm8350 *wm8350) ...@@ -102,8 +102,9 @@ static int wm8350_wdt_stop(struct wm8350 *wm8350)
return ret; return ret;
} }
static int wm8350_wdt_kick(struct wm8350 *wm8350) static int wm8350_wdt_ping(struct watchdog_device *wdt_dev)
{ {
struct wm8350 *wm8350 = watchdog_get_drvdata(wdt_dev);
int ret; int ret;
u16 reg; u16 reg;
...@@ -117,168 +118,25 @@ static int wm8350_wdt_kick(struct wm8350 *wm8350) ...@@ -117,168 +118,25 @@ static int wm8350_wdt_kick(struct wm8350 *wm8350)
return ret; return ret;
} }
static int wm8350_wdt_open(struct inode *inode, struct file *file) static const struct watchdog_info wm8350_wdt_info = {
{
struct wm8350 *wm8350 = get_wm8350();
int ret;
if (!wm8350)
return -ENODEV;
if (test_and_set_bit(0, &wm8350_wdt_users))
return -EBUSY;
ret = wm8350_wdt_start(wm8350);
if (ret != 0)
return ret;
return nonseekable_open(inode, file);
}
static int wm8350_wdt_release(struct inode *inode, struct file *file)
{
struct wm8350 *wm8350 = get_wm8350();
if (wm8350_wdt_expect_close)
wm8350_wdt_stop(wm8350);
else {
dev_warn(wm8350->dev, "Watchdog device closed uncleanly\n");
wm8350_wdt_kick(wm8350);
}
clear_bit(0, &wm8350_wdt_users);
return 0;
}
static ssize_t wm8350_wdt_write(struct file *file,
const char __user *data, size_t count,
loff_t *ppos)
{
struct wm8350 *wm8350 = get_wm8350();
size_t i;
if (count) {
wm8350_wdt_kick(wm8350);
if (!nowayout) {
/* In case it was set long ago */
wm8350_wdt_expect_close = 0;
/* scan to see whether or not we got the magic
character */
for (i = 0; i != count; i++) {
char c;
if (get_user(c, data + i))
return -EFAULT;
if (c == 'V')
wm8350_wdt_expect_close = 42;
}
}
}
return count;
}
static const struct watchdog_info ident = {
.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
.identity = "WM8350 Watchdog", .identity = "WM8350 Watchdog",
}; };
static long wm8350_wdt_ioctl(struct file *file, unsigned int cmd, static const struct watchdog_ops wm8350_wdt_ops = {
unsigned long arg)
{
struct wm8350 *wm8350 = get_wm8350();
int ret = -ENOTTY, time, i;
void __user *argp = (void __user *)arg;
int __user *p = argp;
u16 reg;
switch (cmd) {
case WDIOC_GETSUPPORT:
ret = copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0;
break;
case WDIOC_GETSTATUS:
case WDIOC_GETBOOTSTATUS:
ret = put_user(0, p);
break;
case WDIOC_SETOPTIONS:
{
int options;
if (get_user(options, p))
return -EFAULT;
ret = -EINVAL;
/* Setting both simultaneously means at least one must fail */
if (options == WDIOS_DISABLECARD)
ret = wm8350_wdt_stop(wm8350);
if (options == WDIOS_ENABLECARD)
ret = wm8350_wdt_start(wm8350);
break;
}
case WDIOC_KEEPALIVE:
ret = wm8350_wdt_kick(wm8350);
break;
case WDIOC_SETTIMEOUT:
ret = get_user(time, p);
if (ret)
break;
if (time == 0) {
if (nowayout)
ret = -EINVAL;
else
wm8350_wdt_stop(wm8350);
break;
}
for (i = 0; i < ARRAY_SIZE(wm8350_wdt_cfgs); i++)
if (wm8350_wdt_cfgs[i].time == time)
break;
if (i == ARRAY_SIZE(wm8350_wdt_cfgs))
ret = -EINVAL;
else
ret = wm8350_wdt_set_timeout(wm8350,
wm8350_wdt_cfgs[i].val);
break;
case WDIOC_GETTIMEOUT:
reg = wm8350_reg_read(wm8350, WM8350_SYSTEM_CONTROL_2);
reg &= WM8350_WDOG_TO_MASK;
for (i = 0; i < ARRAY_SIZE(wm8350_wdt_cfgs); i++)
if (wm8350_wdt_cfgs[i].val == reg)
break;
if (i == ARRAY_SIZE(wm8350_wdt_cfgs)) {
dev_warn(wm8350->dev,
"Unknown watchdog configuration: %x\n", reg);
ret = -EINVAL;
} else
ret = put_user(wm8350_wdt_cfgs[i].time, p);
}
return ret;
}
static const struct file_operations wm8350_wdt_fops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.llseek = no_llseek, .start = wm8350_wdt_start,
.write = wm8350_wdt_write, .stop = wm8350_wdt_stop,
.unlocked_ioctl = wm8350_wdt_ioctl, .ping = wm8350_wdt_ping,
.open = wm8350_wdt_open, .set_timeout = wm8350_wdt_set_timeout,
.release = wm8350_wdt_release,
}; };
static struct miscdevice wm8350_wdt_miscdev = { static struct watchdog_device wm8350_wdt = {
.minor = WATCHDOG_MINOR, .info = &wm8350_wdt_info,
.name = "watchdog", .ops = &wm8350_wdt_ops,
.fops = &wm8350_wdt_fops, .timeout = 4,
.min_timeout = 1,
.max_timeout = 4,
}; };
static int __devinit wm8350_wdt_probe(struct platform_device *pdev) static int __devinit wm8350_wdt_probe(struct platform_device *pdev)
...@@ -290,18 +148,18 @@ static int __devinit wm8350_wdt_probe(struct platform_device *pdev) ...@@ -290,18 +148,18 @@ static int __devinit wm8350_wdt_probe(struct platform_device *pdev)
return -ENODEV; return -ENODEV;
} }
/* Default to 4s timeout */ watchdog_set_nowayout(&wm8350_wdt, nowayout);
wm8350_wdt_set_timeout(wm8350, 0x05); watchdog_set_drvdata(&wm8350_wdt, wm8350);
wm8350_wdt_miscdev.parent = &pdev->dev; /* Default to 4s timeout */
wm8350_wdt_set_timeout(&wm8350_wdt, 4);
return misc_register(&wm8350_wdt_miscdev); return watchdog_register_device(&wm8350_wdt);
} }
static int __devexit wm8350_wdt_remove(struct platform_device *pdev) static int __devexit wm8350_wdt_remove(struct platform_device *pdev)
{ {
misc_deregister(&wm8350_wdt_miscdev); watchdog_unregister_device(&wm8350_wdt);
return 0; return 0;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册