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

#define DT_DRV_COMPAT atmel_sam_watchdog

/**
 * @brief Watchdog (WDT) Driver for Atmel SAM MCUs
 *
 * Note:
 * - Once the watchdog disable bit is set, it cannot be cleared till next
 *   power reset, i.e, the watchdog cannot be started once stopped.
 * - Since the MCU boots with WDT enabled, the CONFIG_WDT_DISABLE_AT_BOOT
 *   is set default at boot and watchdog module is disabled in the MCU for
 *   systems that don't need watchdog functionality.
 * - If the application needs to use the watchdog in the system, then
 *   CONFIG_WDT_DISABLE_AT_BOOT must be unset in the app's config file
 */

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

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

#define SAM_PRESCALAR   128
#define WDT_MAX_VALUE   4095

/* Device constant configuration parameters */
struct wdt_sam_dev_cfg {
	Wdt *regs;
};

struct wdt_sam_dev_data {
	wdt_callback_t cb;
	uint32_t mode;
	bool timeout_valid;
	bool mode_set;
};

static struct wdt_sam_dev_data wdt_sam_data = { 0 };

static void wdt_sam_isr(const struct device *dev)
{
	const struct wdt_sam_dev_cfg *config = dev->config;
	uint32_t wdt_sr;
	Wdt * const wdt = config->regs;
	struct wdt_sam_dev_data *data = dev->data;

	/* Clear status bit to acknowledge interrupt by dummy read. */
	wdt_sr = wdt->WDT_SR;

	data->cb(dev, 0);
}

/**
 * @brief Calculates the watchdog counter value (WDV)
 *        to be installed in the watchdog timer
 *
 * @param timeout Timeout value in milliseconds.
 * @param slow clock on board in Hz.
 */
int wdt_sam_convert_timeout(uint32_t timeout, uint32_t sclk)
{
	uint32_t max, min;

	timeout = timeout * 1000U;
	min =  (SAM_PRESCALAR * 1000000) / sclk;
	max = min * WDT_MAX_VALUE;
	if ((timeout < min) || (timeout > max)) {
		LOG_ERR("Invalid timeout value allowed range:"
			"%d ms to %d ms", min / 1000U, max / 1000U);
		return -EINVAL;
	}

	return WDT_MR_WDV(timeout / min);
}

static int wdt_sam_disable(const struct device *dev)
{
	const struct wdt_sam_dev_cfg *config = dev->config;

	Wdt * const wdt = config->regs;
	struct wdt_sam_dev_data *data = dev->data;

	/* since Watchdog mode register is 'write-once', we can't disable if
	 * someone has already set the mode register
	 */
	if (data->mode_set) {
		return -EPERM;
	}

	/* do we handle -EFAULT here */

	/* Watchdog Mode register is 'write-once' only register.
	 * Once disabled, it cannot be enabled until the device is reset
	 */
	wdt->WDT_MR |= WDT_MR_WDDIS;
	data->mode_set = true;

	return 0;
}

static int wdt_sam_setup(const struct device *dev, uint8_t options)
{
	const struct wdt_sam_dev_cfg *config = dev->config;

	Wdt * const wdt = config->regs;
	struct wdt_sam_dev_data *data = dev->data;

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

	/* since Watchdog mode register is 'write-once', we can't set if
	 * someone has already set the mode register
	 */
	if (data->mode_set) {
		return -EPERM;
	}

	if ((options & WDT_OPT_PAUSE_IN_SLEEP) == WDT_OPT_PAUSE_IN_SLEEP) {
		data->mode |= WDT_MR_WDIDLEHLT;
	}

	if ((options & WDT_OPT_PAUSE_HALTED_BY_DBG) ==
	    WDT_OPT_PAUSE_HALTED_BY_DBG) {
		data->mode |= WDT_MR_WDDBGHLT;
	}

	wdt->WDT_MR = data->mode;
	data->mode_set = true;

	return 0;
}

