/*
 * drivers/watchdog/orion5x_wdt.c
 *
 * Watchdog driver for Orion5x processors
 *
 * Author: Sylver Bruneau <sylver.bruneau@googlemail.com>
 *
 * 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/module.h>
#include <linux/moduleparam.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <linux/platform_device.h>
#include <linux/watchdog.h>
#include <linux/init.h>
#include <linux/uaccess.h>
#include <linux/io.h>
#include <linux/spinlock.h>
#include <plat/orion5x_wdt.h>

/*
 * Watchdog timer block registers.
 */
#define TIMER_CTRL		(TIMER_VIRT_BASE + 0x0000)
#define  WDT_EN			0x0010
#define WDT_VAL			(TIMER_VIRT_BASE + 0x0024)

#define WDT_MAX_CYCLE_COUNT	0xffffffff
#define WDT_IN_USE		0
#define WDT_OK_TO_CLOSE		1

static int nowayout = WATCHDOG_NOWAYOUT;
static int heartbeat = -1;		/* module parameter (seconds) */
static unsigned int wdt_max_duration;	/* (seconds) */
static unsigned int wdt_tclk;
static unsigned long wdt_status;
static spinlock_t wdt_lock;

static void wdt_enable(void)
{
	u32 reg;

	spin_lock(&wdt_lock);

	/* Set watchdog duration */
	writel(wdt_tclk * heartbeat, WDT_VAL);

	/* Clear watchdog timer interrupt */
	reg = readl(BRIDGE_CAUSE);
	reg &= ~WDT_INT_REQ;
	writel(reg, BRIDGE_CAUSE);

	/* Enable watchdog timer */
	reg = readl(TIMER_CTRL);
	reg |= WDT_EN;
	writel(reg, TIMER_CTRL);

	/* Enable reset on watchdog */
	reg = readl(CPU_RESET_MASK);
	reg |= WDT_RESET;
	writel(reg, CPU_RESET_MASK);

	spin_unlock(&wdt_lock);
}

static void wdt_disable(void)
{
	u32 reg;

	spin_lock(&wdt_lock);

	/* Disable reset on watchdog */
	reg = readl(CPU_RESET_MASK);
	reg &= ~WDT_RESET;
	writel(reg, CPU_RESET_MASK);

	/* Disable watchdog timer */
	reg = readl(TIMER_CTRL);
	reg &= ~WDT_EN;
	writel(reg, TIMER_CTRL);

	spin_unlock(&wdt_lock);
}

static int orion5x_wdt_get_timeleft(int *time_left)
{
	spin_lock(&wdt_lock);
	*time_left = readl(WDT_VAL) / wdt_tclk;
	spin_unlock(&wdt_lock);
	return 0;
}

static int orion5x_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_enable();
	return nonseekable_open(inode, file);
}

static ssize_t orion5x_wdt_write(struct file *file, const char *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_enable();
	}
	return len;
}

static struct watchdog_info ident = {
	.options	= WDIOF_MAGICCLOSE | WDIOF_SETTIMEOUT |
			  WDIOF_KEEPALIVEPING,
	.identity	= "Orion5x Watchdog",
};


static long orion5x_wdt_ioctl(struct file *file, unsigned int cmd,
				unsigned long arg)
{
	int ret = -ENOTTY;
	int time;

	switch (cmd) {
	case WDIOC_GETSUPPORT:
		ret = copy_to_user((struct watchdog_info *)arg, &ident,
				   sizeof(ident)) ? -EFAULT : 0;
		break;

	case WDIOC_GETSTATUS:
	case WDIOC_GETBOOTSTATUS:
		ret = put_user(0, (int *)arg);
		break;

	case WDIOC_KEEPALIVE:
		wdt_enable();
		ret = 0;
		break;

	case WDIOC_SETTIMEOUT:
		ret = get_user(time, (int *)arg);
		if (ret)
			break;

		if (time <= 0 || time > wdt_max_duration) {
			ret = -EINVAL;
			break;
		}
		heartbeat = time;
		wdt_enable();
		/* Fall through */

	case WDIOC_GETTIMEOUT:
		ret = put_user(heartbeat, (int *)arg);
		break;

	case WDIOC_GETTIMELEFT:
		if (orion5x_wdt_get_timeleft(&time)) {
			ret = -EINVAL;
			break;
		}
		ret = put_user(time, (int *)arg);
		break;
	}
	return ret;
}

static int orion5x_wdt_release(struct inode *inode, struct file *file)
{
	if (test_bit(WDT_OK_TO_CLOSE, &wdt_status))
		wdt_disable();
	else
		printk(KERN_CRIT "WATCHDOG: Device closed unexpectedly - "
					"timer will not stop\n");
	clear_bit(WDT_IN_USE, &wdt_status);
	clear_bit(WDT_OK_TO_CLOSE, &wdt_status);

	return 0;
}


static const struct file_operations orion5x_wdt_fops = {
	.owner		= THIS_MODULE,
	.llseek		= no_llseek,
	.write		= orion5x_wdt_write,
	.unlocked_ioctl	= orion5x_wdt_ioctl,
	.open		= orion5x_wdt_open,
	.release	= orion5x_wdt_release,
};

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

static int __devinit orion5x_wdt_probe(struct platform_device *pdev)
{
	struct orion5x_wdt_platform_data *pdata = pdev->dev.platform_data;
	int ret;

	if (pdata) {
		wdt_tclk = pdata->tclk;
	} else {
		printk(KERN_ERR "Orion5x Watchdog misses platform data\n");
		return -ENODEV;
	}

	if (orion5x_wdt_miscdev.parent)
		return -EBUSY;
	orion5x_wdt_miscdev.parent = &pdev->dev;

	wdt_max_duration = WDT_MAX_CYCLE_COUNT / wdt_tclk;
	if (heartbeat <= 0 || heartbeat > wdt_max_duration)
		heartbeat = wdt_max_duration;

	ret = misc_register(&orion5x_wdt_miscdev);
	if (ret)
		return ret;

	printk(KERN_INFO "Orion5x Watchdog Timer: Initial timeout %d sec%s\n",
				heartbeat, nowayout ? ", nowayout" : "");
	return 0;
}

static int __devexit orion5x_wdt_remove(struct platform_device *pdev)
{
	int ret;

	if (test_bit(WDT_IN_USE, &wdt_status)) {
		wdt_disable();
		clear_bit(WDT_IN_USE, &wdt_status);
	}

	ret = misc_deregister(&orion5x_wdt_miscdev);
	if (!ret)
		orion5x_wdt_miscdev.parent = NULL;

	return ret;
}

static struct platform_driver orion5x_wdt_driver = {
	.probe		= orion5x_wdt_probe,
	.remove		= __devexit_p(orion5x_wdt_remove),
	.driver		= {
		.owner	= THIS_MODULE,
		.name	= "orion5x_wdt",
	},
};

static int __init orion5x_wdt_init(void)
{
	spin_lock_init(&wdt_lock);
	return platform_driver_register(&orion5x_wdt_driver);
}

static void __exit orion5x_wdt_exit(void)
{
	platform_driver_unregister(&orion5x_wdt_driver);
}

module_init(orion5x_wdt_init);
module_exit(orion5x_wdt_exit);

MODULE_AUTHOR("Sylver Bruneau <sylver.bruneau@googlemail.com>");
MODULE_DESCRIPTION("Orion5x Processor Watchdog");

module_param(heartbeat, int, 0);
MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds");

module_param(nowayout, int, 0);
MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started");

MODULE_LICENSE("GPL");
MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
