/*
 * Copyright (c) 2021 ITE Corporation. All Rights Reserved.
 * SPDX-License-Identifier: Apache-2.0
 */

#define DT_DRV_COMPAT ite_it8xxx2_watchdog

#include <zephyr/drivers/watchdog.h>
#include <errno.h>
#include <soc.h>

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

#define IT8XXX2_WATCHDOG_MAGIC_BYTE			0x5c
#define WARNING_TIMER_PERIOD_MS_TO_1024HZ_COUNT(ms)	((ms) * 1024 / 1000)

/* enter critical period or not */
static int wdt_warning_fired;

/* device config */
struct wdt_it8xxx2_config {
	/* wdt register base address */
	struct wdt_it8xxx2_regs *base;
};

/* driver data */
struct wdt_it8xxx2_data {
	/* timeout callback used to handle watchdog event */
	wdt_callback_t callback;
	/* indicate whether a watchdog timeout is installed */
	bool timeout_installed;
	/* watchdog feed timeout in milliseconds */
	uint32_t timeout;
};

static int wdt_it8xxx2_install_timeout(const struct device *dev,
					  const struct wdt_timeout_cfg *config)
{
	const struct wdt_it8xxx2_config *const wdt_config = dev->config;
	struct wdt_it8xxx2_data *data = dev->data;
	struct wdt_it8xxx2_regs *const inst = wdt_config->base;

	/* if watchdog is already running */
	if ((inst->ETWCFG) & IT8XXX2_WDT_LEWDCNTL) {
		return -EBUSY;
	}

	/*
	 * Not support lower limit window timeouts (min value must be equal to
	 * 0). Upper limit window timeouts can't be 0 when we install timeout.
	 */
	if ((config->window.min != 0) || (config->window.max == 0)) {
		data->timeout_installed = false;
		return -EINVAL;
	}

	/* save watchdog timeout */
	data->timeout = config->window.max;

	/* install user timeout isr */
	data->callback = config->callback;

	/* mark installed */
	data->timeout_installed = true;

	return 0;
}

static int wdt_it8xxx2_setup(const struct device *dev, uint8_t options)
{
	const struct wdt_it8xxx2_config *const wdt_config = dev->config;
	struct wdt_it8xxx2_data *data = dev->data;
	struct wdt_it8xxx2_regs *const inst = wdt_config->base;
	uint16_t cnt0 = WARNING_TIMER_PERIOD_MS_TO_1024HZ_COUNT(data->timeout);
	uint16_t cnt1 = WARNING_TIMER_PERIOD_MS_TO_1024HZ_COUNT((data->timeout
			+ CONFIG_WDT_ITE_WARNING_LEADING_TIME_MS));

	/* disable pre-warning timer1 interrupt */
	irq_disable(DT_INST_IRQN(0));

	if (!data->timeout_installed) {
		LOG_ERR("No valid WDT timeout installed");
		return -EINVAL;
	}

	if ((inst->ETWCFG) & IT8XXX2_WDT_LEWDCNTL) {
		LOG_ERR("WDT is already running");
		return -EBUSY;
	}

	if ((options & WDT_OPT_PAUSE_IN_SLEEP) != 0) {
		LOG_ERR("WDT_OPT_PAUSE_IN_SLEEP is not supported");
		return -ENOTSUP;
	}

	/* pre-warning timer1 is 16-bit counter down timer */
	inst->ET1CNTLHR = (cnt0 >> 8) & 0xff;
	inst->ET1CNTLLR = cnt0 & 0xff;

	/* clear pre-warning timer1 interrupt status */
	ite_intc_isr_clear(DT_INST_IRQN(0));

	/* enable pre-warning timer1 interrupt */
	irq_enable(DT_INST_IRQN(0));

	/* don't stop watchdog timer counting */
	inst->ETWCTRL &= ~IT8XXX2_WDT_EWDSCEN;

	/* set watchdog timer count */
	inst->EWDCNTHR = (cnt1 >> 8) & 0xff;
	inst->EWDCNTLR = cnt1 & 0xff;

	/* allow to write timer1 count register */
	inst->ETWCFG &= ~IT8XXX2_WDT_LET1CNTL;

	/*
	 * bit5 = 1: enable key match function to touch watchdog
	 * bit4 = 1: select watchdog clock source from prescaler
	 * bit3 = 1: lock watchdog count register (also mark as watchdog running)
	 * bit1 = 1: lock timer1 prescaler register
	 */
	inst->ETWCFG = (IT8XXX2_WDT_EWDKEYEN |
			IT8XXX2_WDT_EWDSRC |
			IT8XXX2_WDT_LEWDCNTL |
			IT8XXX2_WDT_LET1PS);

	LOG_DBG("WDT Setup and enabled");

	return 0;
}

/*
 * reload the WDT and pre-warning timer1 counter
 *
 * @param dev Pointer to the device structure for the driver instance.
 * @param channel_id Index of the fed channel, and we only support
 *                   channel_id = 0 now.
 */
