// SPDX-License-Identifier: GPL-2.0
/*
 * Renesas RZ/A Series WDT Driver
 *
 * Copyright (C) 2017 Renesas Electronics America, Inc.
 * Copyright (C) 2017 Chris Brandt
 */

#include <linux/bitops.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/watchdog.h>

#define DEFAULT_TIMEOUT		30

/* Watchdog Timer Registers */
#define WTCSR			0
#define WTCSR_MAGIC		0xA500
#define WTSCR_WT		BIT(6)
#define WTSCR_TME		BIT(5)
#define WTSCR_CKS(i)		(i)

#define WTCNT			2
#define WTCNT_MAGIC		0x5A00

#define WRCSR			4
#define WRCSR_MAGIC		0x5A00
#define WRCSR_RSTE		BIT(6)
#define WRCSR_CLEAR_WOVF	0xA500	/* special value */

/* The maximum CKS register setting value to get the longest timeout */
#define CKS_3BIT		0x7
#define CKS_4BIT		0xF

#define DIVIDER_3BIT		16384	/* Clock divider when CKS = 0x7 */
#define DIVIDER_4BIT		4194304	/* Clock divider when CKS = 0xF */

struct rza_wdt {
	struct watchdog_device wdev;
	void __iomem *base;
	struct clk *clk;
	u8 count;
	u8 cks;
};

static void rza_wdt_calc_timeout(struct rza_wdt *priv, int timeout)
{
	unsigned long rate = clk_get_rate(priv->clk);
	unsigned int ticks;

	if (priv->cks == CKS_4BIT) {
		ticks = DIV_ROUND_UP(timeout * rate, DIVIDER_4BIT);

		/*
		 * Since max_timeout was set in probe, we know that the timeout
		 * value passed will never calculate to a tick value greater
		 * than 256.
		 */
		priv->count = 256 - ticks;

	} else {
		/* Start timer with longest timeout */
		priv->count = 0;
	}

	pr_debug("%s: timeout set to %u (WTCNT=%d)\n", __func__,
		 timeout, priv->count);
}

static int rza_wdt_start(struct watchdog_device *wdev)
{
	struct rza_wdt *priv = watchdog_get_drvdata(wdev);

	/* Stop timer */
	writew(WTCSR_MAGIC | 0, priv->base + WTCSR);

	/* Must dummy read WRCSR:WOVF at least once before clearing */
	readb(priv->base + WRCSR);
	writew(WRCSR_CLEAR_WOVF, priv->base + WRCSR);

	rza_wdt_calc_timeout(priv, wdev->timeout);

	writew(WRCSR_MAGIC | WRCSR_RSTE, priv->base + WRCSR);
	writew(WTCNT_MAGIC | priv->count, priv->base + WTCNT);
	writew(WTCSR_MAGIC | WTSCR_WT | WTSCR_TME |
	       WTSCR_CKS(priv->cks), priv->base + WTCSR);

	return 0;
}

static int rza_wdt_stop(struct watchdog_device *wdev)
{
	struct rza_wdt *priv = watchdog_get_drvdata(wdev);

	writew(WTCSR_MAGIC | 0, priv->base + WTCSR);

	return 0;
}

static int rza_wdt_ping(struct watchdog_device *wdev)
{
	struct rza_wdt *priv = watchdog_get_drvdata(wdev);

	writew(WTCNT_MAGIC | priv->count, priv->base + WTCNT);

	pr_debug("%s: timeout = %u\n", __func__, wdev->timeout);

	return 0;
}

static int rza_set_timeout(struct watchdog_device *wdev, unsigned int timeout)
{
	wdev->timeout = timeout;
	rza_wdt_start(wdev);
	return 0;
}

