diff options
Diffstat (limited to 'drivers/watchdog/stmp3xxx_wdt.c')
-rw-r--r-- | drivers/watchdog/stmp3xxx_wdt.c | 288 |
1 files changed, 0 insertions, 288 deletions
diff --git a/drivers/watchdog/stmp3xxx_wdt.c b/drivers/watchdog/stmp3xxx_wdt.c deleted file mode 100644 index 1f4f69728fee..000000000000 --- a/drivers/watchdog/stmp3xxx_wdt.c +++ /dev/null @@ -1,288 +0,0 @@ -/* - * Watchdog driver for Freescale STMP37XX/STMP378X - * - * Author: Vitaly Wool <vital@embeddedalley.com> - * - * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved. - * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include <linux/init.h> -#include <linux/kernel.h> -#include <linux/fs.h> -#include <linux/miscdevice.h> -#include <linux/watchdog.h> -#include <linux/platform_device.h> -#include <linux/spinlock.h> -#include <linux/uaccess.h> -#include <linux/module.h> - -#include <mach/platform.h> -#include <mach/regs-rtc.h> - -#define DEFAULT_HEARTBEAT 19 -#define MAX_HEARTBEAT (0x10000000 >> 6) - -/* missing bitmask in headers */ -#define BV_RTC_PERSISTENT1_GENERAL__RTC_FORCE_UPDATER 0x80000000 - -#define WDT_IN_USE 0 -#define WDT_OK_TO_CLOSE 1 - -#define WDOG_COUNTER_RATE 1000 /* 1 kHz clock */ - -static DEFINE_SPINLOCK(stmp3xxx_wdt_io_lock); -static unsigned long wdt_status; -static const bool nowayout = WATCHDOG_NOWAYOUT; -static int heartbeat = DEFAULT_HEARTBEAT; -static unsigned long boot_status; - -static void wdt_enable(u32 value) -{ - spin_lock(&stmp3xxx_wdt_io_lock); - __raw_writel(value, REGS_RTC_BASE + HW_RTC_WATCHDOG); - stmp3xxx_setl(BM_RTC_CTRL_WATCHDOGEN, REGS_RTC_BASE + HW_RTC_CTRL); - stmp3xxx_setl(BV_RTC_PERSISTENT1_GENERAL__RTC_FORCE_UPDATER, - REGS_RTC_BASE + HW_RTC_PERSISTENT1); - spin_unlock(&stmp3xxx_wdt_io_lock); -} - -static void wdt_disable(void) -{ - spin_lock(&stmp3xxx_wdt_io_lock); - stmp3xxx_clearl(BV_RTC_PERSISTENT1_GENERAL__RTC_FORCE_UPDATER, - REGS_RTC_BASE + HW_RTC_PERSISTENT1); - stmp3xxx_clearl(BM_RTC_CTRL_WATCHDOGEN, REGS_RTC_BASE + HW_RTC_CTRL); - spin_unlock(&stmp3xxx_wdt_io_lock); -} - -static void wdt_ping(void) -{ - wdt_enable(heartbeat * WDOG_COUNTER_RATE); -} - -static int stmp3xxx_wdt_open(struct inode *inode, struct file *file) -{ - if (test_and_set_bit(WDT_IN_USE, &wdt_status)) - return -EBUSY; - - clear_bit(WDT_OK_TO_CLOSE, &wdt_status); - wdt_ping(); - - return nonseekable_open(inode, file); -} - -static ssize_t stmp3xxx_wdt_write(struct file *file, const char __user *data, - size_t len, loff_t *ppos) -{ - if (len) { - if (!nowayout) { - size_t i; - - clear_bit(WDT_OK_TO_CLOSE, &wdt_status); - - for (i = 0; i != len; i++) { - char c; - - if (get_user(c, data + i)) - return -EFAULT; - if (c == 'V') - set_bit(WDT_OK_TO_CLOSE, &wdt_status); - } - } - wdt_ping(); - } - - return len; -} - -static const struct watchdog_info ident = { - .options = WDIOF_CARDRESET | - WDIOF_MAGICCLOSE | - WDIOF_SETTIMEOUT | - WDIOF_KEEPALIVEPING, - .identity = "STMP3XXX Watchdog", -}; - -static long stmp3xxx_wdt_ioctl(struct file *file, unsigned int cmd, - unsigned long arg) -{ - void __user *argp = (void __user *)arg; - int __user *p = argp; - int new_heartbeat, opts; - int ret = -ENOTTY; - - switch (cmd) { - case WDIOC_GETSUPPORT: - ret = copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; - break; - - case WDIOC_GETSTATUS: - ret = put_user(0, p); - break; - - case WDIOC_GETBOOTSTATUS: - ret = put_user(boot_status, p); - break; - - case WDIOC_SETOPTIONS: - if (get_user(opts, p)) { - ret = -EFAULT; - break; - } - if (opts & WDIOS_DISABLECARD) - wdt_disable(); - else if (opts & WDIOS_ENABLECARD) - wdt_ping(); - else { - pr_debug("%s: unknown option 0x%x\n", __func__, opts); - ret = -EINVAL; - break; - } - ret = 0; - break; - - case WDIOC_KEEPALIVE: - wdt_ping(); - ret = 0; - break; - - case WDIOC_SETTIMEOUT: - if (get_user(new_heartbeat, p)) { - ret = -EFAULT; - break; - } - if (new_heartbeat <= 0 || new_heartbeat > MAX_HEARTBEAT) { - ret = -EINVAL; - break; - } - - heartbeat = new_heartbeat; - wdt_ping(); - /* Fall through */ - - case WDIOC_GETTIMEOUT: - ret = put_user(heartbeat, p); - break; - } - return ret; -} - -static int stmp3xxx_wdt_release(struct inode *inode, struct file *file) -{ - int ret = 0; - - if (!nowayout) { - if (!test_bit(WDT_OK_TO_CLOSE, &wdt_status)) { - wdt_ping(); - pr_debug("%s: Device closed unexpectedly\n", __func__); - ret = -EINVAL; - } else { - wdt_disable(); - clear_bit(WDT_OK_TO_CLOSE, &wdt_status); - } - } - clear_bit(WDT_IN_USE, &wdt_status); - - return ret; -} - -static const struct file_operations stmp3xxx_wdt_fops = { - .owner = THIS_MODULE, - .llseek = no_llseek, - .write = stmp3xxx_wdt_write, - .unlocked_ioctl = stmp3xxx_wdt_ioctl, - .open = stmp3xxx_wdt_open, - .release = stmp3xxx_wdt_release, -}; - -static struct miscdevice stmp3xxx_wdt_miscdev = { - .minor = WATCHDOG_MINOR, - .name = "watchdog", - .fops = &stmp3xxx_wdt_fops, -}; - -static int stmp3xxx_wdt_probe(struct platform_device *pdev) -{ - int ret = 0; - - if (heartbeat < 1 || heartbeat > MAX_HEARTBEAT) - heartbeat = DEFAULT_HEARTBEAT; - - boot_status = __raw_readl(REGS_RTC_BASE + HW_RTC_PERSISTENT1) & - BV_RTC_PERSISTENT1_GENERAL__RTC_FORCE_UPDATER; - boot_status = !!boot_status; - stmp3xxx_clearl(BV_RTC_PERSISTENT1_GENERAL__RTC_FORCE_UPDATER, - REGS_RTC_BASE + HW_RTC_PERSISTENT1); - wdt_disable(); /* disable for now */ - - ret = misc_register(&stmp3xxx_wdt_miscdev); - if (ret < 0) { - dev_err(&pdev->dev, "cannot register misc device\n"); - return ret; - } - - pr_info("initialized, heartbeat %d sec\n", heartbeat); - - return ret; -} - -static int stmp3xxx_wdt_remove(struct platform_device *pdev) -{ - misc_deregister(&stmp3xxx_wdt_miscdev); - return 0; -} - -#ifdef CONFIG_PM -static int wdt_suspended; -static u32 wdt_saved_time; - -static int stmp3xxx_wdt_suspend(struct platform_device *pdev, - pm_message_t state) -{ - if (__raw_readl(REGS_RTC_BASE + HW_RTC_CTRL) & - BM_RTC_CTRL_WATCHDOGEN) { - wdt_suspended = 1; - wdt_saved_time = __raw_readl(REGS_RTC_BASE + HW_RTC_WATCHDOG); - wdt_disable(); - } - return 0; -} - -static int stmp3xxx_wdt_resume(struct platform_device *pdev) -{ - if (wdt_suspended) { - wdt_enable(wdt_saved_time); - wdt_suspended = 0; - } - return 0; -} -#else -#define stmp3xxx_wdt_suspend NULL -#define stmp3xxx_wdt_resume NULL -#endif - -static struct platform_driver platform_wdt_driver = { - .driver = { - .name = "stmp3xxx_wdt", - }, - .probe = stmp3xxx_wdt_probe, - .remove = stmp3xxx_wdt_remove, - .suspend = stmp3xxx_wdt_suspend, - .resume = stmp3xxx_wdt_resume, -}; - -module_platform_driver(platform_wdt_driver); - -MODULE_DESCRIPTION("STMP3XXX Watchdog Driver"); -MODULE_LICENSE("GPL"); - -module_param(heartbeat, int, 0); -MODULE_PARM_DESC(heartbeat, - "Watchdog heartbeat period in seconds from 1 to " - __MODULE_STRING(MAX_HEARTBEAT) ", default " - __MODULE_STRING(DEFAULT_HEARTBEAT)); - -MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); |