/*
 * Copyright (c) 2018, Nordic Semiconductor ASA
 *
 * SPDX-License-Identifier: Apache-2.0
 */

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

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

struct wdt_nrfx_data {
	wdt_callback_t m_callbacks[NRF_WDT_CHANNEL_NUMBER];
	uint32_t m_timeout;
	uint8_t m_allocated_channels;
};

struct wdt_nrfx_config {
	nrfx_wdt_t	  wdt;
	nrfx_wdt_config_t config;
};

static inline struct wdt_nrfx_data *get_dev_data(const struct device *dev)
{
	return dev->data;
}

static inline const struct wdt_nrfx_config *get_dev_config(const struct device *dev)
{
	return dev->config;
}


static int wdt_nrf_setup(const struct device *dev, uint8_t options)
{
	nrf_wdt_behaviour_t behaviour;

	/* Activate all available options. Run in all cases. */
	behaviour = NRF_WDT_BEHAVIOUR_RUN_SLEEP_HALT;

	/* Deactivate running in sleep mode. */
	if (options & WDT_OPT_PAUSE_IN_SLEEP) {
		behaviour &= ~NRF_WDT_BEHAVIOUR_RUN_SLEEP;
	}

	/* Deactivate running when debugger is attached. */
	if (options & WDT_OPT_PAUSE_HALTED_BY_DBG) {
		behaviour &= ~NRF_WDT_BEHAVIOUR_RUN_HALT;
	}

	nrf_wdt_behaviour_set(get_dev_config(dev)->wdt.p_reg, behaviour);
	/* The watchdog timer is driven by the LFCLK clock running at 32768 Hz.
	 * The timeout value given in milliseconds needs to be converted here
	 * to watchdog ticks.*/
	nrf_wdt_reload_value_set(
		get_dev_config(dev)->wdt.p_reg,
		(uint32_t)(((uint64_t)get_dev_data(dev)->m_timeout * 32768U)
			   / 1000));

	nrfx_wdt_enable(&get_dev_config(dev)->wdt);

	return 0;
}

static int wdt_nrf_disable(const struct device *dev)
{
	/* Started watchdog cannot be stopped on nRF devices. */
	ARG_UNUSED(dev);
	return -EPERM;
}

static int wdt_nrf_install_timeout(const struct device *dev,
				   const struct wdt_timeout_cfg *cfg)
{
	nrfx_err_t err_code;
	nrfx_wdt_channel_id channel_id;

	if (cfg->flags != WDT_FLAG_RESET_SOC) {
		return -ENOTSUP;
	}

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

	if (get_dev_data(dev)->m_allocated_channels == 0U) {
		/* According to relevant Product Specifications, watchdogs
		 * in all nRF chips can use reload values (determining
		 * the timeout) from range 0xF-0xFFFFFFFF given in 32768 Hz
		 * clock ticks. This makes the allowed range of 0x1-0x07CFFFFF
		 * in milliseconds. Check if the provided value is within
		 * this range. */
		if ((cfg->window.max == 0U) || (cfg->window.max > 0x07CFFFFF)) {
			return -EINVAL;
		}

		/* Save timeout value from first registered watchdog channel. */
		get_dev_data(dev)->m_timeout = cfg->window.max;
	} else if (cfg->window.max != get_dev_data(dev)->m_timeout) {
		return -EINVAL;
	}

	err_code = nrfx_wdt_channel_alloc(&get_dev_config(dev)->wdt,
					  &channel_id);

	if (err_code == NRFX_ERROR_NO_MEM) {
		return -ENOMEM;
	}

	if (cfg->callback != NULL) {
		get_dev_data(dev)->m_callbacks[channel_id] = cfg->callback;
	}

	get_dev_data(dev)->m_allocated_channels++;
	return channel_id;
}

static int wdt_nrf_feed(const struct device *dev, int channel_id)
{
	if (channel_id > get_dev_data(dev)->m_allocated_channels) {
		return -EINVAL;
	}

	nrfx_wdt_channel_feed(&get_dev_config(dev)->wdt,
			      (nrfx_wdt_channel_id)channel_id);

	return 0;
}

static const struct wdt_driver_api wdt_nrfx_driver_api = {
	.setup = wdt_nrf_setup,
	.disable = wdt_nrf_disable,
	.install_timeout = wdt_nrf_install_timeout,
	.feed = wdt_nrf_feed,
};

static void wdt_event_handler(const struct device *dev)
{
	int i;

	for (i = 0; i < get_dev_data(dev)->m_allocated_channels; ++i) {
		if (nrf_wdt_request_status(get_dev_config(dev)->wdt.p_reg,
					   (nrf_wdt_rr_register_t)i)) {
			if (get_dev_data(dev)->m_callbacks[i]) {
				get_dev_data(dev)->m_callbacks[i](dev, i);
			}
		}
	}
}

#define WDT(idx) DT_NODELABEL(wdt##idx)

#define WDT_NRFX_WDT_DEVICE(idx)					       \
	static void wdt_##idx##_event_handler(void)			       \
	{								       \
		wdt_event_handler(DEVICE_DT_GET(WDT(idx)));		       \
	}								       \
	static int wdt_##idx##_init(const struct device *dev)		       \
	{								       \
		nrfx_err_t err_code;					       \
		IRQ_CONNECT(DT_IRQN(WDT(idx)), DT_IRQ(WDT(idx), priority),     \
			    nrfx_isr, nrfx_wdt_##idx##_irq_handler, 0);	       \
		err_code = nrfx_wdt_init(&get_dev_config(dev)->wdt,	       \
				 &get_dev_config(dev)->config,		       \
				 wdt_##idx##_event_handler);		       \
		if (err_code != NRFX_SUCCESS) {				       \
			return -EBUSY;					       \
		}							       \
		return 0;						       \
	}								       \
	static struct wdt_nrfx_data wdt_##idx##_data = {		       \
		.m_timeout = 0,						       \
		.m_allocated_channels = 0,				       \
	};								       \
	static const struct wdt_nrfx_config wdt_##idx##z_config = {	       \
		.wdt = NRFX_WDT_INSTANCE(idx),				       \
		.config = {						       \
			.behaviour   = NRF_WDT_BEHAVIOUR_RUN_SLEEP_HALT,       \
			.reload_value  = 2000,				       \
		}							       \
	};								       \
	DEVICE_DT_DEFINE(WDT(idx),					       \
			    wdt_##idx##_init,				       \
			    device_pm_control_nop,			       \
			    &wdt_##idx##_data,				       \
			    &wdt_##idx##z_config,			       \
			    PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEVICE,  \
			    &wdt_nrfx_driver_api)

#ifdef CONFIG_NRFX_WDT0
WDT_NRFX_WDT_DEVICE(0);
#endif

#ifdef CONFIG_NRFX_WDT1
WDT_NRFX_WDT_DEVICE(1);
#endif
