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

#include <nrfx_wdt.h>
#include <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 * 32768) / 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 != 0) {
		return -EINVAL;
	}

	if (m_allocated_channels == 0) {
		/* 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 == 0) || (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,
		    DT_NORDIC_NRF_WATCHDOG_WDT_0_IRQ_PRIORITY,
		    nrfx_isr, nrfx_wdt_irq_handler, 0);
	irq_enable(DT_NORDIC_NRF_WATCHDOG_WDT_0_IRQ);

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