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

#define DT_DRV_COMPAT nordic_nrf_ipc

#include <string.h>
#include <drivers/ipm.h>
#include <nrfx_ipc.h>
#include "ipm_nrfx_ipc.h"

#define LOG_LEVEL CONFIG_IPM_LOG_LEVEL
#include <logging/log.h>
LOG_MODULE_REGISTER(ipm_nrfx_ipc);

struct ipm_nrf_data {
	ipm_callback_t callback;
	void *user_data;
};

static struct ipm_nrf_data nrfx_ipm_data;

static void gipm_init(void);
static void gipm_send(uint32_t id);

#if IS_ENABLED(CONFIG_IPM_NRF_SINGLE_INSTANCE)

static void nrfx_ipc_handler(uint32_t event_mask, void *p_context)
{
	if (nrfx_ipm_data.callback) {
		while (event_mask) {
			uint8_t event_idx = __CLZ(__RBIT(event_mask));

			__ASSERT(event_idx < NRFX_IPC_ID_MAX_VALUE,
				 "Illegal event_idx: %d", event_idx);
			event_mask &= ~BIT(event_idx);
			nrfx_ipm_data.callback(DEVICE_DT_INST_GET(0),
					       nrfx_ipm_data.user_data,
					       event_idx,
					       NULL);
		}
	}
}

static int ipm_nrf_send(const struct device *dev, int wait, uint32_t id,
			const void *data, int size)
{
	if (id > NRFX_IPC_ID_MAX_VALUE) {
		return -EINVAL;
	}

	if (size > 0) {
		LOG_WRN("nRF driver does not support sending data over IPM");
	}

	gipm_send(id);
	return 0;
}

static int ipm_nrf_max_data_size_get(const struct device *dev)
{
	ARG_UNUSED(dev);

	return 0;
}

static uint32_t ipm_nrf_max_id_val_get(const struct device *dev)
{
	ARG_UNUSED(dev);

	return NRFX_IPC_ID_MAX_VALUE;
}

static void ipm_nrf_register_callback(const struct device *dev,
				      ipm_callback_t cb,
				      void *user_data)
{
	nrfx_ipm_data.callback = cb;
	nrfx_ipm_data.user_data = user_data;
}

static int ipm_nrf_set_enabled(const struct device *dev, int enable)
{
	/* Enable configured channels */
	if (enable) {
		irq_enable(DT_INST_IRQN(0));
		nrfx_ipc_receive_event_group_enable((uint32_t)IPC_EVENT_BITS);
	} else {
		irq_disable(DT_INST_IRQN(0));
		nrfx_ipc_receive_event_group_disable((uint32_t)IPC_EVENT_BITS);
	}
	return 0;
}

static int ipm_nrf_init(const struct device *dev)
{
	gipm_init();
	return 0;
}

static const struct ipm_driver_api ipm_nrf_driver_api = {
	.send = ipm_nrf_send,
	.register_callback = ipm_nrf_register_callback,
	.max_data_size_get = ipm_nrf_max_data_size_get,
	.max_id_val_get = ipm_nrf_max_id_val_get,
	.set_enabled = ipm_nrf_set_enabled
};

DEVICE_DT_INST_DEFINE(0, ipm_nrf_init, NULL, NULL, NULL,
		    PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
		    &ipm_nrf_driver_api);

#else

struct vipm_nrf_data {
	ipm_callback_t callback[NRFX_IPC_ID_MAX_VALUE];
	void *user_data[NRFX_IPC_ID_MAX_VALUE];
	const struct device *ipm_device[NRFX_IPC_ID_MAX_VALUE];
	bool ipm_init;
};

static struct vipm_nrf_data nrfx_vipm_data;

static void vipm_dispatcher(uint32_t event_mask, void *p_context)
{
	while (event_mask) {
		uint8_t event_idx = __CLZ(__RBIT(event_mask));

		__ASSERT(event_idx < NRFX_IPC_ID_MAX_VALUE,
			 "Illegal event_idx: %d", event_idx);
		event_mask &= ~BIT(event_idx);
		if (nrfx_vipm_data.callback[event_idx] != NULL) {
			nrfx_vipm_data.callback[event_idx]
				(nrfx_vipm_data.ipm_device[event_idx],
				 nrfx_vipm_data.user_data[event_idx],
				 0,
				 NULL);
		}
	}
}

