/*
 * 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);

DEVICE_DECLARE(wdt_nrfx);

/* Each activated and not reloaded channel can generate watchdog interrupt.
 * Array m_callbacks provides storing callbacks for each channel.
 */
static wdt_callback_t m_callbacks[NRF_WDT_CHANNEL_NUMBER];

/* The m_allocated_channels variable stores number of currently allocated
 * and activated watchdog channels.
 */
static u8_t m_allocated_channels;

/* The m_timeout variable stores watchdog timeout value in millisecond units.
 * It is used to check whether installing watchdog provide the same timeout
 * value in the window configuration.
 */
static u32_t m_timeout;

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

	ARG_UNUSED(dev);

	/* 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(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(
			(uint32_t)(((uint64_t)m_timeout * 32768U) / 1000));

	nrfx_wdt_enable();

	return 0;
}

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

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

	ARG_UNUSED(dev);

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

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

	if (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. */
		m_timeout = cfg->window.max;
	} else if (cfg->window.max != m_timeout) {
		return -EINVAL;
	}

	err_code = nrfx_wdt_channel_alloc(&channel_id);

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

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

	m_allocated_channels++;
	return channel_id;
}

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

	nrfx_wdt_channel_feed((nrfx_wdt_channel_id)channel_id);

	return 0;
}

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

static void wdt_event_handler(void)
{
	int i;

	for (i = 0; i < m_allocated_channels ; ++i) {
		if (nrf_wdt_request_status((nrf_wdt_rr_register_t)i)) {
			if (m_callbacks[i]) {
				m_callbacks[i](DEVICE_GET(wdt_nrfx), i);
			}
		}
	}
}

static int init_wdt(struct device *dev)
{
	nrfx_err_t err_code;
	/* Set default values. They will be overwritten by setup function. */
	const nrfx_wdt_config_t config = {
		.behaviour          = NRF_WDT_BEHAVIOUR_RUN_SLEEP_HALT,
		.reload_value       = 2000
	};

	ARG_UNUSED(dev);

	err_code = nrfx_wdt_init(&config, wdt_event_handler);
	if (err_code != NRFX_SUCCESS) {
		return -EBUSY;
	}

	IRQ_CONNECT(DT_NORDIC_NRF_WATCHDOG_WDT_0_IRQ_0,
		    DT_NORDIC_NRF_WATCHDOG_WDT_0_IRQ_0_PRIORITY,
		    nrfx_isr, nrfx_wdt_irq_handler, 0);
	irq_enable(DT_NORDIC_NRF_WATCHDOG_WDT_0_IRQ_0);

	return 0;
}

DEVICE_AND_API_INIT(wdt_nrf, DT_NORDIC_NRF_WATCHDOG_WDT_0_LABEL, init_wdt,
		    NULL, NULL, PRE_KERNEL_1,
		    CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &wdt_nrf_api);
