/*
 * Copyright (c) 2016-2019 Nordic Semiconductor ASA
 * Copyright (c) 2016 Vinayak Kariappa Chettimada
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <soc.h>
#include <drivers/clock_control.h>
#include <drivers/clock_control/nrf_clock_control.h>
#include "nrf_clock_calibration.h"
#include <logging/log.h>
#include <hal/nrf_power.h>

LOG_MODULE_REGISTER(clock_control, CONFIG_CLOCK_CONTROL_LOG_LEVEL);

/* Helper logging macros which prepends subsys name to the log. */
#ifdef CONFIG_LOG
#define CLOCK_LOG(lvl, dev, subsys, ...) \
	LOG_##lvl("%s: " GET_ARG1(__VA_ARGS__), \
		get_sub_config(dev, (enum clock_control_nrf_type)subsys)->name \
		COND_CODE_0(NUM_VA_ARGS_LESS_1(__VA_ARGS__),\
				(), (, GET_ARGS_LESS_1(__VA_ARGS__))))
#else
#define CLOCK_LOG(...)
#endif

#define ERR(dev, subsys, ...) CLOCK_LOG(ERR, dev, subsys, __VA_ARGS__)
#define WRN(dev, subsys, ...) CLOCK_LOG(WRN, dev, subsys, __VA_ARGS__)
#define INF(dev, subsys, ...) CLOCK_LOG(INF, dev, subsys, __VA_ARGS__)
#define DBG(dev, subsys, ...) CLOCK_LOG(DBG, dev, subsys, __VA_ARGS__)

/* returns true if clock stopping or starting can be performed. If false then
 * start/stop will be deferred and performed later on by handler owner.
 */
typedef bool (*nrf_clock_handler_t)(struct device *dev);

/* Clock subsys structure */
struct nrf_clock_control_sub_data {
	sys_slist_t list;	/* List of users requesting callback */
	u8_t ref;		/* Users counter */
	bool started;		/* Indicated that clock is started */
};

/* Clock subsys static configuration */
struct nrf_clock_control_sub_config {
	nrf_clock_handler_t start_handler; /* Called before start */
	nrf_clock_handler_t stop_handler; /* Called before stop */
	nrf_clock_event_t started_evt;	/* Clock started event */
	nrf_clock_task_t start_tsk;	/* Clock start task */
	nrf_clock_task_t stop_tsk;	/* Clock stop task */
#ifdef CONFIG_LOG
	const char *name;
#endif
};

struct nrf_clock_control_data {
	struct nrf_clock_control_sub_data subsys[CLOCK_CONTROL_NRF_TYPE_COUNT];
};

struct nrf_clock_control_config {
	struct nrf_clock_control_sub_config
					subsys[CLOCK_CONTROL_NRF_TYPE_COUNT];
};

static void clkstarted_handle(struct device *dev,
			      enum clock_control_nrf_type type);

/* Return true if given event has enabled interrupt and is triggered. Event
 * is cleared.
 */
static bool clock_event_check_and_clean(nrf_clock_event_t evt, u32_t intmask)
{
	bool ret = nrf_clock_event_check(NRF_CLOCK, evt) &&
			nrf_clock_int_enable_check(NRF_CLOCK, intmask);

	if (ret) {
		nrf_clock_event_clear(NRF_CLOCK, evt);
	}

	return ret;
}

static void clock_irqs_disable(void)
{
	nrf_clock_int_disable(NRF_CLOCK,
			(NRF_CLOCK_INT_HF_STARTED_MASK |
			 NRF_CLOCK_INT_LF_STARTED_MASK |
			 COND_CODE_1(CONFIG_USB_NRFX,
				(NRF_POWER_INT_USBDETECTED_MASK |
				 NRF_POWER_INT_USBREMOVED_MASK |
				 NRF_POWER_INT_USBPWRRDY_MASK),
				(0))));
}

static void clock_irqs_enable(void)
{
	nrf_clock_int_enable(NRF_CLOCK,
			(NRF_CLOCK_INT_HF_STARTED_MASK |
			 NRF_CLOCK_INT_LF_STARTED_MASK |
			 COND_CODE_1(CONFIG_USB_NRFX,
				(NRF_POWER_INT_USBDETECTED_MASK |
				 NRF_POWER_INT_USBREMOVED_MASK |
				 NRF_POWER_INT_USBPWRRDY_MASK),
				(0))));
}

