/*
 * Retu watchdog driver
 *
 * Copyright (C) 2004, 2005 Nokia Corporation
 *
 * Based on code written by Amit Kucheria and Michael Buesch.
 * Rewritten by Aaro Koskinen.
 *
 * This file is subject to the terms and conditions of the GNU General
 * Public License. See the file "COPYING" in the main directory of this
 * archive for more details.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 */

#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mfd/retu.h>
#include <linux/watchdog.h>
#include <linux/platform_device.h>

/* Watchdog timer values in seconds */
#define RETU_WDT_MAX_TIMER	63

struct retu_wdt_dev {
	struct retu_dev		*rdev;
	struct device		*dev;
	struct delayed_work	ping_work;
};

/*
 * Since Retu watchdog cannot be disabled in hardware, we must kick it
 * with a timer until userspace watchdog software takes over. If
 * CONFIG_WATCHDOG_NOWAYOUT is set, we never start the feeding.
 */
static void retu_wdt_ping_enable(struct retu_wdt_dev *wdev)
{
	retu_write(wdev->rdev, RETU_REG_WATCHDOG, RETU_WDT_MAX_TIMER);
	schedule_delayed_work(&wdev->ping_work,
			round_jiffies_relative(RETU_WDT_MAX_TIMER * HZ / 2));
}

static void retu_wdt_ping_disable(struct retu_wdt_dev *wdev)
{
	retu_write(wdev->rdev, RETU_REG_WATCHDOG, RETU_WDT_MAX_TIMER);
	cancel_delayed_work_sync(&wdev->ping_work);
}

static void retu_wdt_ping_work(struct work_struct *work)
{
	struct retu_wdt_dev *wdev = container_of(to_delayed_work(work),
						struct retu_wdt_dev, ping_work);
	retu_wdt_ping_enable(wdev);
}

static int retu_wdt_start(struct watchdog_device *wdog)
{
	struct retu_wdt_dev *wdev = watchdog_get_drvdata(wdog);

	retu_wdt_ping_disable(wdev);

	return retu_write(wdev->rdev, RETU_REG_WATCHDOG, wdog->timeout);
}

static int retu_wdt_stop(struct watchdog_device *wdog)
{
	struct retu_wdt_dev *wdev = watchdog_get_drvdata(wdog);

	retu_wdt_ping_enable(wdev);

	return 0;
}

static int retu_wdt_ping(struct watchdog_device *wdog)
{
	struct retu_wdt_dev *wdev = watchdog_get_drvdata(wdog);

	return retu_write(wdev->rdev, RETU_REG_WATCHDOG, wdog->timeout);
}

static int retu_wdt_set_timeout(struct watchdog_device *wdog,
				unsigned int timeout)
{
	struct retu_wdt_dev *wdev = watchdog_get_drvdata(wdog);

	wdog->timeout = timeout;
	return retu_write(wdev->rdev, RETU_REG_WATCHDOG, wdog->timeout);
}

static const struct watchdog_info retu_wdt_info = {
	.options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING,
	.identity = "Retu watchdog",
};

static const struct watchdog_ops retu_wdt_ops = {
	.owner		= THIS_MODULE,
	.start		= retu_wdt_start,
	.stop		= retu_wdt_stop,
	.ping		= retu_wdt_ping,
	.set_timeout	= retu_wdt_set_timeout,
};

static int retu_wdt_probe(struct platform_device *pdev)
{
	struct retu_dev *rdev = dev_get_drvdata(pdev->dev.parent);
	bool nowayout = WATCHDOG_NOWAYOUT;
	struct watchdog_device *retu_wdt;
	struct retu_wdt_dev *wdev;
	int ret;

	retu_wdt = devm_kzalloc(&pdev->dev, sizeof(*retu_wdt), GFP_KERNEL);
	if (!retu_wdt)
		return -ENOMEM;

	wdev = devm_kzalloc(&pdev->dev, sizeof(*wdev), GFP_KERNEL);
	if (!wdev)
		return -ENOMEM;

	retu_wdt->info		= &retu_wdt_info;
	retu_wdt->ops		= &retu_wdt_ops;
	retu_wdt->timeout	= RETU_WDT_MAX_TIMER;
	retu_wdt->min_timeout	= 0;
	retu_wdt->max_timeout	= RETU_WDT_MAX_TIMER;
	retu_wdt->parent	= &pdev->dev;

	watchdog_set_drvdata(retu_wdt, wdev);
	watchdog_set_nowayout(retu_wdt, nowayout);

	wdev->rdev		= rdev;
	wdev->dev		= &pdev->dev;

	INIT_DELAYED_WORK(&wdev->ping_work, retu_wdt_ping_work);

	ret = watchdog_register_device(retu_wdt);
	if (ret < 0)
		return ret;

	if (nowayout)
		retu_wdt_ping(retu_wdt);
	else
		retu_wdt_ping_enable(wdev);

	platform_set_drvdata(pdev, retu_wdt);

	return 0;
}

static int retu_wdt_remove(struct platform_device *pdev)
{
	struct watchdog_device *wdog = platform_get_drvdata(pdev);
	struct retu_wdt_dev *wdev = watchdog_get_drvdata(wdog);

	watchdog_unregister_device(wdog);
	cancel_delayed_work_sync(&wdev->ping_work);

	return 0;
}

static struct platform_driver retu_wdt_driver = {
	.probe		= retu_wdt_probe,
	.remove		= retu_wdt_remove,
	.driver		= {
		.name	= "retu-wdt",
	},
};
module_platform_driver(retu_wdt_driver);

MODULE_ALIAS("platform:retu-wdt");
MODULE_DESCRIPTION("Retu watchdog");
MODULE_AUTHOR("Amit Kucheria");
MODULE_AUTHOR("Aaro Koskinen <aaro.koskinen@iki.fi>");
MODULE_LICENSE("GPL");
