/*
 * Copyright (C) 2008-2009 Avionic Design GmbH
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/fs.h>
#include <linux/io.h>
#include <linux/miscdevice.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/types.h>
#include <linux/uaccess.h>
#include <linux/watchdog.h>

#define WATCHDOG_NAME "adx-wdt"

/* register offsets */
#define	ADX_WDT_CONTROL		0x00
#define	ADX_WDT_CONTROL_ENABLE	(1 << 0)
#define	ADX_WDT_CONTROL_nRESET	(1 << 1)
#define	ADX_WDT_TIMEOUT		0x08

static struct platform_device *adx_wdt_dev;
static unsigned long driver_open;

#define	WDT_STATE_STOP	0
#define	WDT_STATE_START	1

struct adx_wdt {
	void __iomem *base;
	unsigned long timeout;
	unsigned int state;
	unsigned int wake;
	spinlock_t lock;
};

static struct watchdog_info adx_wdt_info = {
	.identity = "Avionic Design Xanthos Watchdog",
	.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
};

static void adx_wdt_start_locked(struct adx_wdt *wdt)
{
	u32 ctrl;

	ctrl = readl(wdt->base + ADX_WDT_CONTROL);
	ctrl |= ADX_WDT_CONTROL_ENABLE;
	writel(ctrl, wdt->base + ADX_WDT_CONTROL);
	wdt->state = WDT_STATE_START;
}

static void adx_wdt_start(struct adx_wdt *wdt)
{
	unsigned long flags;

	spin_lock_irqsave(&wdt->lock, flags);
	adx_wdt_start_locked(wdt);
	spin_unlock_irqrestore(&wdt->lock, flags);
}

static void adx_wdt_stop_locked(struct adx_wdt *wdt)
{
	u32 ctrl;

	ctrl = readl(wdt->base + ADX_WDT_CONTROL);
	ctrl &= ~ADX_WDT_CONTROL_ENABLE;
	writel(ctrl, wdt->base + ADX_WDT_CONTROL);
	wdt->state = WDT_STATE_STOP;
}

static void adx_wdt_stop(struct adx_wdt *wdt)
{
	unsigned long flags;

	spin_lock_irqsave(&wdt->lock, flags);
	adx_wdt_stop_locked(wdt);
	spin_unlock_irqrestore(&wdt->lock, flags);
}

static void adx_wdt_set_timeout(struct adx_wdt *wdt, unsigned long seconds)
{
	unsigned long timeout = seconds * 1000;
	unsigned long flags;
	unsigned int state;

	spin_lock_irqsave(&wdt->lock, flags);
	state = wdt->state;
	adx_wdt_stop_locked(wdt);
	writel(timeout, wdt->base + ADX_WDT_TIMEOUT);

	if (state == WDT_STATE_START)
		adx_wdt_start_locked(wdt);

	wdt->timeout = timeout;
	spin_unlock_irqrestore(&wdt->lock, flags);
}

static void adx_wdt_get_timeout(struct adx_wdt *wdt, unsigned long *seconds)
{
	*seconds = wdt->timeout / 1000;
}

static void adx_wdt_keepalive(struct adx_wdt *wdt)
{
	unsigned long flags;

	spin_lock_irqsave(&wdt->lock, flags);
	writel(wdt->timeout, wdt->base + ADX_WDT_TIMEOUT);
	spin_unlock_irqrestore(&wdt->lock, flags);
}

static int adx_wdt_open(struct inode *inode, struct file *file)
{
	struct adx_wdt *wdt = platform_get_drvdata(adx_wdt_dev);

	if (test_and_set_bit(0, &driver_open))
		return -EBUSY;

	file->private_data = wdt;
	adx_wdt_set_timeout(wdt, 30);
	adx_wdt_start(wdt);

	return nonseekable_open(inode, file);
}

static int adx_wdt_release(struct inode *inode, struct file *file)
{
	struct adx_wdt *wdt = file->private_data;

	adx_wdt_stop(wdt);
	clear_bit(0, &driver_open);

	return 0;
}

static long adx_wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
	struct adx_wdt *wdt = file->private_data;
	void __user *argp = (void __user *)arg;
	unsigned long __user *p = argp;
	unsigned long seconds = 0;
	unsigned int options;
	long ret = -EINVAL;

	switch (cmd) {
	case WDIOC_GETSUPPORT:
		if (copy_to_user(argp, &adx_wdt_info, sizeof(adx_wdt_info)))
			return -EFAULT;
		else
			return 0;

	case WDIOC_GETSTATUS:
	case WDIOC_GETBOOTSTATUS:
		return put_user(0, p);

	case WDIOC_KEEPALIVE:
		adx_wdt_keepalive(wdt);
		return 0;

	case WDIOC_SETTIMEOUT:
		if (get_user(seconds, p))
			return -EFAULT;

		adx_wdt_set_timeout(wdt, seconds);

		/* fallthrough */
	case WDIOC_GETTIMEOUT:
		adx_wdt_get_timeout(wdt, &seconds);
		return put_user(seconds, p);

	case WDIOC_SETOPTIONS:
		if (copy_from_user(&options, argp, sizeof(options)))
			return -EFAULT;

		if (options & WDIOS_DISABLECARD) {
			adx_wdt_stop(wdt);
			ret = 0;
		}

		if (options & WDIOS_ENABLECARD) {
			adx_wdt_start(wdt);
			ret = 0;
		}

		return ret;

	default:
		break;
	}

	return -ENOTTY;
}