static struct nrf_clock_control_sub_data *get_sub_data(struct device *dev,
					      enum clock_control_nrf_type type)
{
	struct nrf_clock_control_data *data = dev->driver_data;

	return &data->subsys[type];
}

static const struct nrf_clock_control_sub_config *get_sub_config(
					struct device *dev,
					enum clock_control_nrf_type type)
{
	const struct nrf_clock_control_config *config =
						dev->config->config_info;

	return &config->subsys[type];
}

static enum clock_control_status get_status(struct device *dev,
					    clock_control_subsys_t subsys)
{
	enum clock_control_nrf_type type = (enum clock_control_nrf_type)subsys;
	struct nrf_clock_control_sub_data *data;

	__ASSERT_NO_MSG(type < CLOCK_CONTROL_NRF_TYPE_COUNT);
	data = get_sub_data(dev, type);
	if (data->started) {
		return CLOCK_CONTROL_STATUS_ON;
	}

	if (data->ref > 0) {
		return CLOCK_CONTROL_STATUS_STARTING;
	}

	return CLOCK_CONTROL_STATUS_OFF;
}

static int clock_stop(struct device *dev, clock_control_subsys_t subsys)
{
	enum clock_control_nrf_type type = (enum clock_control_nrf_type)subsys;
	const struct nrf_clock_control_sub_config *config;
	struct nrf_clock_control_sub_data *data;
	int err = 0;
	int key;

	__ASSERT_NO_MSG(type < CLOCK_CONTROL_NRF_TYPE_COUNT);
	config = get_sub_config(dev, type);
	data = get_sub_data(dev, type);

	key = irq_lock();
	if (data->ref == 0) {
		err = -EALREADY;
		goto out;
	}
	data->ref--;
	if (data->ref == 0) {
		bool do_stop;

		DBG(dev, subsys, "Stopping");
		sys_slist_init(&data->list);

		do_stop =  (config->stop_handler) ?
				config->stop_handler(dev) : true;

		if (do_stop) {
			nrf_clock_task_trigger(NRF_CLOCK, config->stop_tsk);
			/* It may happen that clock is being stopped when it
			 * has just been started and start is not yet handled
			 * (due to irq_lock). In that case after stopping the
			 * clock, started event is cleared to prevent false
			 * interrupt being triggered.
			 */
			nrf_clock_event_clear(NRF_CLOCK, config->started_evt);
		}

		data->started = false;
	}

out:
	irq_unlock(key);

	return err;
}

static bool is_in_list(sys_slist_t *list, sys_snode_t *node)
{
	sys_snode_t *item = sys_slist_peek_head(list);

	do {
		if (item == node) {
			return true;
		}

		item = sys_slist_peek_next(item);
	} while (item);

	return false;
}

static void list_append(sys_slist_t *list, sys_snode_t *node)
{
	int key;

	key = irq_lock();
	sys_slist_append(list, node);
	irq_unlock(key);
}

static struct clock_control_async_data *list_get(sys_slist_t *list)
{
	struct clock_control_async_data *async_data;
	sys_snode_t *node;
	int key;

	key = irq_lock();
	node = sys_slist_get(list);
	irq_unlock(key);
	async_data = CONTAINER_OF(node,
		struct clock_control_async_data, node);

	return async_data;
}

static int clock_async_start(struct device *dev,
			     clock_control_subsys_t subsys,
			     struct clock_control_async_data *data)
{
	enum clock_control_nrf_type type = (enum clock_control_nrf_type)subsys;
	const struct nrf_clock_control_sub_config *config;
	struct nrf_clock_control_sub_data *clk_data;
	int key;
	u8_t ref;

	__ASSERT_NO_MSG(type < CLOCK_CONTROL_NRF_TYPE_COUNT);
	config = get_sub_config(dev, type);
	clk_data = get_sub_data(dev, type);

	__ASSERT_NO_MSG((data == NULL) ||
			((data != NULL) && (data->cb != NULL)));

