/*
 * Copyright (c) 2018 Henrik Brix Andersen <henrik@brixandersen.dk>
 * Copyright (c) 2017 Google LLC.
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#define DT_DRV_COMPAT atmel_sam0_watchdog

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

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

#define WDT_REGS ((Wdt *)DT_INST_REG_ADDR(0))

#ifndef WDT_CONFIG_PER_8_Val
#define WDT_CONFIG_PER_8_Val WDT_CONFIG_PER_CYC8_Val
#endif
#ifndef WDT_CONFIG_PER_8K_Val
#define WDT_CONFIG_PER_8K_Val WDT_CONFIG_PER_CYC8192_Val
#endif
#ifndef WDT_CONFIG_PER_16K_Val
#define WDT_CONFIG_PER_16K_Val WDT_CONFIG_PER_CYC16384_Val
#endif

/* syncbusy check is different for SAM D/E */
#ifdef WDT_STATUS_SYNCBUSY
#define WDT_SYNCBUSY WDT_REGS->STATUS.bit.SYNCBUSY
#else
#define WDT_SYNCBUSY WDT_REGS->SYNCBUSY.reg
#endif

struct wdt_sam0_dev_data {
	wdt_callback_t cb;
	bool timeout_valid;
};

static struct wdt_sam0_dev_data wdt_sam0_data = { 0 };

static void wdt_sam0_wait_synchronization(void)
{
	while (WDT_SYNCBUSY) {
		/* wait for SYNCBUSY */
	}
}

static inline void wdt_sam0_set_enable(bool on)
{
#ifdef WDT_CTRLA_ENABLE
	WDT_REGS->CTRLA.bit.ENABLE = on;
#else
	WDT_REGS->CTRL.bit.ENABLE = on;
#endif
}

static inline bool wdt_sam0_is_enabled(void)
{
#ifdef WDT_CTRLA_ENABLE
	return WDT_REGS->CTRLA.bit.ENABLE;
#else
	return WDT_REGS->CTRL.bit.ENABLE;
#endif
}

static uint32_t wdt_sam0_timeout_to_wdt_period(uint32_t timeout_ms)
{
	uint32_t next_pow2;
	uint32_t cycles;

	/* Calculate number of clock cycles @ 1.024 kHz input clock */
	cycles = (timeout_ms * 1024U) / 1000;

	/* Minimum wdt period is 8 clock cycles (register value 0) */
	if (cycles <= 8U) {
		return 0;
	}

	/* Round up to next pow2 and calculate the register value */
	next_pow2 = (1ULL << 32) >> __builtin_clz(cycles - 1);
	return find_msb_set(next_pow2 >> 4);
}

static void wdt_sam0_isr(const struct device *dev)
{
	struct wdt_sam0_dev_data *data = dev->data;

	WDT_REGS->INTFLAG.reg = WDT_INTFLAG_EW;

	if (data->cb != NULL) {
		data->cb(dev, 0);
	}
}

static int wdt_sam0_setup(const struct device *dev, uint8_t options)
{
	struct wdt_sam0_dev_data *data = dev->data;

	if (wdt_sam0_is_enabled()) {
		LOG_ERR("Watchdog already setup");
		return -EBUSY;
	}

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

	if (options & WDT_OPT_PAUSE_IN_SLEEP) {
		LOG_ERR("Pause in sleep not supported");
		return -ENOTSUP;
	}

	if (options & WDT_OPT_PAUSE_HALTED_BY_DBG) {
		LOG_ERR("Pause when halted by debugger not supported");
		return -ENOTSUP;
	}

	/* Enable watchdog */
	wdt_sam0_set_enable(1);
	wdt_sam0_wait_synchronization();

	return 0;
}

static int wdt_sam0_disable(const struct device *dev)
{
	if (!wdt_sam0_is_enabled()) {
		return -EFAULT;
	}

	wdt_sam0_set_enable(0);
	wdt_sam0_wait_synchronization();

	return 0;
}

