/*
 * Copyright (c) 2021 Carlo Caione <ccaione@baylibre.com>
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <zephyr/drivers/mbox.h>
#include <nrfx_ipc.h>

#define LOG_LEVEL CONFIG_MBOX_LOG_LEVEL
#include <zephyr/logging/log.h>
#include <zephyr/irq.h>
LOG_MODULE_REGISTER(mbox_nrfx_ipc);

#define DT_DRV_COMPAT nordic_mbox_nrf_ipc

struct mbox_nrf_data {
	mbox_callback_t cb[IPC_CONF_NUM];
	void *user_data[IPC_CONF_NUM];
	const struct device *dev;
	uint32_t enabled_mask;
};

static struct mbox_nrf_data nrfx_mbox_data;

static struct mbox_nrf_conf {
	uint32_t rx_mask;
	uint32_t tx_mask;
} nrfx_mbox_conf = {
	.rx_mask = DT_INST_PROP(0, rx_mask),
	.tx_mask = DT_INST_PROP(0, tx_mask),
};

static inline bool is_rx_channel_valid(const struct device *dev, uint32_t ch)
{
	const struct mbox_nrf_conf *conf = dev->config;

	return ((ch < IPC_CONF_NUM) && (conf->rx_mask & BIT(ch)));
}

static inline bool is_tx_channel_valid(const struct device *dev, uint32_t ch)
{
	const struct mbox_nrf_conf *conf = dev->config;

	return ((ch < IPC_CONF_NUM) && (conf->tx_mask & BIT(ch)));
}

static void mbox_dispatcher(uint8_t event_idx, void *p_context)
{
	struct mbox_nrf_data *data = (struct mbox_nrf_data *) p_context;
	const struct device *dev = data->dev;

	uint32_t channel = event_idx;

	if (!is_rx_channel_valid(dev, channel)) {
		LOG_WRN("RX event on illegal channel");
	}

	if (!(data->enabled_mask & BIT(channel))) {
		LOG_WRN("RX event on disabled channel");
	}

	if (data->cb[channel] != NULL) {
		data->cb[channel](dev, channel, data->user_data[channel], NULL);
	}
}

static int mbox_nrf_send(const struct device *dev, uint32_t channel,
			 const struct mbox_msg *msg)
{
	if (msg) {
		LOG_WRN("Sending data not supported");
	}

	if (!is_tx_channel_valid(dev, channel)) {
		return -EINVAL;
	}

	nrfx_ipc_signal(channel);

	return 0;
}

static int mbox_nrf_register_callback(const struct device *dev, uint32_t channel,
				      mbox_callback_t cb, void *user_data)
{
	struct mbox_nrf_data *data = dev->data;

	if (channel >= IPC_CONF_NUM) {
		return -EINVAL;
	}

	data->cb[channel] = cb;
	data->user_data[channel] = user_data;

	return 0;
}

static int mbox_nrf_mtu_get(const struct device *dev)
{
	/* We only support signalling */
	return 0;
}

static uint32_t mbox_nrf_max_channels_get(const struct device *dev)
{
	return IPC_CONF_NUM;
}

static int mbox_nrf_set_enabled(const struct device *dev, uint32_t channel, bool enable)
{
	struct mbox_nrf_data *data = dev->data;

	if (!is_rx_channel_valid(dev, channel)) {
		return -EINVAL;
	}

	if ((enable == 0 && (!(data->enabled_mask & BIT(channel)))) ||
	    (enable != 0 &&   (data->enabled_mask & BIT(channel)))) {
		return -EALREADY;
	}

	if (enable && (data->cb[channel] == NULL)) {
		LOG_WRN("Enabling channel without a registered callback\n");
	}

	if (enable && data->enabled_mask == 0) {
		irq_enable(DT_INST_IRQN(0));
	}

	if (enable) {
		data->enabled_mask |= BIT(channel);
		compiler_barrier();
		nrfx_ipc_receive_event_enable(channel);
	} else {
		nrfx_ipc_receive_event_disable(channel);
		compiler_barrier();
		data->enabled_mask &= ~BIT(channel);
	}

	if (data->enabled_mask == 0) {
		irq_disable(DT_INST_IRQN(0));
	}

	return 0;
}

static void enable_dt_channels(const struct device *dev)
{
	const struct mbox_nrf_conf *conf = dev->config;
	nrfx_ipc_config_t ch_config = { 0 };

	if (conf->tx_mask >= BIT(IPC_CONF_NUM)) {
		LOG_WRN("tx_mask too big (or IPC_CONF_NUM too small)");
	}

	if (conf->rx_mask >= BIT(IPC_CONF_NUM)) {
		LOG_WRN("rx_mask too big (or IPC_CONF_NUM too small)");
	}

	/* Enable the interrupts on .set_enabled() only */
	ch_config.receive_events_enabled = 0;

	for (size_t ch = 0; ch < IPC_CONF_NUM; ch++) {
		if (conf->tx_mask & BIT(ch)) {
			ch_config.send_task_config[ch] = BIT(ch);
		}

		if (conf->rx_mask & BIT(ch)) {
			ch_config.receive_event_config[ch] = BIT(ch);
		}
	}

	nrfx_ipc_config_load(&ch_config);
}

static int mbox_nrf_init(const struct device *dev)
{
	struct mbox_nrf_data *data = dev->data;

	data->dev = dev;

	nrfx_ipc_init(0, mbox_dispatcher, (void *) data);

	IRQ_CONNECT(DT_INST_IRQN(0), DT_INST_IRQ(0, priority),
		    nrfx_isr, nrfx_ipc_irq_handler, 0);

	enable_dt_channels(dev);

	return 0;
}

static const struct mbox_driver_api mbox_nrf_driver_api = {
	.send = mbox_nrf_send,
	.register_callback = mbox_nrf_register_callback,
	.mtu_get = mbox_nrf_mtu_get,
	.max_channels_get = mbox_nrf_max_channels_get,
	.set_enabled = mbox_nrf_set_enabled,
};

DEVICE_DT_INST_DEFINE(0, mbox_nrf_init, NULL, &nrfx_mbox_data, &nrfx_mbox_conf,
		    POST_KERNEL, CONFIG_MBOX_INIT_PRIORITY,
		    &mbox_nrf_driver_api);