static int wdt_it8xxx2_feed(const struct device *dev, int channel_id)
{
	const struct wdt_it8xxx2_config *const wdt_config = dev->config;
	struct wdt_it8xxx2_data *data = dev->data;
	struct wdt_it8xxx2_regs *const inst = wdt_config->base;
	uint16_t cnt0 = WARNING_TIMER_PERIOD_MS_TO_1024HZ_COUNT(data->timeout);

	ARG_UNUSED(channel_id);

	/* reset pre-warning timer1 */
	inst->ETWCTRL |= IT8XXX2_WDT_ET1RST;

	/* restart watchdog timer */
	inst->EWDKEYR = IT8XXX2_WATCHDOG_MAGIC_BYTE;

	/* reset pre-warning timer1 to default if time is touched */
	if (wdt_warning_fired) {
		wdt_warning_fired = 0;

		/* pre-warning timer1 is 16-bit counter down timer */
		inst->ET1CNTLHR = (cnt0 >> 8) & 0xff;
		inst->ET1CNTLLR = cnt0 & 0xff;

		/* clear timer1 interrupt status */
		ite_intc_isr_clear(DT_INST_IRQN(0));

		/* enable timer1 interrupt */
		irq_enable(DT_INST_IRQN(0));
	}

	LOG_DBG("WDT Kicking");

	return 0;
}

static int wdt_it8xxx2_disable(const struct device *dev)
{
	const struct wdt_it8xxx2_config *const wdt_config = dev->config;
	struct wdt_it8xxx2_data *data = dev->data;
	struct wdt_it8xxx2_regs *const inst = wdt_config->base;

	/* stop watchdog timer counting */
	inst->ETWCTRL |= IT8XXX2_WDT_EWDSCEN;

	/* unlock watchdog count register (also mark as watchdog not running) */
	inst->ETWCFG &= ~IT8XXX2_WDT_LEWDCNTL;

	/* disable pre-warning timer1 interrupt */
	irq_disable(DT_INST_IRQN(0));

	/* mark uninstalled */
	data->timeout_installed = false;

	LOG_DBG("WDT Disabled");

	return 0;
}

static void wdt_it8xxx2_isr(const struct device *dev)
{
	const struct wdt_it8xxx2_config *const wdt_config = dev->config;
	struct wdt_it8xxx2_data *data = dev->data;
	struct wdt_it8xxx2_regs *const inst = wdt_config->base;

	/* clear pre-warning timer1 interrupt status */
	ite_intc_isr_clear(DT_INST_IRQN(0));

	/* reset pre-warning timer1 */
	inst->ETWCTRL |= IT8XXX2_WDT_ET1RST;

	/* callback function, ex. print warning message */
	if (data->callback) {
		data->callback(dev, 0);
	}

	if (IS_ENABLED(CONFIG_WDT_ITE_REDUCE_WARNING_LEADING_TIME)) {
		/*
		 * Once warning timer triggered: if watchdog timer isn't reloaded,
		 * then we will reduce interval of warning timer to 30ms to print
		 * more warning messages before watchdog reset.
		 */
		if (!wdt_warning_fired) {
			uint16_t cnt0 = WARNING_TIMER_PERIOD_MS_TO_1024HZ_COUNT(30);

			/* pre-warning timer1 is 16-bit counter down timer */
			inst->ET1CNTLHR = (cnt0 >> 8) & 0xff;
			inst->ET1CNTLLR = cnt0 & 0xff;

			/* clear pre-warning timer1 interrupt status */
			ite_intc_isr_clear(DT_INST_IRQN(0));
		}
	}
	wdt_warning_fired++;

	LOG_DBG("WDT ISR");
}

static const struct wdt_driver_api wdt_it8xxx2_api = {
	.setup = wdt_it8xxx2_setup,
	.disable = wdt_it8xxx2_disable,
	.install_timeout = wdt_it8xxx2_install_timeout,
	.feed = wdt_it8xxx2_feed,
};

static int wdt_it8xxx2_init(const struct device *dev)
{
	const struct wdt_it8xxx2_config *const wdt_config = dev->config;
	struct wdt_it8xxx2_regs *const inst = wdt_config->base;

	if (IS_ENABLED(CONFIG_WDT_DISABLE_AT_BOOT)) {
		wdt_it8xxx2_disable(dev);
	}

	/* unlock access to watchdog registers */
	inst->ETWCFG = 0x00;

	/* set WDT and timer1 to use 1.024kHz clock */
	inst->ET1PSR = IT8XXX2_WDT_ETPS_1P024_KHZ;

	/* set WDT key match enabled and WDT clock to use ET1PSR */
	inst->ETWCFG = (IT8XXX2_WDT_EWDKEYEN |
			IT8XXX2_WDT_EWDSRC);

	/*
	 * select the mode that watchdog can be stopped, this is needed for
	 * wdt_it8xxx2_disable() api and WDT_OPT_PAUSE_HALTED_BY_DBG flag
	 */
	inst->ETWCTRL |= IT8XXX2_WDT_EWDSCMS;

	IRQ_CONNECT(DT_INST_IRQN(0), 0, wdt_it8xxx2_isr,
		    DEVICE_DT_INST_GET(0), 0);
	return 0;
}

static const struct wdt_it8xxx2_config wdt_it8xxx2_cfg_0 = {
	.base = (struct wdt_it8xxx2_regs *)DT_INST_REG_ADDR(0),
};

static struct wdt_it8xxx2_data wdt_it8xxx2_dev_data;

DEVICE_DT_INST_DEFINE(0, wdt_it8xxx2_init, NULL,
			&wdt_it8xxx2_dev_data, &wdt_it8xxx2_cfg_0,
			PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
			&wdt_it8xxx2_api);