	/* if node is in the list it means that it is scheduled for
	 * the second time.
	 */
	if ((data != NULL)
	    && is_in_list(&clk_data->list, &data->node)) {
		return -EBUSY;
	}

	key = irq_lock();
	ref = ++clk_data->ref;
	__ASSERT_NO_MSG(clk_data->ref > 0);
	irq_unlock(key);

	if (data) {
		bool already_started;

		clock_irqs_disable();
		already_started = clk_data->started;
		if (!already_started) {
			list_append(&clk_data->list, &data->node);
		}
		clock_irqs_enable();

		if (already_started) {
			data->cb(dev, data->user_data);
		}
	}

	if (ref == 1) {
		bool do_start;

		do_start =  (config->start_handler) ?
				config->start_handler(dev) : true;
		if (do_start) {
			DBG(dev, subsys, "Triggering start task");
			nrf_clock_task_trigger(NRF_CLOCK,
					       config->start_tsk);
		} else {
			/* If external start_handler indicated that clcok is
			 * still running (it may happen in case of LF RC clock
			 * which was requested to be stopped during ongoing
			 * calibration (clock will not be stopped in that case)
			 * and requested to be started before calibration is
			 * completed. In that case clock is still running and
			 * we can notify enlisted requests.
			 */
			clkstarted_handle(dev, type);
		}
	}

	return 0;
}

static int clock_start(struct device *dev, clock_control_subsys_t sub_system)
{
	return clock_async_start(dev, sub_system, NULL);
}

/* Note: this function has public linkage, and MUST have this
 * particular name.  The platform architecture itself doesn't care,
 * but there is a test (tests/kernel/arm_irq_vector_table) that needs
 * to find it to it can set it in a custom vector table.  Should
 * probably better abstract that at some point (e.g. query and reset
 * it by pointer at runtime, maybe?) so we don't have this leaky
 * symbol.
 */
void nrf_power_clock_isr(void *arg);

static int clk_init(struct device *dev)
{
	IRQ_CONNECT(DT_INST_0_NORDIC_NRF_CLOCK_IRQ_0,
		    DT_INST_0_NORDIC_NRF_CLOCK_IRQ_0_PRIORITY,
		    nrf_power_clock_isr, 0, 0);

	irq_enable(DT_INST_0_NORDIC_NRF_CLOCK_IRQ_0);

	nrf_clock_lf_src_set(NRF_CLOCK, CLOCK_CONTROL_NRF_K32SRC);

	if (IS_ENABLED(CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC_CALIBRATION)) {
		z_nrf_clock_calibration_init(dev);
	}

	clock_irqs_enable();

	for (enum clock_control_nrf_type i = 0;
		i < CLOCK_CONTROL_NRF_TYPE_COUNT; i++) {
		sys_slist_init(&(get_sub_data(dev, i)->list));
	}

	return 0;
}
static const struct clock_control_driver_api clock_control_api = {
	.on = clock_start,
	.off = clock_stop,
	.async_on = clock_async_start,
	.get_status = get_status,
};

static struct nrf_clock_control_data data;

static const struct nrf_clock_control_config config = {
	.subsys = {
		[CLOCK_CONTROL_NRF_TYPE_HFCLK] = {
			.start_tsk = NRF_CLOCK_TASK_HFCLKSTART,
			.started_evt = NRF_CLOCK_EVENT_HFCLKSTARTED,
			.stop_tsk = NRF_CLOCK_TASK_HFCLKSTOP,
			IF_ENABLED(CONFIG_LOG, (.name = "hfclk",))
		},
		[CLOCK_CONTROL_NRF_TYPE_LFCLK] = {
			.start_tsk = NRF_CLOCK_TASK_LFCLKSTART,
			.started_evt = NRF_CLOCK_EVENT_LFCLKSTARTED,
			.stop_tsk = NRF_CLOCK_TASK_LFCLKSTOP,
			IF_ENABLED(CONFIG_LOG, (.name = "lfclk",))
			IF_ENABLED(
				CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC_CALIBRATION,
				(
				.start_handler = z_nrf_clock_calibration_start,
				.stop_handler = z_nrf_clock_calibration_stop,
				)
			)
		}
	}
};

