/*
 * Copyright (C) 2020 Katsuhiro Suzuki
 *
 * SPDX-License-Identifier: Apache-2.0
 */

/**
 * @brief Watchdog (WDT) Driver for SiFive Freedom
 */

#define DT_DRV_COMPAT sifive_wdt

#include <kernel.h>
#include <soc.h>
#include <drivers/watchdog.h>

#define LOG_LEVEL CONFIG_WDT_LOG_LEVEL
#include <logging/log.h>
LOG_MODULE_REGISTER(wdt_sifive);

#define WDOGCFG_SCALE_MAX     0xf
#define WDOGCFG_SCALE_SHIFT   0
#define WDOGCFG_SCALE_MASK    (WDOGCFG_SCALE_MAX << WDOGCFG_SCALE_SHIFT)
#define WDOGCFG_RSTEN         BIT(8)
#define WDOGCFG_ZEROCMP       BIT(9)
#define WDOGCFG_ENALWAYS      BIT(12)
#define WDOGCFG_COREAWAKE     BIT(13)
#define WDOGCFG_IP0           BIT(28)

#define WDOGCMP_MAX        0xffff

#define WDOG_KEY           0x51f15e
#define WDOG_FEED          0xd09f00d

#define WDOG_CLK           32768

struct wdt_sifive_reg {
	/* offset: 0x000 */
	uint32_t wdogcfg;
	uint32_t dummy0;
	uint32_t wdogcount;
	uint32_t dummy1;
	/* offset: 0x010 */
	uint32_t wdogs;
	uint32_t dummy2;
	uint32_t wdogfeed;
	uint32_t wdogkey;
	/* offset: 0x020 */
	uint32_t wdogcmp0;
};

struct wdt_sifive_device_config {
	uintptr_t regs;
};

struct wdt_sifive_dev_data {
	wdt_callback_t cb;
	bool enable_cb;
	bool timeout_valid;
};

#define DEV_CFG(dev) \
	((const struct wdt_sifive_device_config *const)(dev)->config)
#define DEV_REG(dev) \
	((struct wdt_sifive_reg *)(DEV_CFG(dev))->regs)

/**
 * @brief Set maximum length of timeout to watchdog
 *
 * @param dev Watchdog device struct
 */
static void wdt_sifive_set_max_timeout(const struct device *dev)
{
	volatile struct wdt_sifive_reg *wdt = DEV_REG(dev);
	uint32_t t;

	t = wdt->wdogcfg;
	t |= WDOGCFG_SCALE_MASK;

	wdt->wdogkey = WDOG_KEY;
	wdt->wdogcfg = t;
	wdt->wdogkey = WDOG_KEY;
	wdt->wdogcmp0 = WDOGCMP_MAX;
}

static void wdt_sifive_isr(const struct device *dev)
{
	volatile struct wdt_sifive_reg *wdt = DEV_REG(dev);
	struct wdt_sifive_dev_data *data = dev->data;
	uint32_t t;

	wdt_sifive_set_max_timeout(dev);

	t = wdt->wdogcfg;
	t &= ~WDOGCFG_IP0;

	wdt->wdogkey = WDOG_KEY;
	wdt->wdogcfg = t;

	if (data->enable_cb && data->cb) {
		data->enable_cb = false;
		data->cb(dev, 0);
	}
}

static int wdt_sifive_disable(const struct device *dev)
{
	struct wdt_sifive_dev_data *data = dev->data;

	wdt_sifive_set_max_timeout(dev);

	data->enable_cb = false;

	return 0;
}

static int wdt_sifive_setup(const struct device *dev, uint8_t options)
{
	volatile struct wdt_sifive_reg *wdt = DEV_REG(dev);
	struct wdt_sifive_dev_data *data = dev->data;
	uint32_t t, mode;

	if (!data->timeout_valid) {
		LOG_ERR("No valid timeouts installed");
		return -EINVAL;
	}

	mode = WDOGCFG_ENALWAYS;
	if ((options & WDT_OPT_PAUSE_IN_SLEEP) ==
	    WDT_OPT_PAUSE_IN_SLEEP) {
		mode = WDOGCFG_COREAWAKE;
	}
	if ((options & WDT_OPT_PAUSE_HALTED_BY_DBG) ==
	    WDT_OPT_PAUSE_HALTED_BY_DBG) {
		mode = WDOGCFG_COREAWAKE;
	}

	t = wdt->wdogcfg;
	t &= ~(WDOGCFG_ENALWAYS | WDOGCFG_COREAWAKE);
	t |= mode;

	wdt->wdogkey = WDOG_KEY;
	wdt->wdogcfg = t;

	return 0;
}