static ssize_t adx_wdt_write(struct file *file, const char __user *data,
		size_t len, loff_t *ppos)
{
	struct adx_wdt *wdt = file->private_data;

	if (len)
		adx_wdt_keepalive(wdt);

	return len;
}

static const struct file_operations adx_wdt_fops = {
	.owner = THIS_MODULE,
	.llseek = no_llseek,
	.open = adx_wdt_open,
	.release = adx_wdt_release,
	.unlocked_ioctl = adx_wdt_ioctl,
	.write = adx_wdt_write,
};

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

static int __devinit adx_wdt_probe(struct platform_device *pdev)
{
	struct resource *res;
	struct adx_wdt *wdt;
	int ret = 0;
	u32 ctrl;

	wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL);
	if (!wdt) {
		dev_err(&pdev->dev, "cannot allocate WDT structure\n");
		return -ENOMEM;
	}

	spin_lock_init(&wdt->lock);

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res) {
		dev_err(&pdev->dev, "cannot obtain I/O memory region\n");
		return -ENXIO;
	}

	res = devm_request_mem_region(&pdev->dev, res->start,
			res->end - res->start + 1, res->name);
	if (!res) {
		dev_err(&pdev->dev, "cannot request I/O memory region\n");
		return -ENXIO;
	}

	wdt->base = devm_ioremap_nocache(&pdev->dev, res->start,
			res->end - res->start + 1);
	if (!wdt->base) {
		dev_err(&pdev->dev, "cannot remap I/O memory region\n");
		return -ENXIO;
	}

	/* disable watchdog and reboot on timeout */
	ctrl = readl(wdt->base + ADX_WDT_CONTROL);
	ctrl &= ~ADX_WDT_CONTROL_ENABLE;
	ctrl &= ~ADX_WDT_CONTROL_nRESET;
	writel(ctrl, wdt->base + ADX_WDT_CONTROL);

	platform_set_drvdata(pdev, wdt);
	adx_wdt_dev = pdev;

	ret = misc_register(&adx_wdt_miscdev);
	if (ret) {
		dev_err(&pdev->dev, "cannot register miscdev on minor %d "
				"(err=%d)\n", WATCHDOG_MINOR, ret);
		return ret;
	}

	return 0;
}

static int __devexit adx_wdt_remove(struct platform_device *pdev)
{
	struct adx_wdt *wdt = platform_get_drvdata(pdev);

	misc_deregister(&adx_wdt_miscdev);
	adx_wdt_stop(wdt);
	platform_set_drvdata(pdev, NULL);

	return 0;
}

static void adx_wdt_shutdown(struct platform_device *pdev)
{
	struct adx_wdt *wdt = platform_get_drvdata(pdev);
	adx_wdt_stop(wdt);
}

#ifdef CONFIG_PM
static int adx_wdt_suspend(struct device *dev)
{
	struct platform_device *pdev = to_platform_device(dev);
	struct adx_wdt *wdt = platform_get_drvdata(pdev);

	wdt->wake = (wdt->state == WDT_STATE_START) ? 1 : 0;
	adx_wdt_stop(wdt);

	return 0;
}

static int adx_wdt_resume(struct device *dev)
{
	struct platform_device *pdev = to_platform_device(dev);
	struct adx_wdt *wdt = platform_get_drvdata(pdev);

	if (wdt->wake)
		adx_wdt_start(wdt);

	return 0;
}

static struct dev_pm_ops adx_wdt_pm_ops = {
	.suspend = adx_wdt_suspend,
	.resume = adx_wdt_resume,
};

#  define ADX_WDT_PM_OPS	(&adx_wdt_pm_ops)
#else
#  define ADX_WDT_PM_OPS	NULL
#endif

static struct platform_driver adx_wdt_driver = {
	.probe = adx_wdt_probe,
	.remove = __devexit_p(adx_wdt_remove),
	.shutdown = adx_wdt_shutdown,
	.driver = {
		.name = WATCHDOG_NAME,
		.owner = THIS_MODULE,
		.pm = ADX_WDT_PM_OPS,
	},
};

static int __init adx_wdt_init(void)
{
	return platform_driver_register(&adx_wdt_driver);
}

static void __exit adx_wdt_exit(void)
{
	platform_driver_unregister(&adx_wdt_driver);
}

module_init(adx_wdt_init);
module_exit(adx_wdt_exit);

MODULE_DESCRIPTION("Avionic Design Xanthos Watchdog Driver");
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Thierry Reding <thierry.reding@avionic-design.de>");
MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