DEVICE_AND_API_INIT(clock_nrf,
		    DT_INST_0_NORDIC_NRF_CLOCK_LABEL,
		    clk_init, &data, &config, PRE_KERNEL_1,
		    CONFIG_KERNEL_INIT_PRIORITY_DEVICE,
		    &clock_control_api);

static void clkstarted_handle(struct device *dev,
			      enum clock_control_nrf_type type)
{
	struct nrf_clock_control_sub_data *sub_data = get_sub_data(dev, type);
	struct clock_control_async_data *async_data;

	DBG(dev, type, "Clock started");
	sub_data->started = true;

	while ((async_data = list_get(&sub_data->list)) != NULL) {
		async_data->cb(dev, async_data->user_data);
	}
}

#if defined(CONFIG_USB_NRFX)
static bool power_event_check_and_clean(nrf_power_event_t evt, u32_t intmask)
{
	bool ret = nrf_power_event_check(NRF_POWER, evt) &&
			nrf_power_int_enable_check(NRF_POWER, intmask);

	if (ret) {
		nrf_power_event_clear(NRF_POWER, evt);
	}

	return ret;
}
#endif

static void usb_power_isr(void)
{
#if defined(CONFIG_USB_NRFX)
	extern void usb_dc_nrfx_power_event_callback(nrf_power_event_t event);

	if (power_event_check_and_clean(NRF_POWER_EVENT_USBDETECTED,
					NRF_POWER_INT_USBDETECTED_MASK)) {
		usb_dc_nrfx_power_event_callback(NRF_POWER_EVENT_USBDETECTED);
	}

	if (power_event_check_and_clean(NRF_POWER_EVENT_USBPWRRDY,
					NRF_POWER_INT_USBPWRRDY_MASK)) {
		usb_dc_nrfx_power_event_callback(NRF_POWER_EVENT_USBPWRRDY);
	}

	if (power_event_check_and_clean(NRF_POWER_EVENT_USBREMOVED,
					NRF_POWER_INT_USBREMOVED_MASK)) {
		usb_dc_nrfx_power_event_callback(NRF_POWER_EVENT_USBREMOVED);
	}
#endif
}

void nrf_power_clock_isr(void *arg)
{
	ARG_UNUSED(arg);
	struct device *dev = DEVICE_GET(clock_nrf);

	if (clock_event_check_and_clean(NRF_CLOCK_EVENT_HFCLKSTARTED,
					NRF_CLOCK_INT_HF_STARTED_MASK)) {
		struct nrf_clock_control_sub_data *data =
				get_sub_data(dev, CLOCK_CONTROL_NRF_TYPE_HFCLK);

		/* Check needed due to anomaly 201:
		 * HFCLKSTARTED may be generated twice.
		 */
		if (!data->started) {
			clkstarted_handle(dev, CLOCK_CONTROL_NRF_TYPE_HFCLK);
		}
	}

	if (clock_event_check_and_clean(NRF_CLOCK_EVENT_LFCLKSTARTED,
					NRF_CLOCK_INT_LF_STARTED_MASK)) {
		if (IS_ENABLED(
			CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC_CALIBRATION)) {
			z_nrf_clock_calibration_lfclk_started(dev);
		}
		clkstarted_handle(dev, CLOCK_CONTROL_NRF_TYPE_LFCLK);
	}

	usb_power_isr();

	if (IS_ENABLED(CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC_CALIBRATION)) {
		z_nrf_clock_calibration_isr();
	}
}

#ifdef CONFIG_USB_NRFX
void nrf5_power_usb_power_int_enable(bool enable)
{
	u32_t mask;

	mask = NRF_POWER_INT_USBDETECTED_MASK |
	       NRF_POWER_INT_USBREMOVED_MASK |
	       NRF_POWER_INT_USBPWRRDY_MASK;

	if (enable) {
		nrf_power_int_enable(NRF_POWER, mask);
		irq_enable(DT_INST_0_NORDIC_NRF_CLOCK_IRQ_0);
	} else {
		nrf_power_int_disable(NRF_POWER, mask);
	}
}
#endif
