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

#include <zephyr/drivers/watchdog.h>
#include <zephyr/drivers/counter.h>
#include <zephyr/logging/log_ctrl.h>

#define WDT_CHANNEL_COUNT DT_PROP(DT_WDT_COUNTER, num_channels)
#define DT_WDT_COUNTER DT_COMPAT_GET_ANY_STATUS_OKAY(zephyr_counter_watchdog)

#define WDT_SUPPORTED_CFG_FLAGS (WDT_FLAG_RESET_NONE | WDT_FLAG_RESET_SOC)

extern void sys_arch_reboot(int type);

struct wdt_counter_data {
	wdt_callback_t callback[CONFIG_WDT_COUNTER_CH_COUNT];
	uint32_t timeout[CONFIG_WDT_COUNTER_CH_COUNT];
	uint8_t flags[CONFIG_WDT_COUNTER_CH_COUNT];
	uint8_t alloc_cnt;
};

static struct wdt_counter_data wdt_data;

struct wdt_counter_config {
	const struct device *counter;
};

static int wdt_counter_setup(const struct device *dev, uint8_t options)
{
	const struct wdt_counter_config *config = dev->config;
	const struct device *counter = config->counter;

	if ((options & WDT_OPT_PAUSE_IN_SLEEP) || (options & WDT_OPT_PAUSE_HALTED_BY_DBG)) {
		return -ENOTSUP;
	}

	return counter_start(counter);
}

static int wdt_counter_disable(const struct device *dev)
{
	const struct wdt_counter_config *config = dev->config;
	const struct device *counter = config->counter;

	return counter_stop(counter);
}

static void counter_alarm_callback(const struct device *dev,
				   uint8_t chan_id, uint32_t ticks,
				   void *user_data)
{
	const struct device *wdt_dev = user_data;
	struct wdt_counter_data *data = wdt_dev->data;

	counter_stop(dev);
	if (data->callback[chan_id]) {
		data->callback[chan_id](wdt_dev, chan_id);
	}

	if (data->flags[chan_id] & WDT_FLAG_RESET_SOC) {
		LOG_PANIC();
		sys_arch_reboot(0);
	}
}

static int timeout_set(const struct device *dev, int chan_id, bool cancel)
{
	const struct wdt_counter_config *config = dev->config;
	struct wdt_counter_data *data = dev->data;
	const struct device *counter = config->counter;
	struct counter_alarm_cfg alarm_cfg = {
		.callback = counter_alarm_callback,
		.ticks = data->timeout[chan_id],
		.user_data = (void *)dev,
		.flags = 0
	};

	if (cancel) {
		int err = counter_cancel_channel_alarm(counter, chan_id);

		if (err < 0) {
			return err;
		}
	}

	return counter_set_channel_alarm(counter, chan_id, &alarm_cfg);
}

static int wdt_counter_install_timeout(const struct device *dev,
				   const struct wdt_timeout_cfg *cfg)
{
	struct wdt_counter_data *data = dev->data;
	const struct wdt_counter_config *config = dev->config;
	const struct device *counter = config->counter;
	int chan_id;

	if (!device_is_ready(counter)) {
		return -EIO;
	}

	uint32_t max_timeout = counter_get_top_value(counter) -
				counter_get_guard_period(counter,
				COUNTER_GUARD_PERIOD_LATE_TO_SET);
	uint32_t timeout_ticks = counter_us_to_ticks(counter, (uint64_t)cfg->window.max * 1000);

	if (cfg->flags & ~WDT_SUPPORTED_CFG_FLAGS) {
		return -ENOTSUP;
	}

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

	if (timeout_ticks > max_timeout || timeout_ticks == 0) {
		return -EINVAL;
	}

	if (data->alloc_cnt == 0) {
		return -ENOMEM;
	}

	data->alloc_cnt--;
	chan_id = data->alloc_cnt;
	data->timeout[chan_id] = timeout_ticks;
	data->callback[chan_id] = cfg->callback;
	data->flags[chan_id] = cfg->flags;

	int err = timeout_set(dev, chan_id, false);

	if (err < 0) {
		return err;
	}

	return chan_id;
}

static int wdt_counter_feed(const struct device *dev, int chan_id)
{
	const struct wdt_counter_config *config = dev->config;

	if (chan_id > counter_get_num_of_channels(config->counter)) {
		return -EINVAL;
	}

	/* Move alarm further in time. */
	return timeout_set(dev, chan_id, true);
}

static const struct wdt_driver_api wdt_counter_driver_api = {
	.setup = wdt_counter_setup,
	.disable = wdt_counter_disable,
	.install_timeout = wdt_counter_install_timeout,
	.feed = wdt_counter_feed,
};

static const struct wdt_counter_config wdt_counter_config = {
	.counter = DEVICE_DT_GET(DT_PHANDLE(DT_WDT_COUNTER, counter)),
};


static int wdt_counter_init(const struct device *dev)
{
	const struct wdt_counter_config *config = dev->config;
	struct wdt_counter_data *data = dev->data;
	uint8_t ch_cnt = counter_get_num_of_channels(config->counter);

	data->alloc_cnt = MIN(ch_cnt, CONFIG_WDT_COUNTER_CH_COUNT);

	return 0;
}

DEVICE_DT_DEFINE(DT_WDT_COUNTER, wdt_counter_init, NULL,
		 &wdt_data, &wdt_counter_config,
		 POST_KERNEL,
		 CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
		 &wdt_counter_driver_api);