/**
 * @brief Calculates the watchdog counter value (wdogcmp0) and
 *        scaler (wdogscale) to be installed in the watchdog timer
 *
 * @param timeout Timeout value in milliseconds.
 * @param clk     Clock of watchdog in Hz.
 * @param scaler  Pointer to return scaler power of 2
 *
 * @return Watchdog counter value
 */
static int wdt_sifive_convtime(uint32_t timeout, int clk, int *scaler)
{
	uint64_t cnt;
	int i;

	cnt = (uint64_t)timeout * clk / 1000;
	for (i = 0; i < 16; i++) {
		if (cnt <= WDOGCMP_MAX) {
			break;
		}

		cnt >>= 1;
	}

	if (i == 16) {
		/* Maximum counter and scaler */
		LOG_ERR("Invalid timeout value allowed range");

		*scaler = WDOGCFG_SCALE_MAX;
		return WDOGCMP_MAX;
	}

	*scaler = i;

	return cnt;
}

static int wdt_sifive_install_timeout(const struct device *dev,
				      const struct wdt_timeout_cfg *cfg)
{
	volatile struct wdt_sifive_reg *wdt = DEV_REG(dev);
	struct wdt_sifive_dev_data *data = dev->data;
	uint32_t mode = 0, t;
	int cmp, scaler;

	if (data->timeout_valid) {
		LOG_ERR("No more timeouts can be installed");
		return -ENOMEM;
	}
	if (cfg->window.min != 0U || cfg->window.max == 0U) {
		return -EINVAL;
	}

	/*
	 * Freedom watchdog does not support window timeout config.
	 * So use max field of window.
	 */
	cmp = wdt_sifive_convtime(cfg->window.max, WDOG_CLK, &scaler);
	if (cmp < 0 || WDOGCMP_MAX < cmp) {
		LOG_ERR("Unsupported watchdog timeout\n");
		return -EINVAL;
	}

	switch (cfg->flags) {
	case WDT_FLAG_RESET_SOC:
		/* WDT supports global SoC reset but cannot callback. */
		mode = WDOGCFG_RSTEN | WDOGCFG_ZEROCMP;
		break;
	case WDT_FLAG_RESET_NONE:
		/* No reset */
		mode = WDOGCFG_ZEROCMP;
		break;
	case WDT_FLAG_RESET_CPU_CORE:
	default:
		LOG_ERR("Unsupported watchdog config flags\n");

		wdt_sifive_disable(dev);
		return -ENOTSUP;
	}

	t = wdt->wdogcfg;
	t &= ~(WDOGCFG_RSTEN | WDOGCFG_ZEROCMP | WDOGCFG_SCALE_MASK);
	t |= mode | scaler;

	wdt->wdogkey = WDOG_KEY;
	wdt->wdogcfg = t;
	wdt->wdogkey = WDOG_KEY;
	wdt->wdogcmp0 = cmp;

	data->cb = cfg->callback;
	data->enable_cb = true;
	data->timeout_valid = true;

	return 0;
}

static int wdt_sifive_feed(const struct device *dev, int channel_id)
{
	volatile struct wdt_sifive_reg *wdt = DEV_REG(dev);

	wdt->wdogkey = WDOG_KEY;
	wdt->wdogfeed = WDOG_FEED;

	return 0;
}

static const struct wdt_driver_api wdt_sifive_api = {
	.setup = wdt_sifive_setup,
	.disable = wdt_sifive_disable,
	.install_timeout = wdt_sifive_install_timeout,
	.feed = wdt_sifive_feed,
};

static void wdt_sifive_irq_config(void)
{
	IRQ_CONNECT(DT_INST_IRQN(0),
		    DT_INST_IRQ(0, priority), wdt_sifive_isr,
		    DEVICE_DT_INST_GET(0), 0);
	irq_enable(DT_INST_IRQN(0));
}

static int wdt_sifive_init(const struct device *dev)
{
#ifdef CONFIG_WDT_DISABLE_AT_BOOT
	wdt_sifive_disable(dev);
#endif
	wdt_sifive_irq_config();

	return 0;
}

static struct wdt_sifive_dev_data wdt_sifive_data;

static const struct wdt_sifive_device_config wdt_sifive_cfg = {
	.regs = DT_INST_REG_ADDR(0),
};

DEVICE_DT_INST_DEFINE(0, wdt_sifive_init, NULL,
		      &wdt_sifive_data, &wdt_sifive_cfg, PRE_KERNEL_1,
		      CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &wdt_sifive_api);