static int vipm_nrf_max_data_size_get(const struct device *dev)
{
	return ipm_max_data_size_get(dev);
}

static uint32_t vipm_nrf_max_id_val_get(const struct device *dev)
{
	ARG_UNUSED(dev);

	return 0;
}

static int vipm_nrf_init(const struct device *dev)
{
	if (!nrfx_vipm_data.ipm_init) {
		gipm_init();
		nrfx_vipm_data.ipm_init = true;
	}
	return 0;
}

#define VIPM_DEVICE_1(_idx)						\
static int vipm_nrf_##_idx##_send(const struct device *dev, int wait,	\
				  uint32_t id, const void *data, int size)	\
{									\
	if (!IS_ENABLED(CONFIG_IPM_MSG_CH_##_idx##_TX)) {		\
		LOG_ERR("IPM_" #_idx " is RX message channel");		\
		return -EINVAL;						\
	}								\
									\
	if (id > NRFX_IPC_ID_MAX_VALUE) {				\
		return -EINVAL;						\
	}								\
									\
	if (id != 0) {							\
		LOG_WRN("Passing message ID to IPM with"		\
			"predefined message ID");			\
	}								\
									\
	if (size > 0) {							\
		LOG_WRN("nRF driver does not support"			\
			"sending data over IPM");			\
	}								\
									\
	gipm_send(_idx);						\
	return 0;							\
}									\
									\
static void vipm_nrf_##_idx##_register_callback(const struct device *dev, \
						ipm_callback_t cb,	\
						void *user_data)	\
{									\
	if (IS_ENABLED(CONFIG_IPM_MSG_CH_##_idx##_RX)) {		\
		nrfx_vipm_data.callback[_idx] = cb;			\
		nrfx_vipm_data.user_data[_idx] = user_data;		\
		nrfx_vipm_data.ipm_device[_idx] = dev;			\
	} else {							\
		LOG_WRN("Trying to register a callback"			\
			"for TX channel IPM_" #_idx);			\
	}								\
}									\
									\
static int vipm_nrf_##_idx##_set_enabled(const struct device *dev, int enable)\
{									\
	if (!IS_ENABLED(CONFIG_IPM_MSG_CH_##_idx##_RX)) {		\
		LOG_ERR("IPM_" #_idx " is TX message channel");		\
		return -EINVAL;						\
	} else if (enable) {						\
		irq_enable(DT_INST_IRQN(0));		\
		nrfx_ipc_receive_event_enable(_idx);			\
	} else if (!enable) {						\
		nrfx_ipc_receive_event_disable(_idx);			\
	}								\
	return 0;							\
}									\
									\
static const struct ipm_driver_api vipm_nrf_##_idx##_driver_api = {	\
	.send = vipm_nrf_##_idx##_send,					\
	.register_callback = vipm_nrf_##_idx##_register_callback,	\
	.max_data_size_get = vipm_nrf_max_data_size_get,		\
	.max_id_val_get = vipm_nrf_max_id_val_get,			\
	.set_enabled = vipm_nrf_##_idx##_set_enabled			\
};									\
									\
DEVICE_DEFINE(vipm_nrf_##_idx, "IPM_"#_idx,				\
		    vipm_nrf_init, NULL, NULL, NULL,			\
		    PRE_KERNEL_2, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,	\
		    &vipm_nrf_##_idx##_driver_api)

#define VIPM_DEVICE(_idx, _)						\
	IF_ENABLED(CONFIG_IPM_MSG_CH_##_idx##_ENABLE, (VIPM_DEVICE_1(_idx)))

LISTIFY(NRFX_IPC_ID_MAX_VALUE, VIPM_DEVICE, (;), _);

#endif

static void gipm_init(void)
{
	/* Init IPC */
#if IS_ENABLED(CONFIG_IPM_NRF_SINGLE_INSTANCE)
	nrfx_ipc_init(0, nrfx_ipc_handler, (void *)&nrfx_ipm_data);
#else
	nrfx_ipc_init(0, vipm_dispatcher, (void *)&nrfx_ipm_data);
#endif
	IRQ_CONNECT(DT_INST_IRQN(0),
		    DT_INST_IRQ(0, priority),
		    nrfx_isr, nrfx_ipc_irq_handler, 0);

	/* Set up signals and channels */
	nrfx_ipc_config_load(&ipc_cfg);
}

static void gipm_send(uint32_t id)
{
	nrfx_ipc_signal(id);
}
