/*
 * Copyright (C) 2017 Intel Corporation
 *
 * SPDX-License-Identifier: Apache-2.0
 */

/* Include esp-idf headers first to avoid redefining BIT() macro */
#include <rom/ets_sys.h>
#include <soc/rtc_cntl_reg.h>
#include <soc/timer_group_reg.h>

#include <string.h>
#include <watchdog.h>
#include <device.h>

struct wdt_esp32_data {
	struct wdt_config config;
};

static struct wdt_esp32_data shared_data;

/* ESP32 ignores writes to any register if WDTWPROTECT doesn't contain the
 * magic value of TIMG_WDT_WKEY_VALUE.  The datasheet recommends unsealing,
 * making modifications, and sealing for every watchdog modification.
 */
static inline void wdt_esp32_seal(void)
{
	volatile u32_t *reg = (u32_t *)TIMG_WDTWPROTECT_REG(1);

	*reg = 0;
}

static inline void wdt_esp32_unseal(void)
{
	volatile u32_t *reg = (u32_t *)TIMG_WDTWPROTECT_REG(1);

	*reg = TIMG_WDT_WKEY_VALUE;
}

static void wdt_esp32_enable(struct device *dev)
{
	volatile u32_t *reg = (u32_t *)TIMG_WDTCONFIG0_REG(1);

	ARG_UNUSED(dev);

	wdt_esp32_unseal();
	*reg |= BIT(TIMG_WDT_EN_S);
	wdt_esp32_seal();
}

static void wdt_esp32_disable(struct device *dev)
{
	volatile u32_t *reg = (u32_t *)TIMG_WDTCONFIG0_REG(1);

	ARG_UNUSED(dev);

	wdt_esp32_unseal();
	*reg &= ~BIT(TIMG_WDT_EN_S);
	wdt_esp32_seal();
}

static void adjust_timeout(u32_t timeout)
{
	volatile u32_t *reg;
	enum wdt_clock_timeout_cycles cycles =
		(enum wdt_clock_timeout_cycles)timeout;
	u32_t ticks;

	/* The watchdog API in Zephyr was modeled after the QMSI drivers,
	 * and those were modeled after the Quark MCUs.  The possible
	 * values of enum wdt_clock_timeout_cycles maps 1:1 to what the
	 * Quark D2000 expects.  At 32MHz, the timeout value in ms is given
	 * by the following formula, according to the D2000 datasheet:
	 *
	 *                   2^(cycles + 11)
	 *      timeout_ms = ---------------
	 *                         1000
	 *
	 * (e.g. 2.048ms for 2^16 cycles, or the WDT_2_16_CYCLES value.)
	 *
	 * While this is sort of backwards (this should be given units of
	 * time and converted to what the hardware expects), try to map this
	 * value to what the ESP32 expects.  Use the same timeout value for
	 * stages 0 and 1, regardless of the configuration mode, in order to
	 * simplify things.
	 */

	 /* MWDT ticks every 12.5ns.  Set the prescaler to 40000, so the
	  * counter for each watchdog stage is decremented every 0.5ms.
	  */
	 reg = (u32_t *)TIMG_WDTCONFIG1_REG(1);
	 *reg = 40000;

	 ticks = 1<<(cycles + 2);

	 /* Correct the value: this is an integer-only approximation of
	  *    0.114074 * exp(0.67822 * cycles)
	  * Which calculates the difference in ticks from the D2000 values to
	  * the value calculated by the previous expression.
	  */
	 ticks += (1<<cycles) / 10;

	 reg = (u32_t *)TIMG_WDTCONFIG2_REG(1);
	 *reg = ticks;

	 reg = (u32_t *)TIMG_WDTCONFIG3_REG(1);
	 *reg = ticks;
}

static void wdt_esp32_isr(void *param);

static void wdt_esp32_reload(struct device *dev)
{
	volatile u32_t *reg = (u32_t *)TIMG_WDTFEED_REG(1);

	ARG_UNUSED(dev);

	wdt_esp32_unseal();
	*reg = 0xABAD1DEA; /* Writing any value to WDTFEED will reload it. */
	wdt_esp32_seal();
}

