diff options
Diffstat (limited to 'drivers/watchdog/at32ap700x_wdt.c')
| -rw-r--r-- | drivers/watchdog/at32ap700x_wdt.c | 96 |
1 files changed, 40 insertions, 56 deletions
diff --git a/drivers/watchdog/at32ap700x_wdt.c b/drivers/watchdog/at32ap700x_wdt.c index ae0fca5e874..25b5c67d3af 100644 --- a/drivers/watchdog/at32ap700x_wdt.c +++ b/drivers/watchdog/at32ap700x_wdt.c @@ -32,6 +32,7 @@ #include <linux/uaccess.h> #include <linux/io.h> #include <linux/spinlock.h> +#include <linux/slab.h> #define TIMEOUT_MIN 1 #define TIMEOUT_MAX 2 @@ -44,8 +45,8 @@ MODULE_PARM_DESC(timeout, "Timeout value. Limited to be 1 or 2 seconds. (default=" __MODULE_STRING(TIMEOUT_DEFAULT) ")"); -static int nowayout = WATCHDOG_NOWAYOUT; -module_param(nowayout, int, 0); +static bool nowayout = WATCHDOG_NOWAYOUT; +module_param(nowayout, bool, 0); MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); @@ -202,7 +203,7 @@ static int at32_wdt_get_status(void) return status; } -static struct watchdog_info at32_wdt_info = { +static const struct watchdog_info at32_wdt_info = { .identity = "at32ap700x watchdog", .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | @@ -212,8 +213,8 @@ static struct watchdog_info at32_wdt_info = { /* * Handle commands from user-space. */ -static int at32_wdt_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) +static long at32_wdt_ioctl(struct file *file, + unsigned int cmd, unsigned long arg) { int ret = -ENOTTY; int time; @@ -221,27 +222,10 @@ static int at32_wdt_ioctl(struct inode *inode, struct file *file, int __user *p = argp; switch (cmd) { - case WDIOC_KEEPALIVE: - at32_wdt_pat(); - ret = 0; - break; case WDIOC_GETSUPPORT: ret = copy_to_user(argp, &at32_wdt_info, sizeof(at32_wdt_info)) ? -EFAULT : 0; break; - case WDIOC_SETTIMEOUT: - ret = get_user(time, p); - if (ret) - break; - ret = at32_wdt_settimeout(time); - if (ret) - break; - /* Enable new time value */ - at32_wdt_start(); - /* fall through */ - case WDIOC_GETTIMEOUT: - ret = put_user(wdt->timeout, p); - break; case WDIOC_GETSTATUS: ret = put_user(0, p); break; @@ -258,6 +242,23 @@ static int at32_wdt_ioctl(struct inode *inode, struct file *file, at32_wdt_start(); ret = 0; break; + case WDIOC_KEEPALIVE: + at32_wdt_pat(); + ret = 0; + break; + case WDIOC_SETTIMEOUT: + ret = get_user(time, p); + if (ret) + break; + ret = at32_wdt_settimeout(time); + if (ret) + break; + /* Enable new time value */ + at32_wdt_start(); + /* fall through */ + case WDIOC_GETTIMEOUT: + ret = put_user(wdt->timeout, p); + break; } return ret; @@ -283,7 +284,7 @@ static ssize_t at32_wdt_write(struct file *file, const char __user *data, */ for (i = 0; i != len; i++) { char c; - if (get_user(c, data+i)) + if (get_user(c, data + i)) return -EFAULT; if (c == 'V') expect_release = 42; @@ -298,7 +299,7 @@ static ssize_t at32_wdt_write(struct file *file, const char __user *data, static const struct file_operations at32_wdt_fops = { .owner = THIS_MODULE, .llseek = no_llseek, - .ioctl = at32_wdt_ioctl, + .unlocked_ioctl = at32_wdt_ioctl, .open = at32_wdt_open, .release = at32_wdt_close, .write = at32_wdt_write, @@ -320,13 +321,12 @@ static int __init at32_wdt_probe(struct platform_device *pdev) return -ENXIO; } - wdt = kzalloc(sizeof(struct wdt_at32ap700x), GFP_KERNEL); - if (!wdt) { - dev_dbg(&pdev->dev, "no memory for wdt structure\n"); + wdt = devm_kzalloc(&pdev->dev, sizeof(struct wdt_at32ap700x), + GFP_KERNEL); + if (!wdt) return -ENOMEM; - } - wdt->regs = ioremap(regs->start, regs->end - regs->start + 1); + wdt->regs = devm_ioremap(&pdev->dev, regs->start, resource_size(regs)); if (!wdt->regs) { ret = -ENOMEM; dev_dbg(&pdev->dev, "could not map I/O memory\n"); @@ -341,13 +341,17 @@ static int __init at32_wdt_probe(struct platform_device *pdev) dev_info(&pdev->dev, "CPU must be reset with external " "reset or POR due to silicon errata.\n"); ret = -EIO; - goto err_iounmap; + goto err_free; } else { wdt->users = 0; } - wdt->miscdev.minor = WATCHDOG_MINOR; - wdt->miscdev.name = "watchdog"; - wdt->miscdev.fops = &at32_wdt_fops; + + wdt->miscdev.minor = WATCHDOG_MINOR; + wdt->miscdev.name = "watchdog"; + wdt->miscdev.fops = &at32_wdt_fops; + wdt->miscdev.parent = &pdev->dev; + + platform_set_drvdata(pdev, wdt); if (at32_wdt_settimeout(timeout)) { at32_wdt_settimeout(TIMEOUT_DEFAULT); @@ -359,21 +363,16 @@ static int __init at32_wdt_probe(struct platform_device *pdev) ret = misc_register(&wdt->miscdev); if (ret) { dev_dbg(&pdev->dev, "failed to register wdt miscdev\n"); - goto err_iounmap; + goto err_free; } - platform_set_drvdata(pdev, wdt); - wdt->miscdev.parent = &pdev->dev; dev_info(&pdev->dev, "AT32AP700X WDT at 0x%p, timeout %d sec (nowayout=%d)\n", wdt->regs, wdt->timeout, nowayout); return 0; -err_iounmap: - iounmap(wdt->regs); err_free: - kfree(wdt); wdt = NULL; return ret; } @@ -386,12 +385,8 @@ static int __exit at32_wdt_remove(struct platform_device *pdev) at32_wdt_stop(); misc_deregister(&wdt->miscdev); - iounmap(wdt->regs); - kfree(wdt); wdt = NULL; - platform_set_drvdata(pdev, NULL); } - return 0; } @@ -432,19 +427,8 @@ static struct platform_driver at32_wdt_driver = { .shutdown = at32_wdt_shutdown, }; -static int __init at32_wdt_init(void) -{ - return platform_driver_probe(&at32_wdt_driver, at32_wdt_probe); -} -module_init(at32_wdt_init); - -static void __exit at32_wdt_exit(void) -{ - platform_driver_unregister(&at32_wdt_driver); -} -module_exit(at32_wdt_exit); +module_platform_driver_probe(at32_wdt_driver, at32_wdt_probe); -MODULE_AUTHOR("Hans-Christian Egtvedt <hcegtvedt@atmel.com>"); +MODULE_AUTHOR("Hans-Christian Egtvedt <egtvedt@samfundet.no>"); MODULE_DESCRIPTION("Watchdog driver for Atmel AT32AP700X"); MODULE_LICENSE("GPL"); -MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); |
