// SPDX-License-Identifier: GPL-2.0
/*
 * Renesas RZ/N1 Watchdog timer.
 * This is a 12-bit timer driver from a (62.5/16384) MHz clock. It can't even
 * cope with 2 seconds.
 *
 * Copyright 2018 Renesas Electronics Europe Ltd.
 *
 * Derived from Ralink RT288x watchdog timer.
 */

#include <linux/clk.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/platform_device.h>
#include <linux/reboot.h>
#include <linux/watchdog.h>

#define DEFAULT_TIMEOUT		60

#define RZN1_WDT_RETRIGGER			0x0
#define RZN1_WDT_RETRIGGER_RELOAD_VAL		0
#define RZN1_WDT_RETRIGGER_RELOAD_VAL_MASK	0xfff
#define RZN1_WDT_RETRIGGER_PRESCALE		BIT(12)
#define RZN1_WDT_RETRIGGER_ENABLE		BIT(13)
#define RZN1_WDT_RETRIGGER_WDSI			(0x2 << 14)

#define RZN1_WDT_PRESCALER			16384
#define RZN1_WDT_MAX				4095

struct rzn1_watchdog {
	struct watchdog_device		wdtdev;
	void __iomem			*base;
	unsigned long			clk_rate_khz;
};

static inline uint32_t max_heart_beat_ms(unsigned long clk_rate_khz)
{
	return (RZN1_WDT_MAX * RZN1_WDT_PRESCALER) / clk_rate_khz;
}

static inline uint32_t compute_reload_value(uint32_t tick_ms,
					    unsigned long clk_rate_khz)
{
	return (tick_ms * clk_rate_khz) / RZN1_WDT_PRESCALER;
}

static int rzn1_wdt_ping(struct watchdog_device *w)
{
	struct rzn1_watchdog *wdt = watchdog_get_drvdata(w);

	/* Any value retrigggers the watchdog */
	writel(0, wdt->base + RZN1_WDT_RETRIGGER);

	return 0;
}

static int rzn1_wdt_start(struct watchdog_device *w)
{
	struct rzn1_watchdog *wdt = watchdog_get_drvdata(w);
	u32 val;

	/*
	 * The hardware allows you to write to this reg only once.
	 * Since this includes the reload value, there is no way to change the
	 * timeout once started. Also note that the WDT clock is half the bus
	 * fabric clock rate, so if the bus fabric clock rate is changed after
	 * the WDT is started, the WDT interval will be wrong.
	 */
	val = RZN1_WDT_RETRIGGER_WDSI;
	val |= RZN1_WDT_RETRIGGER_ENABLE;
	val |= RZN1_WDT_RETRIGGER_PRESCALE;
	val |= compute_reload_value(w->max_hw_heartbeat_ms, wdt->clk_rate_khz);
	writel(val, wdt->base + RZN1_WDT_RETRIGGER);

	return 0;
}

static irqreturn_t rzn1_wdt_irq(int irq, void *_wdt)
{
	pr_crit("RZN1 Watchdog. Initiating system reboot\n");
	emergency_restart();

	return IRQ_HANDLED;
}

static struct watchdog_info rzn1_wdt_info = {
	.identity = "RZ/N1 Watchdog",
	.options = WDIOF_MAGICCLOSE | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
};

static const struct watchdog_ops rzn1_wdt_ops = {
	.owner = THIS_MODULE,
	.start = rzn1_wdt_start,
	.ping = rzn1_wdt_ping,
};

static void rzn1_wdt_clk_disable_unprepare(void *data)
{
	clk_disable_unprepare(data);
}

static int rzn1_wdt_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct rzn1_watchdog *wdt;
	struct device_node *np = dev->of_node;
	struct clk *clk;
	unsigned long clk_rate;
	int ret;
	int irq;

	wdt = devm_kzalloc(dev, sizeof(*wdt), GFP_KERNEL);
	if (!wdt)
		return -ENOMEM;

	wdt->base = devm_platform_ioremap_resource(pdev, 0);
	if (IS_ERR(wdt->base))
		return PTR_ERR(wdt->base);

	irq = platform_get_irq(pdev, 0);
	if (irq < 0)
		return irq;

	ret = devm_request_irq(dev, irq, rzn1_wdt_irq, 0,
			       np->name, wdt);
	if (ret) {
		dev_err(dev, "failed to request irq %d\n", irq);
		return ret;
	}

	clk = devm_clk_get(dev, NULL);
	if (IS_ERR(clk)) {
		dev_err(dev, "failed to get the clock\n");
		return PTR_ERR(clk);
	}

	ret = clk_prepare_enable(clk);
	if (ret) {
		dev_err(dev, "failed to prepare/enable the clock\n");
		return ret;
	}

	ret = devm_add_action_or_reset(dev, rzn1_wdt_clk_disable_unprepare,
				       clk);
	if (ret)
		return ret;

	clk_rate = clk_get_rate(clk);
	if (!clk_rate) {
		dev_err(dev, "failed to get the clock rate\n");
		return -EINVAL;
	}

	wdt->clk_rate_khz = clk_rate / 1000;
	wdt->wdtdev.info = &rzn1_wdt_info,
	wdt->wdtdev.ops = &rzn1_wdt_ops,
	wdt->wdtdev.status = WATCHDOG_NOWAYOUT_INIT_STATUS,
	wdt->wdtdev.parent = dev;
	/*
	 * The period of the watchdog cannot be changed once set
	 * and is limited to a very short period.
	 * Configure it for a 1s period once and for all, and
	 * rely on the heart-beat provided by the watchdog core
	 * to make this usable by the user-space.
	 */
	wdt->wdtdev.max_hw_heartbeat_ms = max_heart_beat_ms(wdt->clk_rate_khz);
	if (wdt->wdtdev.max_hw_heartbeat_ms > 1000)
		wdt->wdtdev.max_hw_heartbeat_ms = 1000;

	wdt->wdtdev.timeout = DEFAULT_TIMEOUT;
	ret = watchdog_init_timeout(&wdt->wdtdev, 0, dev);
	if (ret)
		return ret;

	watchdog_set_drvdata(&wdt->wdtdev, wdt);

	return devm_watchdog_register_device(dev, &wdt->wdtdev);
}


static const struct of_device_id rzn1_wdt_match[] = {
	{ .compatible = "renesas,rzn1-wdt" },
	{},
};
MODULE_DEVICE_TABLE(of, rzn1_wdt_match);

static struct platform_driver rzn1_wdt_driver = {
	.probe		= rzn1_wdt_probe,
	.driver		= {
		.name		= KBUILD_MODNAME,
		.of_match_table	= rzn1_wdt_match,
	},
};

module_platform_driver(rzn1_wdt_driver);

MODULE_DESCRIPTION("Renesas RZ/N1 hardware watchdog");
MODULE_AUTHOR("Phil Edworthy <phil.edworthy@renesas.com>");
MODULE_LICENSE("GPL");