static void set_interrupt_enabled(bool setting)
{
	volatile u32_t *intr_enable_reg = (u32_t *)TIMG_INT_ENA_TIMERS_REG(1);
	volatile u32_t *intr_clear_timers = (u32_t *)TIMG_INT_CLR_TIMERS_REG(1);

	*intr_clear_timers |= TIMG_WDT_INT_CLR;

	if (setting) {
		*intr_enable_reg |= TIMG_WDT_INT_ENA;

		IRQ_CONNECT(CONFIG_WDT_ESP32_IRQ, 4, wdt_esp32_isr,
			    &shared_data, 0);
		irq_enable(CONFIG_WDT_ESP32_IRQ);
	} else {
		*intr_enable_reg &= ~TIMG_WDT_INT_ENA;

		irq_disable(CONFIG_WDT_ESP32_IRQ);
	}
}

static int wdt_esp32_set_config(struct device *dev, struct wdt_config *config)
{
	struct wdt_esp32_data *data = dev->driver_data;
	volatile u32_t *reg = (u32_t *)TIMG_WDTCONFIG0_REG(1);
	u32_t v;

	if (!config) {
		return -EINVAL;
	}

	v = *reg;

	/* Stages 3 and 4 are not used: disable them. */
	v |= TIMG_WDT_STG_SEL_OFF<<TIMG_WDT_STG2_S;
	v |= TIMG_WDT_STG_SEL_OFF<<TIMG_WDT_STG3_S;

	/* Wait for 3.2us before booting again. */
	v |= 7<<TIMG_WDT_SYS_RESET_LENGTH_S;
	v |= 7<<TIMG_WDT_CPU_RESET_LENGTH_S;

	if (config->mode == WDT_MODE_RESET) {
		/* Warm reset on timeout */
		v |= TIMG_WDT_STG_SEL_RESET_SYSTEM<<TIMG_WDT_STG0_S;
		v |= TIMG_WDT_STG_SEL_OFF<<TIMG_WDT_STG1_S;

		/* Disable interrupts for this mode. */
		v &= ~(TIMG_WDT_LEVEL_INT_EN | TIMG_WDT_EDGE_INT_EN);
	} else if (config->mode == WDT_MODE_INTERRUPT_RESET) {
		/* Interrupt first, and warm reset if not reloaded */
		v |= TIMG_WDT_STG_SEL_INT<<TIMG_WDT_STG0_S;
		v |= TIMG_WDT_STG_SEL_RESET_SYSTEM<<TIMG_WDT_STG1_S;

		/* Use level-triggered interrupts. */
		v |= TIMG_WDT_LEVEL_INT_EN;
		v &= ~TIMG_WDT_EDGE_INT_EN;
	} else {
		return -EINVAL;
	}

	wdt_esp32_unseal();
	*reg = v;
	adjust_timeout(config->timeout & WDT_TIMEOUT_MASK);
	set_interrupt_enabled(config->mode == WDT_MODE_INTERRUPT_RESET);
	wdt_esp32_seal();

	wdt_esp32_reload(dev);

	memcpy(&data->config, config, sizeof(*config));
	return 0;
}

static void wdt_esp32_get_config(struct device *dev, struct wdt_config *config)
{
	struct wdt_esp32_data *data = dev->driver_data;

	memcpy(config, &data->config, sizeof(*config));
}

static int wdt_esp32_init(struct device *dev)
{
	struct wdt_esp32_data *data = dev->driver_data;

	memset(&data->config, 0, sizeof(data->config));

#ifdef CONFIG_ESP32_DISABLE_AT_BOOT
	wdt_esp32_disable(dev);
#endif

	/* This is a level 4 interrupt, which is handled by _Level4Vector,
	 * located in xtensa_vectors.S.
	 */
	irq_disable(CONFIG_WDT_ESP32_IRQ);
	intr_matrix_set(0, ETS_TG1_WDT_LEVEL_INTR_SOURCE, CONFIG_WDT_ESP32_IRQ);

	return 0;
}

static const struct wdt_driver_api wdt_api = {
	.enable = wdt_esp32_enable,
	.disable = wdt_esp32_disable,
	.get_config = wdt_esp32_get_config,
	.set_config = wdt_esp32_set_config,
	.reload = wdt_esp32_reload
};

DEVICE_AND_API_INIT(wdt_esp32, CONFIG_WDT_ESP32_DEVICE_NAME, wdt_esp32_init,
		    &shared_data, NULL,
		    PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEVICE,
		    &wdt_api);

static void wdt_esp32_isr(void *param)
{
	struct wdt_esp32_data *data = param;
	volatile u32_t *reg = (u32_t *)TIMG_INT_CLR_TIMERS_REG(1);

	if (data->config.interrupt_fn) {
		data->config.interrupt_fn(DEVICE_GET(wdt_esp32));
	}

	*reg |= TIMG_WDT_INT_CLR;
}
