/*
 * Copyright (c) 2022 Intel Corporation
 *
 * SPDX-License-Identifier: Apache-2.0
 */
#define DT_DRV_COMPAT intel_tco_wdt

#include <zephyr/kernel.h>
#include <zephyr/drivers/watchdog.h>
#include <zephyr/logging/log.h>

LOG_MODULE_REGISTER(wdt_tco, CONFIG_WDT_LOG_LEVEL);

#define TCO_WDT_NODE           DT_NODELABEL(tco_wdt)

#define BASE(d)                ((struct tco_config *)(d)->config)->base

#define TCO_RLD(d)             (BASE(d) + 0x00) /* TCO Timer Reload/Curr. Value */
#define TCO_DAT_IN(d)          (BASE(d) + 0x02) /* TCO Data In Register */
#define TCO_DAT_OUT(d)         (BASE(d) + 0x03) /* TCO Data Out Register */
#define TCO1_STS(d)            (BASE(d) + 0x04) /* TCO1 Status Register */
#define TCO2_STS(d)            (BASE(d) + 0x06) /* TCO2 Status Register */
#define TCO1_CNT(d)            (BASE(d) + 0x08) /* TCO1 Control Register */
#define TCO2_CNT(d)            (BASE(d) + 0x0a) /* TCO2 Control Register */
#define TCO_MSG(d)             (BASE(d) + 0x0c) /* TCO Message Registers */
#define TCO_WDSTATUS(d)        (BASE(d) + 0x0e) /* TCO Watchdog Status Register */
#define TCO_TMR(d)             (BASE(d) + 0x12) /* TCO Timer Register */

/* TCO1_STS bits */
#define STS_NMI2SMI            BIT(0)
#define STS_OS_TCO_SMI         BIT(1)
#define STS_TCO_INT            BIT(2)
#define STS_TIMEOUT            BIT(3)
#define STS_NEWCENTURY         BIT(7)
#define STS_BIOSWR             BIT(8)
#define STS_CPUSCI             BIT(9)
#define STS_CPUSMI             BIT(10)
#define STS_CPUSERR            BIT(12)
#define STS_SLVSEL             BIT(13)

/* TCO2_STS bits */
#define STS_INTRD_DET          BIT(0)
#define STS_SECOND_TO          BIT(1)
#define STS_NRSTRAP            BIT(2)
#define STS_SMLINK_SLAVE_SMI   BIT(3)

/* TCO1_CNT bits */
#define CNT_NR_MSUS            BIT(0)
#define CNT_NMI_NOW            BIT(8)
#define CNT_NMI2SMI_EN         BIT(9)
#define CNT_TCO_TMR_HALT       BIT(11)
#define CNT_TCO_LOCK           BIT(12)

/* TCO_TMR bits */
#define TMR_TCOTMR             BIT_MASK(10)
#define TMR_MIN                0x04
#define TMR_MAX                0x3f

struct tco_data {
	struct k_spinlock lock;
	bool no_reboot;
};

struct tco_config {
	io_port_t base;
};

static int set_no_reboot(const struct device *dev, bool set)
{
	uint16_t val, newval;

	val = sys_in16(TCO1_CNT(dev));

	if (set) {
		val |= CNT_NR_MSUS;
	} else {
		val &= ~CNT_NR_MSUS;
	}

	sys_out16(val, TCO1_CNT(dev));
	newval = sys_in16(TCO1_CNT(dev));

	if (val != newval) {
		return -EIO;
	}

	return 0;
}

static int tco_setup(const struct device *dev, uint8_t options)
{
	struct tco_data *data = dev->data;
	k_spinlock_key_t key;
	uint16_t val;
	int err;

	key = k_spin_lock(&data->lock);

	err = set_no_reboot(dev, data->no_reboot);
	if (err) {
		k_spin_unlock(&data->lock, key);
		LOG_ERR("Failed to update no_reboot bit (err %d)", err);
		return err;
	}

	/* Reload the timer */
	sys_out16(0x01, TCO_RLD(dev));

	/* Enable the timer to start counting by clearing the TCO_TMR_HALT field */
	val = sys_in16(TCO1_CNT(dev));
	val &= ~CNT_TCO_TMR_HALT;
	sys_out16(val, TCO1_CNT(dev));
	val = sys_in16(TCO1_CNT(dev));

	k_spin_unlock(&data->lock, key);

	if ((val & CNT_TCO_TMR_HALT) == CNT_TCO_TMR_HALT) {
		return -EIO;
	}

	return 0;
}