static int wdt_sam_install_timeout(const struct device *dev,
				   const struct wdt_timeout_cfg *cfg)
{
	uint32_t wdt_mode = 0U;
	int timeout_value;

	struct wdt_sam_dev_data *data = dev->data;

	if (data->timeout_valid) {
		LOG_ERR("No more timeouts can be installed");
		return -ENOMEM;
	}

	if (cfg->window.min != 0U) {
		return -EINVAL;
	}

	/*
	 * Convert time to cycles. SAM3X SoC doesn't supports window
	 * timeout config. So the api expects the timeout to be filled
	 * in the max field of the timeout config.
	 */
	timeout_value = wdt_sam_convert_timeout(cfg->window.max,
						(uint32_t) CHIP_FREQ_XTAL_32K);

	if (timeout_value < 0) {
		return -EINVAL;
	}

	switch (cfg->flags) {
	case WDT_FLAG_RESET_SOC:
		/*A Watchdog fault (underflow or error) activates all resets */
		wdt_mode = WDT_MR_WDRSTEN;  /* WDT reset enable */
		break;

	case WDT_FLAG_RESET_NONE:
		/* A Watchdog fault (underflow or error) asserts interrupt. */
		if (cfg->callback) {
			wdt_mode = WDT_MR_WDFIEN;   /* WDT fault interrupt. */
			data->cb = cfg->callback;
		} else {
			LOG_ERR("Invalid(NULL) ISR callback passed\n");
			return -EINVAL;
		}
		break;

		/* Processor only reset mode not available in same70 series */
#ifdef WDT_MR_WDRPROC
	case WDT_FLAG_RESET_CPU_CORE:
		/*A Watchdog fault activates the processor reset*/
		LOG_DBG("Configuring reset CPU only mode\n");
		wdt_mode = WDT_MR_WDRSTEN   |   /* WDT reset enable */
			   WDT_MR_WDRPROC;      /* WDT reset processor only*/
		break;
#endif
	default:
		LOG_ERR("Unsupported watchdog config Flag\n");
		return -ENOTSUP;
	}

	data->mode = wdt_mode |
		     WDT_MR_WDV(timeout_value) |
		     WDT_MR_WDD(timeout_value);

	data->timeout_valid = true;

	return 0;
}

static int wdt_sam_feed(const struct device *dev, int channel_id)
{
	const struct wdt_sam_dev_cfg *config = dev->config;

	/*
	 * On watchdog restart the Watchdog counter is immediately
	 * reloaded/fed with the 12-bit watchdog counter
	 * value from WDT_MR and restarted
	 */
	Wdt * const wdt = config->regs;

	wdt->WDT_CR |= WDT_CR_KEY_PASSWD | WDT_CR_WDRSTT;

	return 0;
}

static const struct wdt_driver_api wdt_sam_api = {
	.setup = wdt_sam_setup,
	.disable = wdt_sam_disable,
	.install_timeout = wdt_sam_install_timeout,
	.feed = wdt_sam_feed,
};

static const struct wdt_sam_dev_cfg wdt_sam_cfg = {
	.regs = (Wdt *)DT_INST_REG_ADDR(0),
};

static void wdt_sam_irq_config(void)
{
	IRQ_CONNECT(DT_INST_IRQN(0),
		    DT_INST_IRQ(0, priority), wdt_sam_isr,
		    DEVICE_DT_INST_GET(0), 0);
	irq_enable(DT_INST_IRQN(0));
}

static int wdt_sam_init(const struct device *dev)
{
#ifdef CONFIG_WDT_DISABLE_AT_BOOT
	wdt_sam_disable(dev);
#endif

	wdt_sam_irq_config();
	return 0;
}

DEVICE_DT_INST_DEFINE(0, wdt_sam_init, NULL,
		    &wdt_sam_data, &wdt_sam_cfg, PRE_KERNEL_1,
		    CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &wdt_sam_api);
