mpc83xx_wdt.c

来自「LINUX 2.6.17.4的源码」· C语言 代码 · 共 230 行

C
230
字号
/* * mpc83xx_wdt.c - MPC83xx watchdog userspace interface * * Authors: Dave Updegraff <dave@cray.org> * 	    Kumar Gala <galak@kernel.crashing.org> * 		Attribution: from 83xx_wst: Florian Schirmer <jolt@tuxbox.org> * 				..and from sc520_wdt * * Note: it appears that you can only actually ENABLE or DISABLE the thing * once after POR. Once enabled, you cannot disable, and vice versa. * * 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 <linux/config.h>#include <linux/fs.h>#include <linux/init.h>#include <linux/kernel.h>#include <linux/miscdevice.h>#include <linux/platform_device.h>#include <linux/module.h>#include <linux/watchdog.h>#include <asm/io.h>#include <asm/uaccess.h>struct mpc83xx_wdt {	__be32 res0;	__be32 swcrr; /* System watchdog control register */#define SWCRR_SWTC 0xFFFF0000 /* Software Watchdog Time Count. */#define SWCRR_SWEN 0x00000004 /* Watchdog Enable bit. */#define SWCRR_SWRI 0x00000002 /* Software Watchdog Reset/Interrupt Select bit.*/#define SWCRR_SWPR 0x00000001 /* Software Watchdog Counter Prescale bit. */	__be32 swcnr; /* System watchdog count register */	u8 res1[2];	__be16 swsrr; /* System watchdog service register */	u8 res2[0xF0];};static struct mpc83xx_wdt __iomem *wd_base;static u16 timeout = 0xffff;module_param(timeout, ushort, 0);MODULE_PARM_DESC(timeout, "Watchdog timeout in ticks. (0<timeout<65536, default=65535");static int reset = 1;module_param(reset, bool, 0);MODULE_PARM_DESC(reset, "Watchdog Interrupt/Reset Mode. 0 = interrupt, 1 = reset");/* * We always prescale, but if someone really doesn't want to they can set this * to 0 */static int prescale = 1;static unsigned int timeout_sec;static unsigned long wdt_is_open;static spinlock_t wdt_spinlock;static void mpc83xx_wdt_keepalive(void){	/* Ping the WDT */	spin_lock(&wdt_spinlock);	out_be16(&wd_base->swsrr, 0x556c);	out_be16(&wd_base->swsrr, 0xaa39);	spin_unlock(&wdt_spinlock);}static ssize_t mpc83xx_wdt_write(struct file *file, const char __user *buf,				 size_t count, loff_t *ppos){	if (count)		mpc83xx_wdt_keepalive();	return count;}static int mpc83xx_wdt_open(struct inode *inode, struct file *file){	u32 tmp = SWCRR_SWEN;	if (test_and_set_bit(0, &wdt_is_open))		return -EBUSY;	/* Once we start the watchdog we can't stop it */	__module_get(THIS_MODULE);	/* Good, fire up the show */	if (prescale)		tmp |= SWCRR_SWPR;	if (reset)		tmp |= SWCRR_SWRI;	tmp |= timeout << 16;	out_be32(&wd_base->swcrr, tmp);	return nonseekable_open(inode, file);}static int mpc83xx_wdt_release(struct inode *inode, struct file *file){	printk(KERN_CRIT "Unexpected close, not stopping watchdog!\n");	mpc83xx_wdt_keepalive();	clear_bit(0, &wdt_is_open);	return 0;}static int mpc83xx_wdt_ioctl(struct inode *inode, struct file *file,				unsigned int cmd, unsigned long arg){	void __user *argp = (void __user *)arg;	int __user *p = argp;	static struct watchdog_info ident = {		.options = WDIOF_KEEPALIVEPING,		.firmware_version = 1,		.identity = "MPC83xx",	};	switch (cmd) {	case WDIOC_GETSUPPORT:		return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0;	case WDIOC_KEEPALIVE:		mpc83xx_wdt_keepalive();		return 0;	case WDIOC_GETTIMEOUT:		return put_user(timeout_sec, p);	default:		return -ENOIOCTLCMD;	}}static struct file_operations mpc83xx_wdt_fops = {	.owner		= THIS_MODULE,	.llseek		= no_llseek,	.write		= mpc83xx_wdt_write,	.ioctl		= mpc83xx_wdt_ioctl,	.open		= mpc83xx_wdt_open,	.release	= mpc83xx_wdt_release,};static struct miscdevice mpc83xx_wdt_miscdev = {	.minor	= WATCHDOG_MINOR,	.name	= "watchdog",	.fops	= &mpc83xx_wdt_fops,};static int __devinit mpc83xx_wdt_probe(struct platform_device *dev){	struct resource *r;	int ret;	unsigned int *freq = dev->dev.platform_data;	/* get a pointer to the register memory */	r = platform_get_resource(dev, IORESOURCE_MEM, 0);	if (!r) {		ret = -ENODEV;		goto err_out;	}	wd_base = ioremap(r->start, sizeof (struct mpc83xx_wdt));	if (wd_base == NULL) {		ret = -ENOMEM;		goto err_out;	}	ret = misc_register(&mpc83xx_wdt_miscdev);	if (ret) {		printk(KERN_ERR "cannot register miscdev on minor=%d "				"(err=%d)\n",				WATCHDOG_MINOR, ret);		goto err_unmap;	}	/* Calculate the timeout in seconds */	if (prescale)		timeout_sec = (timeout * 0x10000) / (*freq);	else		timeout_sec = timeout / (*freq);	printk(KERN_INFO "WDT driver for MPC83xx initialized. "		"mode:%s timeout=%d (%d seconds)\n",		reset ? "reset":"interrupt", timeout, timeout_sec);	spin_lock_init(&wdt_spinlock);	return 0;err_unmap:	iounmap(wd_base);err_out:	return ret;}static int __devexit mpc83xx_wdt_remove(struct platform_device *dev){	misc_deregister(&mpc83xx_wdt_miscdev);	iounmap(wd_base);	return 0;}static struct platform_driver mpc83xx_wdt_driver = {	.probe		= mpc83xx_wdt_probe,	.remove		= __devexit_p(mpc83xx_wdt_remove),	.driver		= {		.name	= "mpc83xx_wdt",	},};static int __init mpc83xx_wdt_init(void){	return platform_driver_register(&mpc83xx_wdt_driver);}static void __exit mpc83xx_wdt_exit(void){	platform_driver_unregister(&mpc83xx_wdt_driver);}module_init(mpc83xx_wdt_init);module_exit(mpc83xx_wdt_exit);MODULE_AUTHOR("Dave Updegraff, Kumar Gala");MODULE_DESCRIPTION("Driver for watchdog timer in MPC83xx uProcessor");MODULE_LICENSE("GPL");MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);

⌨️ 快捷键说明

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