static int wdt_sam0_install_timeout(const struct device *dev,
				    const struct wdt_timeout_cfg *cfg)
{
	struct wdt_sam0_dev_data *data = dev->data;
	uint32_t window, per;

	/* CONFIG is enable protected, error out if already enabled */
	if (wdt_sam0_is_enabled()) {
		LOG_ERR("Watchdog already setup");
		return -EBUSY;
	}

	if (cfg->flags != WDT_FLAG_RESET_SOC) {
		LOG_ERR("Only SoC reset supported");
		return -ENOTSUP;
	}

	if (cfg->window.max == 0) {
		LOG_ERR("Upper limit timeout out of range");
		return -EINVAL;
	}

	per = wdt_sam0_timeout_to_wdt_period(cfg->window.max);
	if (per > WDT_CONFIG_PER_16K_Val) {
		LOG_ERR("Upper limit timeout out of range");
		goto timeout_invalid;
	}

	if (cfg->window.min) {
		/* Window mode */
		window = wdt_sam0_timeout_to_wdt_period(cfg->window.min);
		if (window > WDT_CONFIG_PER_8K_Val) {
			LOG_ERR("Lower limit timeout out of range");
			goto timeout_invalid;
		}
		if (per <= window) {
			/* Ensure we have a window */
			per = window + 1;
		}
#ifdef WDT_CTRLA_WEN
		WDT_REGS->CTRLA.bit.WEN = 1;
#else
		WDT_REGS->CTRL.bit.WEN = 1;
#endif
		wdt_sam0_wait_synchronization();
	} else {
		/* Normal mode */
		if (cfg->callback) {
			if (per == WDT_CONFIG_PER_8_Val) {
				/* Ensure we have time for the early warning */
				per += 1U;
			}
			WDT_REGS->EWCTRL.bit.EWOFFSET = per - 1U;
		}
		window = WDT_CONFIG_PER_8_Val;
#ifdef WDT_CTRLA_WEN
		WDT_REGS->CTRLA.bit.WEN = 0;
#else
		WDT_REGS->CTRL.bit.WEN = 0;
#endif
		wdt_sam0_wait_synchronization();
	}

	WDT_REGS->CONFIG.reg = WDT_CONFIG_WINDOW(window) | WDT_CONFIG_PER(per);
	wdt_sam0_wait_synchronization();

	/* Only enable IRQ if a callback was provided */
	data->cb = cfg->callback;
	if (data->cb) {
		WDT_REGS->INTENSET.reg = WDT_INTENSET_EW;
	} else {
		WDT_REGS->INTENCLR.reg = WDT_INTENCLR_EW;
		WDT_REGS->INTFLAG.reg = WDT_INTFLAG_EW;
	}

	data->timeout_valid = true;

	return 0;

timeout_invalid:
	data->timeout_valid = false;
	data->cb = NULL;

	return -EINVAL;
}

static int wdt_sam0_feed(const struct device *dev, int channel_id)
{
	struct wdt_sam0_dev_data *data = dev->data;

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

	if (WDT_SYNCBUSY) {
		return -EAGAIN;
	}

	WDT_REGS->CLEAR.reg = WDT_CLEAR_CLEAR_KEY_Val;

	return 0;
}

static const struct wdt_driver_api wdt_sam0_api = {
	.setup = wdt_sam0_setup,
	.disable = wdt_sam0_disable,
	.install_timeout = wdt_sam0_install_timeout,
	.feed = wdt_sam0_feed,
};

static int wdt_sam0_init(const struct device *dev)
{
#ifdef CONFIG_WDT_DISABLE_AT_BOOT
	/* Ignore any errors */
	wdt_sam0_disable(dev);
#endif
	/* Enable APB clock */
#ifdef MCLK
	MCLK->APBAMASK.bit.WDT_ = 1;

	/* watchdog clock is fed by OSCULP32K */
#else
	PM->APBAMASK.bit.WDT_ = 1;

	/* Connect to GCLK2 (~1.024 kHz) */
	GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID_WDT
		| GCLK_CLKCTRL_GEN_GCLK2
		| GCLK_CLKCTRL_CLKEN;
#endif

	IRQ_CONNECT(DT_INST_IRQN(0),
		    DT_INST_IRQ(0, priority), wdt_sam0_isr,
		    DEVICE_DT_INST_GET(0), 0);
	irq_enable(DT_INST_IRQN(0));

	return 0;
}

static struct wdt_sam0_dev_data wdt_sam0_data;

DEVICE_DT_INST_DEFINE(0, wdt_sam0_init, NULL,
		    &wdt_sam0_data, NULL, PRE_KERNEL_1,
		    CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &wdt_sam0_api);