static int rza_wdt_restart(struct watchdog_device *wdev, unsigned long action,
			    void *data)
{
	struct rza_wdt *priv = watchdog_get_drvdata(wdev);

	/* Stop timer */
	writew(WTCSR_MAGIC | 0, priv->base + WTCSR);

	/* Must dummy read WRCSR:WOVF at least once before clearing */
	readb(priv->base + WRCSR);
	writew(WRCSR_CLEAR_WOVF, priv->base + WRCSR);

	/*
	 * Start timer with fastest clock source and only 1 clock left before
	 * overflow with reset option enabled.
	 */
	writew(WRCSR_MAGIC | WRCSR_RSTE, priv->base + WRCSR);
	writew(WTCNT_MAGIC | 255, priv->base + WTCNT);
	writew(WTCSR_MAGIC | WTSCR_WT | WTSCR_TME, priv->base + WTCSR);

	/*
	 * Actually make sure the above sequence hits hardware before sleeping.
	 */
	wmb();

	/* Wait for WDT overflow (reset) */
	udelay(20);

	return 0;
}

static const struct watchdog_info rza_wdt_ident = {
	.options = WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT,
	.identity = "Renesas RZ/A WDT Watchdog",
};

static const struct watchdog_ops rza_wdt_ops = {
	.owner = THIS_MODULE,
	.start = rza_wdt_start,
	.stop = rza_wdt_stop,
	.ping = rza_wdt_ping,
	.set_timeout = rza_set_timeout,
	.restart = rza_wdt_restart,
};

static int rza_wdt_probe(struct platform_device *pdev)
{
	struct rza_wdt *priv;
	struct resource *res;
	unsigned long rate;
	int ret;

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

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	priv->base = devm_ioremap_resource(&pdev->dev, res);
	if (IS_ERR(priv->base))
		return PTR_ERR(priv->base);

	priv->clk = devm_clk_get(&pdev->dev, NULL);
	if (IS_ERR(priv->clk))
		return PTR_ERR(priv->clk);

	rate = clk_get_rate(priv->clk);
	if (rate < 16384) {
		dev_err(&pdev->dev, "invalid clock rate (%ld)\n", rate);
		return -ENOENT;
	}

	priv->wdev.info = &rza_wdt_ident,
	priv->wdev.ops = &rza_wdt_ops,
	priv->wdev.parent = &pdev->dev;

	priv->cks = (u8)(uintptr_t)of_device_get_match_data(&pdev->dev);
	if (priv->cks == CKS_4BIT) {
		/* Assume slowest clock rate possible (CKS=0xF) */
		priv->wdev.max_timeout = (DIVIDER_4BIT * U8_MAX) / rate;

	} else if (priv->cks == CKS_3BIT) {
		/* Assume slowest clock rate possible (CKS=7) */
		rate /= DIVIDER_3BIT;

		/*
		 * Since the max possible timeout of our 8-bit count
		 * register is less than a second, we must use
		 * max_hw_heartbeat_ms.
		 */
		priv->wdev.max_hw_heartbeat_ms = (1000 * U8_MAX) / rate;
		dev_dbg(&pdev->dev, "max hw timeout of %dms\n",
			 priv->wdev.max_hw_heartbeat_ms);
	}

	priv->wdev.min_timeout = 1;
	priv->wdev.timeout = DEFAULT_TIMEOUT;

	watchdog_init_timeout(&priv->wdev, 0, &pdev->dev);
	watchdog_set_drvdata(&priv->wdev, priv);

	ret = devm_watchdog_register_device(&pdev->dev, &priv->wdev);
	if (ret)
		dev_err(&pdev->dev, "Cannot register watchdog device\n");

	return ret;
}

static const struct of_device_id rza_wdt_of_match[] = {
	{ .compatible = "renesas,r7s9210-wdt",	.data = (void *)CKS_4BIT, },
	{ .compatible = "renesas,rza-wdt",	.data = (void *)CKS_3BIT, },
	{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, rza_wdt_of_match);

static struct platform_driver rza_wdt_driver = {
	.probe = rza_wdt_probe,
	.driver = {
		.name = "rza_wdt",
		.of_match_table = rza_wdt_of_match,
	},
};

module_platform_driver(rza_wdt_driver);

MODULE_DESCRIPTION("Renesas RZ/A WDT Driver");
MODULE_AUTHOR("Chris Brandt <chris.brandt@renesas.com>");
MODULE_LICENSE("GPL v2");
