aboutsummaryrefslogblamecommitdiffstats
path: root/drivers/watchdog/mpc8xx_wdt.c
blob: 1336425acf20cf3ea50b0b322419b255954a1309 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11










                                                                          






                             

                          



                                
                           


                                            
                                     
                                                                  
 


                                      
                                                                           




                                                                           
                                     
                                                                  
 


                                         
                                                                        






                                                                         

                                     
                                             




                                                                     


                                      
                                  


                 

                                                                         
 

                                     
                                 

                                       


                   

                                                                            



























                                                                   
                                     

                                                  
                                       





                                   
                                     
                                                 
                                       




                                                  
                               




                 
                                                       


                                  
                                           











                                               
                                  

















                                                    
/*
 * mpc8xx_wdt.c - MPC8xx watchdog userspace interface
 *
 * Author: Florian Schirmer <jolt@tuxbox.org>
 *
 * 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/fs.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/miscdevice.h>
#include <linux/module.h>
#include <linux/watchdog.h>
#include <asm/8xx_immap.h>
#include <linux/uaccess.h>
#include <linux/io.h>
#include <syslib/m8xx_wdt.h>

static unsigned long wdt_opened;
static int wdt_status;
static spinlock_t wdt_lock;

static void mpc8xx_wdt_handler_disable(void)
{
	volatile uint __iomem *piscr;
	piscr = (uint *)&((immap_t *)IMAP_ADDR)->im_sit.sit_piscr;

	if (!m8xx_has_internal_rtc)
		m8xx_wdt_stop_timer();
	else
		out_be32(piscr, in_be32(piscr) & ~(PISCR_PIE | PISCR_PTE));
	printk(KERN_NOTICE "mpc8xx_wdt: keep-alive handler deactivated\n");
}

static void mpc8xx_wdt_handler_enable(void)
{
	volatile uint __iomem *piscr;
	piscr = (uint *)&((immap_t *)IMAP_ADDR)->im_sit.sit_piscr;

	if (!m8xx_has_internal_rtc)
		m8xx_wdt_install_timer();
	else
		out_be32(piscr, in_be32(piscr) | PISCR_PIE | PISCR_PTE);
	printk(KERN_NOTICE "mpc8xx_wdt: keep-alive handler activated\n");
}

static int mpc8xx_wdt_open(struct inode *inode, struct file *file)
{
	if (test_and_set_bit(0, &wdt_opened))
		return -EBUSY;
	m8xx_wdt_reset();
	mpc8xx_wdt_handler_disable();
	return nonseekable_open(inode, file);
}

static int mpc8xx_wdt_release(struct inode *inode, struct file *file)
{
	m8xx_wdt_reset();
#if !defined(CONFIG_WATCHDOG_NOWAYOUT)
	mpc8xx_wdt_handler_enable();
#endif
	clear_bit(0, &wdt_opened);
	return 0;
}

static ssize_t mpc8xx_wdt_write(struct file *file, const char *data,
						size_t len, loff_t *ppos)
{
	if (len) {
		spin_lock(&wdt_lock);
		m8xx_wdt_reset();
		spin_unlock(&wdt_lock);
	}
	return len;
}

static long mpc8xx_wdt_ioctl(struct file *file,
					unsigned int cmd, unsigned long arg)
{
	int timeout;
	static struct watchdog_info info = {
		.options = WDIOF_KEEPALIVEPING,
		.firmware_version = 0,
		.identity = "MPC8xx watchdog",
	};

	switch (cmd) {
	case WDIOC_GETSUPPORT:
		if (copy_to_user((void *)arg, &info, sizeof(info)))
			return -EFAULT;
		break;

	case WDIOC_GETSTATUS:
	case WDIOC_GETBOOTSTATUS:
		if (put_user(wdt_status, (int *)arg))
			return -EFAULT;
		wdt_status &= ~WDIOF_KEEPALIVEPING;
		break;

	case WDIOC_GETTEMP:
		return -EOPNOTSUPP;

	case WDIOC_SETOPTIONS:
		return -EOPNOTSUPP;

	case WDIOC_KEEPALIVE:
		spin_lock(&wdt_lock);
		m8xx_wdt_reset();
		wdt_status |= WDIOF_KEEPALIVEPING;
		spin_unlock(&wdt_lock);
		break;

	case WDIOC_SETTIMEOUT:
		return -EOPNOTSUPP;

	case WDIOC_GETTIMEOUT:
		spin_lock(&wdt_lock);
		timeout = m8xx_wdt_get_timeout();
		spin_unlock(&wdt_lock);
		if (put_user(timeout, (int *)arg))
			return -EFAULT;
		break;

	default:
		return -ENOTTY;
	}

	return 0;
}

static const struct file_operations mpc8xx_wdt_fops = {
	.owner = THIS_MODULE,
	.llseek = no_llseek,
	.write = mpc8xx_wdt_write,
	.unlocked_ioctl = mpc8xx_wdt_ioctl,
	.open = mpc8xx_wdt_open,
	.release = mpc8xx_wdt_release,
};

static struct miscdevice mpc8xx_wdt_miscdev = {
	.minor = WATCHDOG_MINOR,
	.name = "watchdog",
	.fops = &mpc8xx_wdt_fops,
};

static int __init mpc8xx_wdt_init(void)
{
	spin_lock_init(&wdt_lock);
	return misc_register(&mpc8xx_wdt_miscdev);
}

static void __exit mpc8xx_wdt_exit(void)
{
	misc_deregister(&mpc8xx_wdt_miscdev);

	m8xx_wdt_reset();
	mpc8xx_wdt_handler_enable();
}

module_init(mpc8xx_wdt_init);
module_exit(mpc8xx_wdt_exit);

MODULE_AUTHOR("Florian Schirmer <jolt@tuxbox.org>");
MODULE_DESCRIPTION("MPC8xx watchdog driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);