⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mv64x60_wdt.c

📁 linux-2.6.15.6
💻 C
字号:
/* * mv64x60_wdt.c - MV64X60 (Marvell Discovery) watchdog userspace interface * * Author: James Chapman <jchapman@katalix.com> * * Platform-specific setup code should configure the dog to generate * interrupt or reset as required.  This code only enables/disables * and services the watchdog. * * Derived from mpc8xx_wdt.c, with the following copyright. *  * 2002 (c) Florian Schirmer <jolt@tuxbox.org> This file is licensed under * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */#include <linux/config.h>#include <linux/fs.h>#include <linux/init.h>#include <linux/kernel.h>#include <linux/miscdevice.h>#include <linux/module.h>#include <linux/watchdog.h>#include <linux/platform_device.h>#include <asm/mv64x60.h>#include <asm/uaccess.h>#include <asm/io.h>/* MV64x60 WDC (config) register access definitions */#define MV64x60_WDC_CTL1_MASK	(3 << 24)#define MV64x60_WDC_CTL1(val)	((val & 3) << 24)#define MV64x60_WDC_CTL2_MASK	(3 << 26)#define MV64x60_WDC_CTL2(val)	((val & 3) << 26)/* Flags bits */#define MV64x60_WDOG_FLAG_OPENED	0#define MV64x60_WDOG_FLAG_ENABLED	1static unsigned long wdt_flags;static int wdt_status;static void __iomem *mv64x60_regs;static int mv64x60_wdt_timeout;static void mv64x60_wdt_reg_write(u32 val){	/* Allow write only to CTL1 / CTL2 fields, retaining values in	 * other fields.	 */	u32 data = readl(mv64x60_regs + MV64x60_WDT_WDC);	data &= ~(MV64x60_WDC_CTL1_MASK | MV64x60_WDC_CTL2_MASK);	data |= val;	writel(data, mv64x60_regs + MV64x60_WDT_WDC);}static void mv64x60_wdt_service(void){	/* Write 01 followed by 10 to CTL2 */	mv64x60_wdt_reg_write(MV64x60_WDC_CTL2(0x01));	mv64x60_wdt_reg_write(MV64x60_WDC_CTL2(0x02));}static void mv64x60_wdt_handler_disable(void){	if (test_and_clear_bit(MV64x60_WDOG_FLAG_ENABLED, &wdt_flags)) {		/* Write 01 followed by 10 to CTL1 */		mv64x60_wdt_reg_write(MV64x60_WDC_CTL1(0x01));		mv64x60_wdt_reg_write(MV64x60_WDC_CTL1(0x02));		printk(KERN_NOTICE "mv64x60_wdt: watchdog deactivated\n");	}}static void mv64x60_wdt_handler_enable(void){	if (!test_and_set_bit(MV64x60_WDOG_FLAG_ENABLED, &wdt_flags)) {		/* Write 01 followed by 10 to CTL1 */		mv64x60_wdt_reg_write(MV64x60_WDC_CTL1(0x01));		mv64x60_wdt_reg_write(MV64x60_WDC_CTL1(0x02));		printk(KERN_NOTICE "mv64x60_wdt: watchdog activated\n");	}}static int mv64x60_wdt_open(struct inode *inode, struct file *file){	if (test_and_set_bit(MV64x60_WDOG_FLAG_OPENED, &wdt_flags))		return -EBUSY;	mv64x60_wdt_service();	mv64x60_wdt_handler_enable();	nonseekable_open(inode, file);	return 0;}static int mv64x60_wdt_release(struct inode *inode, struct file *file){	mv64x60_wdt_service();#if !defined(CONFIG_WATCHDOG_NOWAYOUT)	mv64x60_wdt_handler_disable();#endif	clear_bit(MV64x60_WDOG_FLAG_OPENED, &wdt_flags);	return 0;}static ssize_t mv64x60_wdt_write(struct file *file, const char __user *data,				 size_t len, loff_t * ppos){	if (len)		mv64x60_wdt_service();	return len;}static int mv64x60_wdt_ioctl(struct inode *inode, struct file *file,			     unsigned int cmd, unsigned long arg){	int timeout;	void __user *argp = (void __user *)arg;	static struct watchdog_info info = {		.options = WDIOF_KEEPALIVEPING,		.firmware_version = 0,		.identity = "MV64x60 watchdog",	};	switch (cmd) {	case WDIOC_GETSUPPORT:		if (copy_to_user(argp, &info, sizeof(info)))			return -EFAULT;		break;	case WDIOC_GETSTATUS:	case WDIOC_GETBOOTSTATUS:		if (put_user(wdt_status, (int __user *)argp))			return -EFAULT;		wdt_status &= ~WDIOF_KEEPALIVEPING;		break;	case WDIOC_GETTEMP:		return -EOPNOTSUPP;	case WDIOC_SETOPTIONS:		return -EOPNOTSUPP;	case WDIOC_KEEPALIVE:		mv64x60_wdt_service();		wdt_status |= WDIOF_KEEPALIVEPING;		break;	case WDIOC_SETTIMEOUT:		return -EOPNOTSUPP;	case WDIOC_GETTIMEOUT:		timeout = mv64x60_wdt_timeout * HZ;		if (put_user(timeout, (int __user *)argp))			return -EFAULT;		break;	default:		return -ENOIOCTLCMD;	}	return 0;}static struct file_operations mv64x60_wdt_fops = {	.owner = THIS_MODULE,	.llseek = no_llseek,	.write = mv64x60_wdt_write,	.ioctl = mv64x60_wdt_ioctl,	.open = mv64x60_wdt_open,	.release = mv64x60_wdt_release,};static struct miscdevice mv64x60_wdt_miscdev = {	.minor = WATCHDOG_MINOR,	.name = "watchdog",	.fops = &mv64x60_wdt_fops,};static int __devinit mv64x60_wdt_probe(struct platform_device *dev){	struct mv64x60_wdt_pdata *pdata = dev->dev.platform_data;	int bus_clk = 133;	mv64x60_wdt_timeout = 10;	if (pdata) {		mv64x60_wdt_timeout = pdata->timeout;		bus_clk = pdata->bus_clk;	}	mv64x60_regs = mv64x60_get_bridge_vbase();	writel((mv64x60_wdt_timeout * (bus_clk * 1000000)) >> 8,	       mv64x60_regs + MV64x60_WDT_WDC);	return misc_register(&mv64x60_wdt_miscdev);}static int __devexit mv64x60_wdt_remove(struct platform_device *dev){	misc_deregister(&mv64x60_wdt_miscdev);	mv64x60_wdt_service();	mv64x60_wdt_handler_disable();	return 0;}static struct platform_driver mv64x60_wdt_driver = {	.probe = mv64x60_wdt_probe,	.remove = __devexit_p(mv64x60_wdt_remove),	.driver = {		.owner = THIS_MODULE,		.name = MV64x60_WDT_NAME,	},};static struct platform_device *mv64x60_wdt_dev;static int __init mv64x60_wdt_init(void){	int ret;	printk(KERN_INFO "MV64x60 watchdog driver\n");	mv64x60_wdt_dev = platform_device_register_simple(MV64x60_WDT_NAME,							  -1, NULL, 0);	if (IS_ERR(mv64x60_wdt_dev)) {		ret = PTR_ERR(mv64x60_wdt_dev);		goto out;	}	ret = platform_driver_register(&mv64x60_wdt_driver);      out:	return ret;}static void __exit mv64x60_wdt_exit(void){	platform_driver_unregister(&mv64x60_wdt_driver);	platform_device_unregister(mv64x60_wdt_dev);}module_init(mv64x60_wdt_init);module_exit(mv64x60_wdt_exit);MODULE_AUTHOR("James Chapman <jchapman@katalix.com>");MODULE_DESCRIPTION("MV64x60 watchdog driver");MODULE_LICENSE("GPL");MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -