From bdcff3458f5448fac585a6174ad9342f361b5135 Mon Sep 17 00:00:00 2001 From: Andrew Victor Date: Tue, 26 Sep 2006 17:49:30 +0200 Subject: [WATCHDOG] Atmel AT91RM9200 rename. The new Atmel AT91SAM9261 and AT91SAM9260 processors use a different internal watchdog peripheral. This watchdog driver is therefore AT91RM9200-specific. This patch renames at91_wdt.c to at91rm9200_wdt.c, and changes the name of the configuration option. Signed-off-by: Andrew Victor Signed-off-by: Wim Van Sebroeck diff --git a/arch/arm/configs/at91rm9200dk_defconfig b/arch/arm/configs/at91rm9200dk_defconfig index c82e466..b430414 100644 --- a/arch/arm/configs/at91rm9200dk_defconfig +++ b/arch/arm/configs/at91rm9200dk_defconfig @@ -577,7 +577,7 @@ CONFIG_WATCHDOG_NOWAYOUT=y # Watchdog Device Drivers # # CONFIG_SOFT_WATCHDOG is not set -CONFIG_AT91_WATCHDOG=y +CONFIG_AT91RM9200_WATCHDOG=y # # USB-based Watchdog Cards diff --git a/arch/arm/configs/at91rm9200ek_defconfig b/arch/arm/configs/at91rm9200ek_defconfig index b983fc5..d96fc83 100644 --- a/arch/arm/configs/at91rm9200ek_defconfig +++ b/arch/arm/configs/at91rm9200ek_defconfig @@ -558,7 +558,7 @@ CONFIG_WATCHDOG_NOWAYOUT=y # Watchdog Device Drivers # # CONFIG_SOFT_WATCHDOG is not set -CONFIG_AT91_WATCHDOG=y +CONFIG_AT91RM9200_WATCHDOG=y # # USB-based Watchdog Cards diff --git a/arch/arm/configs/csb337_defconfig b/arch/arm/configs/csb337_defconfig index a2d6fd3..20e6825 100644 --- a/arch/arm/configs/csb337_defconfig +++ b/arch/arm/configs/csb337_defconfig @@ -615,7 +615,7 @@ CONFIG_WATCHDOG_NOWAYOUT=y # Watchdog Device Drivers # # CONFIG_SOFT_WATCHDOG is not set -CONFIG_AT91_WATCHDOG=y +CONFIG_AT91RM9200_WATCHDOG=y # # USB-based Watchdog Cards diff --git a/arch/arm/configs/csb637_defconfig b/arch/arm/configs/csb637_defconfig index 2a1ac6c..df8595a 100644 --- a/arch/arm/configs/csb637_defconfig +++ b/arch/arm/configs/csb637_defconfig @@ -615,7 +615,7 @@ CONFIG_WATCHDOG_NOWAYOUT=y # Watchdog Device Drivers # # CONFIG_SOFT_WATCHDOG is not set -CONFIG_AT91_WATCHDOG=y +CONFIG_AT91RM9200_WATCHDOG=y # # USB-based Watchdog Cards diff --git a/arch/arm/configs/kafa_defconfig b/arch/arm/configs/kafa_defconfig index 54fcd75..a4cdafc 100644 --- a/arch/arm/configs/kafa_defconfig +++ b/arch/arm/configs/kafa_defconfig @@ -560,7 +560,7 @@ CONFIG_WATCHDOG_NOWAYOUT=y # Watchdog Device Drivers # # CONFIG_SOFT_WATCHDOG is not set -CONFIG_AT91_WATCHDOG=y +CONFIG_AT91RM9200_WATCHDOG=y # CONFIG_NVRAM is not set # CONFIG_DTLK is not set # CONFIG_R3964 is not set diff --git a/arch/arm/configs/onearm_defconfig b/arch/arm/configs/onearm_defconfig index cb1d94f..9b9f215 100644 --- a/arch/arm/configs/onearm_defconfig +++ b/arch/arm/configs/onearm_defconfig @@ -607,7 +607,7 @@ CONFIG_WATCHDOG_NOWAYOUT=y # Watchdog Device Drivers # # CONFIG_SOFT_WATCHDOG is not set -CONFIG_AT91_WATCHDOG=y +CONFIG_AT91RM9200_WATCHDOG=y # # USB-based Watchdog Cards diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig index 847a260..529f0a7 100644 --- a/drivers/char/watchdog/Kconfig +++ b/drivers/char/watchdog/Kconfig @@ -60,7 +60,7 @@ config SOFT_WATCHDOG # ARM Architecture -config AT91_WATCHDOG +config AT91RM9200_WATCHDOG tristate "AT91RM9200 watchdog" depends on WATCHDOG && ARCH_AT91RM9200 help diff --git a/drivers/char/watchdog/Makefile b/drivers/char/watchdog/Makefile index ee34741..3644049 100644 --- a/drivers/char/watchdog/Makefile +++ b/drivers/char/watchdog/Makefile @@ -23,7 +23,7 @@ obj-$(CONFIG_WDTPCI) += wdt_pci.o obj-$(CONFIG_USBPCWATCHDOG) += pcwd_usb.o # ARM Architecture -obj-$(CONFIG_AT91_WATCHDOG) += at91_wdt.o +obj-$(CONFIG_AT91RM9200_WATCHDOG) += at91rm9200_wdt.o obj-$(CONFIG_OMAP_WATCHDOG) += omap_wdt.o obj-$(CONFIG_21285_WATCHDOG) += wdt285.o obj-$(CONFIG_977_WATCHDOG) += wdt977.o diff --git a/drivers/char/watchdog/at91_wdt.c b/drivers/char/watchdog/at91_wdt.c deleted file mode 100644 index 4e7a114..0000000 --- a/drivers/char/watchdog/at91_wdt.c +++ /dev/null @@ -1,287 +0,0 @@ -/* - * Watchdog driver for Atmel AT91RM9200 (Thunder) - * - * Copyright (C) 2003 SAN People (Pty) Ltd - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -#define WDT_DEFAULT_TIME 5 /* seconds */ -#define WDT_MAX_TIME 256 /* seconds */ - -static int wdt_time = WDT_DEFAULT_TIME; -static int nowayout = WATCHDOG_NOWAYOUT; - -module_param(wdt_time, int, 0); -MODULE_PARM_DESC(wdt_time, "Watchdog time in seconds. (default="__MODULE_STRING(WDT_DEFAULT_TIME) ")"); - -#ifdef CONFIG_WATCHDOG_NOWAYOUT -module_param(nowayout, int, 0); -MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); -#endif - - -static unsigned long at91wdt_busy; - -/* ......................................................................... */ - -/* - * Disable the watchdog. - */ -static void inline at91_wdt_stop(void) -{ - at91_sys_write(AT91_ST_WDMR, AT91_ST_EXTEN); -} - -/* - * Enable and reset the watchdog. - */ -static void inline at91_wdt_start(void) -{ - at91_sys_write(AT91_ST_WDMR, AT91_ST_EXTEN | AT91_ST_RSTEN | (((65536 * wdt_time) >> 8) & AT91_ST_WDV)); - at91_sys_write(AT91_ST_CR, AT91_ST_WDRST); -} - -/* - * Reload the watchdog timer. (ie, pat the watchdog) - */ -static void inline at91_wdt_reload(void) -{ - at91_sys_write(AT91_ST_CR, AT91_ST_WDRST); -} - -/* ......................................................................... */ - -/* - * Watchdog device is opened, and watchdog starts running. - */ -static int at91_wdt_open(struct inode *inode, struct file *file) -{ - if (test_and_set_bit(0, &at91wdt_busy)) - return -EBUSY; - - at91_wdt_start(); - return nonseekable_open(inode, file); -} - -/* - * Close the watchdog device. - * If CONFIG_WATCHDOG_NOWAYOUT is NOT defined then the watchdog is also - * disabled. - */ -static int at91_wdt_close(struct inode *inode, struct file *file) -{ - if (!nowayout) - at91_wdt_stop(); /* Disable the watchdog when file is closed */ - - clear_bit(0, &at91wdt_busy); - return 0; -} - -/* - * Change the watchdog time interval. - */ -static int at91_wdt_settimeout(int new_time) -{ - /* - * All counting occurs at SLOW_CLOCK / 128 = 0.256 Hz - * - * Since WDV is a 16-bit counter, the maximum period is - * 65536 / 0.256 = 256 seconds. - */ - if ((new_time <= 0) || (new_time > WDT_MAX_TIME)) - return -EINVAL; - - /* Set new watchdog time. It will be used when at91_wdt_start() is called. */ - wdt_time = new_time; - return 0; -} - -static struct watchdog_info at91_wdt_info = { - .identity = "at91 watchdog", - .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, -}; - -/* - * Handle commands from user-space. - */ -static int at91_wdt_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - void __user *argp = (void __user *)arg; - int __user *p = argp; - int new_value; - - switch(cmd) { - case WDIOC_KEEPALIVE: - at91_wdt_reload(); /* pat the watchdog */ - return 0; - - case WDIOC_GETSUPPORT: - return copy_to_user(argp, &at91_wdt_info, sizeof(at91_wdt_info)) ? -EFAULT : 0; - - case WDIOC_SETTIMEOUT: - if (get_user(new_value, p)) - return -EFAULT; - - if (at91_wdt_settimeout(new_value)) - return -EINVAL; - - /* Enable new time value */ - at91_wdt_start(); - - /* Return current value */ - return put_user(wdt_time, p); - - case WDIOC_GETTIMEOUT: - return put_user(wdt_time, p); - - case WDIOC_GETSTATUS: - case WDIOC_GETBOOTSTATUS: - return put_user(0, p); - - case WDIOC_SETOPTIONS: - if (get_user(new_value, p)) - return -EFAULT; - - if (new_value & WDIOS_DISABLECARD) - at91_wdt_stop(); - if (new_value & WDIOS_ENABLECARD) - at91_wdt_start(); - return 0; - - default: - return -ENOTTY; - } -} - -/* - * Pat the watchdog whenever device is written to. - */ -static ssize_t at91_wdt_write(struct file *file, const char *data, size_t len, loff_t *ppos) -{ - at91_wdt_reload(); /* pat the watchdog */ - return len; -} - -/* ......................................................................... */ - -static const struct file_operations at91wdt_fops = { - .owner = THIS_MODULE, - .llseek = no_llseek, - .ioctl = at91_wdt_ioctl, - .open = at91_wdt_open, - .release = at91_wdt_close, - .write = at91_wdt_write, -}; - -static struct miscdevice at91wdt_miscdev = { - .minor = WATCHDOG_MINOR, - .name = "watchdog", - .fops = &at91wdt_fops, -}; - -static int __init at91wdt_probe(struct platform_device *pdev) -{ - int res; - - if (at91wdt_miscdev.dev) - return -EBUSY; - at91wdt_miscdev.dev = &pdev->dev; - - res = misc_register(&at91wdt_miscdev); - if (res) - return res; - - printk("AT91 Watchdog Timer enabled (%d seconds%s)\n", wdt_time, nowayout ? ", nowayout" : ""); - return 0; -} - -static int __exit at91wdt_remove(struct platform_device *pdev) -{ - int res; - - res = misc_deregister(&at91wdt_miscdev); - if (!res) - at91wdt_miscdev.dev = NULL; - - return res; -} - -static void at91wdt_shutdown(struct platform_device *pdev) -{ - at91_wdt_stop(); -} - -#ifdef CONFIG_PM - -static int at91wdt_suspend(struct platform_device *pdev, pm_message_t message) -{ - at91_wdt_stop(); - return 0; -} - -static int at91wdt_resume(struct platform_device *pdev) -{ - if (at91wdt_busy) - at91_wdt_start(); - return 0; -} - -#else -#define at91wdt_suspend NULL -#define at91wdt_resume NULL -#endif - -static struct platform_driver at91wdt_driver = { - .probe = at91wdt_probe, - .remove = __exit_p(at91wdt_remove), - .shutdown = at91wdt_shutdown, - .suspend = at91wdt_suspend, - .resume = at91wdt_resume, - .driver = { - .name = "at91_wdt", - .owner = THIS_MODULE, - }, -}; - -static int __init at91_wdt_init(void) -{ - /* Check that the heartbeat value is within range; if not reset to the default */ - if (at91_wdt_settimeout(wdt_time)) { - at91_wdt_settimeout(WDT_DEFAULT_TIME); - pr_info("at91_wdt: wdt_time value must be 1 <= wdt_time <= 256, using %d\n", wdt_time); - } - - return platform_driver_register(&at91wdt_driver); -} - -static void __exit at91_wdt_exit(void) -{ - platform_driver_unregister(&at91wdt_driver); -} - -module_init(at91_wdt_init); -module_exit(at91_wdt_exit); - -MODULE_AUTHOR("Andrew Victor"); -MODULE_DESCRIPTION("Watchdog driver for Atmel AT91RM9200"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); diff --git a/drivers/char/watchdog/at91rm9200_wdt.c b/drivers/char/watchdog/at91rm9200_wdt.c new file mode 100644 index 0000000..4e7a114 --- /dev/null +++ b/drivers/char/watchdog/at91rm9200_wdt.c @@ -0,0 +1,287 @@ +/* + * Watchdog driver for Atmel AT91RM9200 (Thunder) + * + * Copyright (C) 2003 SAN People (Pty) Ltd + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define WDT_DEFAULT_TIME 5 /* seconds */ +#define WDT_MAX_TIME 256 /* seconds */ + +static int wdt_time = WDT_DEFAULT_TIME; +static int nowayout = WATCHDOG_NOWAYOUT; + +module_param(wdt_time, int, 0); +MODULE_PARM_DESC(wdt_time, "Watchdog time in seconds. (default="__MODULE_STRING(WDT_DEFAULT_TIME) ")"); + +#ifdef CONFIG_WATCHDOG_NOWAYOUT +module_param(nowayout, int, 0); +MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); +#endif + + +static unsigned long at91wdt_busy; + +/* ......................................................................... */ + +/* + * Disable the watchdog. + */ +static void inline at91_wdt_stop(void) +{ + at91_sys_write(AT91_ST_WDMR, AT91_ST_EXTEN); +} + +/* + * Enable and reset the watchdog. + */ +static void inline at91_wdt_start(void) +{ + at91_sys_write(AT91_ST_WDMR, AT91_ST_EXTEN | AT91_ST_RSTEN | (((65536 * wdt_time) >> 8) & AT91_ST_WDV)); + at91_sys_write(AT91_ST_CR, AT91_ST_WDRST); +} + +/* + * Reload the watchdog timer. (ie, pat the watchdog) + */ +static void inline at91_wdt_reload(void) +{ + at91_sys_write(AT91_ST_CR, AT91_ST_WDRST); +} + +/* ......................................................................... */ + +/* + * Watchdog device is opened, and watchdog starts running. + */ +static int at91_wdt_open(struct inode *inode, struct file *file) +{ + if (test_and_set_bit(0, &at91wdt_busy)) + return -EBUSY; + + at91_wdt_start(); + return nonseekable_open(inode, file); +} + +/* + * Close the watchdog device. + * If CONFIG_WATCHDOG_NOWAYOUT is NOT defined then the watchdog is also + * disabled. + */ +static int at91_wdt_close(struct inode *inode, struct file *file) +{ + if (!nowayout) + at91_wdt_stop(); /* Disable the watchdog when file is closed */ + + clear_bit(0, &at91wdt_busy); + return 0; +} + +/* + * Change the watchdog time interval. + */ +static int at91_wdt_settimeout(int new_time) +{ + /* + * All counting occurs at SLOW_CLOCK / 128 = 0.256 Hz + * + * Since WDV is a 16-bit counter, the maximum period is + * 65536 / 0.256 = 256 seconds. + */ + if ((new_time <= 0) || (new_time > WDT_MAX_TIME)) + return -EINVAL; + + /* Set new watchdog time. It will be used when at91_wdt_start() is called. */ + wdt_time = new_time; + return 0; +} + +static struct watchdog_info at91_wdt_info = { + .identity = "at91 watchdog", + .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, +}; + +/* + * Handle commands from user-space. + */ +static int at91_wdt_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + void __user *argp = (void __user *)arg; + int __user *p = argp; + int new_value; + + switch(cmd) { + case WDIOC_KEEPALIVE: + at91_wdt_reload(); /* pat the watchdog */ + return 0; + + case WDIOC_GETSUPPORT: + return copy_to_user(argp, &at91_wdt_info, sizeof(at91_wdt_info)) ? -EFAULT : 0; + + case WDIOC_SETTIMEOUT: + if (get_user(new_value, p)) + return -EFAULT; + + if (at91_wdt_settimeout(new_value)) + return -EINVAL; + + /* Enable new time value */ + at91_wdt_start(); + + /* Return current value */ + return put_user(wdt_time, p); + + case WDIOC_GETTIMEOUT: + return put_user(wdt_time, p); + + case WDIOC_GETSTATUS: + case WDIOC_GETBOOTSTATUS: + return put_user(0, p); + + case WDIOC_SETOPTIONS: + if (get_user(new_value, p)) + return -EFAULT; + + if (new_value & WDIOS_DISABLECARD) + at91_wdt_stop(); + if (new_value & WDIOS_ENABLECARD) + at91_wdt_start(); + return 0; + + default: + return -ENOTTY; + } +} + +/* + * Pat the watchdog whenever device is written to. + */ +static ssize_t at91_wdt_write(struct file *file, const char *data, size_t len, loff_t *ppos) +{ + at91_wdt_reload(); /* pat the watchdog */ + return len; +} + +/* ......................................................................... */ + +static const struct file_operations at91wdt_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .ioctl = at91_wdt_ioctl, + .open = at91_wdt_open, + .release = at91_wdt_close, + .write = at91_wdt_write, +}; + +static struct miscdevice at91wdt_miscdev = { + .minor = WATCHDOG_MINOR, + .name = "watchdog", + .fops = &at91wdt_fops, +}; + +static int __init at91wdt_probe(struct platform_device *pdev) +{ + int res; + + if (at91wdt_miscdev.dev) + return -EBUSY; + at91wdt_miscdev.dev = &pdev->dev; + + res = misc_register(&at91wdt_miscdev); + if (res) + return res; + + printk("AT91 Watchdog Timer enabled (%d seconds%s)\n", wdt_time, nowayout ? ", nowayout" : ""); + return 0; +} + +static int __exit at91wdt_remove(struct platform_device *pdev) +{ + int res; + + res = misc_deregister(&at91wdt_miscdev); + if (!res) + at91wdt_miscdev.dev = NULL; + + return res; +} + +static void at91wdt_shutdown(struct platform_device *pdev) +{ + at91_wdt_stop(); +} + +#ifdef CONFIG_PM + +static int at91wdt_suspend(struct platform_device *pdev, pm_message_t message) +{ + at91_wdt_stop(); + return 0; +} + +static int at91wdt_resume(struct platform_device *pdev) +{ + if (at91wdt_busy) + at91_wdt_start(); + return 0; +} + +#else +#define at91wdt_suspend NULL +#define at91wdt_resume NULL +#endif + +static struct platform_driver at91wdt_driver = { + .probe = at91wdt_probe, + .remove = __exit_p(at91wdt_remove), + .shutdown = at91wdt_shutdown, + .suspend = at91wdt_suspend, + .resume = at91wdt_resume, + .driver = { + .name = "at91_wdt", + .owner = THIS_MODULE, + }, +}; + +static int __init at91_wdt_init(void) +{ + /* Check that the heartbeat value is within range; if not reset to the default */ + if (at91_wdt_settimeout(wdt_time)) { + at91_wdt_settimeout(WDT_DEFAULT_TIME); + pr_info("at91_wdt: wdt_time value must be 1 <= wdt_time <= 256, using %d\n", wdt_time); + } + + return platform_driver_register(&at91wdt_driver); +} + +static void __exit at91_wdt_exit(void) +{ + platform_driver_unregister(&at91wdt_driver); +} + +module_init(at91_wdt_init); +module_exit(at91_wdt_exit); + +MODULE_AUTHOR("Andrew Victor"); +MODULE_DESCRIPTION("Watchdog driver for Atmel AT91RM9200"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); -- cgit v0.10.2