static int tco_disable(const struct device *dev)
{
	struct tco_data *data = dev->data;
	k_spinlock_key_t key;
	uint16_t val;

	key = k_spin_lock(&data->lock);

	/* Set the TCO_TMR_HALT field so that the timer gets halted */
	val = sys_in16(TCO1_CNT(dev));
	val |= CNT_TCO_TMR_HALT;
	sys_out16(val, TCO1_CNT(dev));
	val = sys_in16(TCO1_CNT(dev));

	set_no_reboot(dev, true);

	k_spin_unlock(&data->lock, key);

	if ((val & CNT_TCO_TMR_HALT) == 0) {
		return -EIO;
	}

	return 0;
}

static uint16_t msec_to_ticks(uint32_t msec)
{
	/* Convert from milliseconds to timer ticks. The timer is clocked at
	 * approximately 0.6 seconds.
	 */
	return ((msec / MSEC_PER_SEC) * 10) / 6;
}

static int tco_install_timeout(const struct device *dev,
			       const struct wdt_timeout_cfg *cfg)
{
	struct tco_data *data = dev->data;
	k_spinlock_key_t key;
	uint16_t val, ticks;

	/* TCO watchdog doesn't support windowed timeouts */
	if (cfg->window.min != 0) {
		return -EINVAL;
	}

	/* No callback support */
	if (cfg->callback != NULL) {
		return -ENOTSUP;
	}

	ticks = msec_to_ticks(cfg->window.max);

	LOG_DBG("window.max %u -> ticks %u", cfg->window.max, ticks);

	if (ticks < TMR_MIN || ticks > TMR_MAX) {
		return -EINVAL;
	}

	switch (cfg->flags) {
	case WDT_FLAG_RESET_SOC:
		data->no_reboot = false;
		break;
	case WDT_FLAG_RESET_NONE:
		data->no_reboot = true;
		break;
	case WDT_FLAG_RESET_CPU_CORE:
		LOG_ERR("CPU-only reset not supported");
		return -ENOTSUP;
	default:
		LOG_ERR("Unknown watchdog configuration flags");
		return -EINVAL;
	}

	key = k_spin_lock(&data->lock);

	/* Set the TCO_TMR field. This value is loaded into the timer each time
	 * the TCO_RLD register is written.
	 */
	val = sys_in16(TCO_TMR(dev));
	val &= ~TMR_TCOTMR;
	val |= ticks;
	sys_out16(val, TCO_TMR(dev));
	val = sys_in16(TCO_TMR(dev));

	k_spin_unlock(&data->lock, key);

	if ((val & TMR_TCOTMR) != ticks) {
		LOG_ERR("val %u", val);
		return -EIO;
	}

	return 0;
}

static int tco_feed(const struct device *dev, int channel_id)
{
	struct tco_data *data = dev->data;
	k_spinlock_key_t key;

	key = k_spin_lock(&data->lock);

	/* TCORLD: Writing any value to this register will reload the timer to
	 * prevent the timeout.
	 */
	sys_out16(0x01, TCO_RLD(dev));

	k_spin_unlock(&data->lock, key);

	return 0;
}

static const struct wdt_driver_api tco_driver_api = {
	.setup = tco_setup,
	.disable = tco_disable,
	.install_timeout = tco_install_timeout,
	.feed = tco_feed,
};

static int wdt_init(const struct device *dev)
{
	const struct tco_config *config = dev->config;
	struct tco_data *data = dev->data;
	k_spinlock_key_t key;

	LOG_DBG("Using 0x%04x as TCOBA", config->base);

	key = k_spin_lock(&data->lock);

	sys_out16(STS_TIMEOUT, TCO1_STS(dev)); /* Clear the Time Out Status bit */
	sys_out16(STS_SECOND_TO, TCO2_STS(dev)); /* Clear SECOND_TO_STS bit */

	set_no_reboot(dev, data->no_reboot);

	k_spin_unlock(&data->lock, key);

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

	return 0;
}

static struct tco_data wdt_data = {
};

static const struct tco_config wdt_config = {
	.base = DT_REG_ADDR(TCO_WDT_NODE),
};

DEVICE_DT_DEFINE(TCO_WDT_NODE, wdt_init, NULL, &wdt_data, &wdt_config,
		 POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE,
		 &tco_driver_api);
