/*
 * Copyright (c) 2020-2023 Intel Corporation
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#define DT_DRV_COMPAT intel_sedi_ipm

#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/pm/device.h>
#include <zephyr/drivers/ipm.h>

#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(ipm_sedi, CONFIG_IPM_LOG_LEVEL);

#include "ipm_sedi.h"

extern void sedi_ipc_isr(IN sedi_ipc_t ipc_device);

static void set_ipm_dev_busy(const struct device *dev, bool is_write)
{
	struct ipm_sedi_context *ipm = dev->data;
	unsigned int key = irq_lock();

	atomic_set_bit(&ipm->status, is_write ? IPM_WRITE_BUSY_BIT : IPM_READ_BUSY_BIT);
	pm_device_busy_set(dev);
	irq_unlock(key);
}

static void clear_ipm_dev_busy(const struct device *dev, bool is_write)
{
	struct ipm_sedi_context *ipm = dev->data;
	unsigned int key = irq_lock();

	atomic_clear_bit(&ipm->status, is_write ? IPM_WRITE_BUSY_BIT : IPM_READ_BUSY_BIT);
	if ((!atomic_test_bit(&ipm->status, IPM_WRITE_BUSY_BIT))
		&& (!atomic_test_bit(&ipm->status, IPM_READ_BUSY_BIT))) {
		pm_device_busy_clear(dev);
	}
	irq_unlock(key);
}

static void ipm_event_dispose(IN sedi_ipc_t device, IN uint32_t event, INOUT void *params)
{
	const struct device *dev = (const struct device *)params;
	struct ipm_sedi_context *ipm = dev->data;
	uint32_t drbl_in = 0, len;

	LOG_DBG("dev: %u, event: %u", device, event);
	switch (event) {
	case SEDI_IPC_EVENT_MSG_IN:
		if (ipm->rx_msg_notify_cb != NULL) {
			set_ipm_dev_busy(dev, false);
			sedi_ipc_read_dbl(device, &drbl_in);
			len = IPC_HEADER_GET_LENGTH(drbl_in);
			sedi_ipc_read_msg(device, ipm->incoming_data_buf, len);
			ipm->rx_msg_notify_cb(dev,
					      ipm->rx_msg_notify_cb_data,
					      drbl_in, ipm->incoming_data_buf);
		} else {
			LOG_WRN("no handler for ipm new msg");
		}
		break;
	case SEDI_IPC_EVENT_MSG_PEER_ACKED:
		if (atomic_test_bit(&ipm->status, IPM_WRITE_IN_PROC_BIT)) {
			k_sem_give(&ipm->device_write_msg_sem);
		} else {
			LOG_WRN("no sending in progress, got an ack");
		}
		break;
	default:
		return;
	}
}

static int ipm_init(const struct device *dev)
{
	/* allocate resource and context*/
	const struct ipm_sedi_config_t *info = dev->config;
	sedi_ipc_t device = info->ipc_device;
	struct ipm_sedi_context *ipm = dev->data;

	info->irq_config();
	k_sem_init(&ipm->device_write_msg_sem, 0, 1);
	k_mutex_init(&ipm->device_write_lock);
	ipm->status = 0;

	sedi_ipc_init(device, ipm_event_dispose, (void *)dev);
	atomic_set_bit(&ipm->status, IPM_PEER_READY_BIT);
	LOG_DBG("ipm driver initialized on device: %p", dev);
	return 0;
}

static int ipm_send_isr(const struct device *dev,
			 uint32_t drbl,
			 const void *msg,
			 int msg_size)
{
	const struct ipm_sedi_config_t *info = dev->config;
	sedi_ipc_t device = info->ipc_device;
	uint32_t drbl_acked = 0;

	sedi_ipc_write_msg(device, (uint8_t *)msg,
			   (uint32_t)msg_size);
	sedi_ipc_write_dbl(device, drbl);
	do {
		sedi_ipc_read_ack_drbl(device, &drbl_acked);
	} while ((drbl_acked & BIT(IPC_BUSY_BIT)) == 0);

	return 0;
}

static int ipm_sedi_send(const struct device *dev,
		     int wait,
		     uint32_t drbl,
		     const void *msg,
		     int msg_size)
{
	__ASSERT((dev != NULL), "bad params\n");
	const struct ipm_sedi_config_t *info = dev->config;
	struct ipm_sedi_context *ipm = dev->data;
	sedi_ipc_t device = info->ipc_device;
	int ret, sedi_ret;

	/* check params, check status */
	if ((msg_size > IPC_DATA_LEN_MAX) || ((msg_size > 0) && (msg == NULL)) ||
	    ((drbl & BIT(IPC_BUSY_BIT)) == 0)) {
		LOG_ERR("bad params when sending ipm msg on device: %p", dev);
		return -EINVAL;
	}

	if (wait == 0) {
		LOG_ERR("not support no wait mode when sending ipm msg");
		return -ENOTSUP;
	}

	if (k_is_in_isr()) {
		return ipm_send_isr(dev, drbl, msg, msg_size);
	}

	k_mutex_lock(&ipm->device_write_lock, K_FOREVER);
	set_ipm_dev_busy(dev, true);

	if (!atomic_test_bit(&ipm->status, IPM_PEER_READY_BIT)) {
		LOG_WRN("peer is not ready");
		ret = -EBUSY;
		goto write_err;
	}

	/* write data regs */
	if (msg_size > 0) {
		sedi_ret = sedi_ipc_write_msg(device, (uint8_t *)msg,
					 (uint32_t)msg_size);
		if (sedi_ret != SEDI_DRIVER_OK) {
			LOG_ERR("ipm write data fail on device: %p", dev);
			ret = -EBUSY;
			goto write_err;
		}
	}

	atomic_set_bit(&ipm->status, IPM_WRITE_IN_PROC_BIT);
	/* write drbl regs to interrupt peer*/
	sedi_ret = sedi_ipc_write_dbl(device, drbl);

	if (sedi_ret != SEDI_DRIVER_OK) {
		LOG_ERR("ipm write doorbell fail on device: %p", dev);
		ret = -EBUSY;
		goto func_out;
	}

	/* wait for busy-bit-consumed interrupt */
	ret = k_sem_take(&ipm->device_write_msg_sem, K_MSEC(IPM_TIMEOUT_MS));
	if (ret) {
		LOG_WRN("ipm write timeout on device: %p", dev);
		sedi_ipc_write_dbl(device, 0);
	}

func_out:
	atomic_clear_bit(&ipm->status, IPM_WRITE_IN_PROC_BIT);

write_err:
	clear_ipm_dev_busy(dev, true);
	k_mutex_unlock(&ipm->device_write_lock);
	if (ret == 0) {
		LOG_DBG("ipm wrote a new message on device: %p, drbl=%08x",
			dev, drbl);
	}
	return ret;
}

static void ipm_sedi_register_callback(const struct device *dev, ipm_callback_t cb,
			  void *user_data)
{
	__ASSERT((dev != NULL), "bad params\n");

	struct ipm_sedi_context *ipm = dev->data;

	if (cb == NULL) {
		LOG_ERR("bad params when add ipm callback on device: %p", dev);
		return;
	}

	if (ipm->rx_msg_notify_cb == NULL) {
		ipm->rx_msg_notify_cb = cb;
		ipm->rx_msg_notify_cb_data = user_data;
	} else {
		LOG_ERR("ipm rx callback already exists on device: %p", dev);
	}
}

static void ipm_sedi_complete(const struct device *dev)
{
	int ret;

	__ASSERT((dev != NULL), "bad params\n");

	const struct ipm_sedi_config_t *info = dev->config;
	sedi_ipc_t device = info->ipc_device;

	ret = sedi_ipc_send_ack_drbl(device, 0);
	if (ret != SEDI_DRIVER_OK) {
		LOG_ERR("ipm send ack drl fail on device: %p", dev);
	}

	clear_ipm_dev_busy(dev, false);
}

static int ipm_sedi_get_max_data_size(const struct device *ipmdev)
{
	ARG_UNUSED(ipmdev);
	return IPC_DATA_LEN_MAX;
}

static uint32_t ipm_sedi_get_max_id(const struct device *ipmdev)
{
	ARG_UNUSED(ipmdev);
	return UINT32_MAX;
}

static int ipm_sedi_set_enable(const struct device *dev, int enable)
{
	__ASSERT((dev != NULL), "bad params\n");

	const struct ipm_sedi_config_t *info = dev->config;

	if (enable) {
		irq_enable(info->irq_num);
	} else {
		irq_disable(info->irq_num);
	}
	return 0;
}

#if defined(CONFIG_PM_DEVICE)
static int ipm_power_ctrl(const struct device *dev,
			  enum pm_device_action action)
{
	return 0;
}
#endif

static const struct ipm_driver_api ipm_funcs = {
	.send = ipm_sedi_send,
	.register_callback = ipm_sedi_register_callback,
	.max_data_size_get = ipm_sedi_get_max_data_size,
	.max_id_val_get = ipm_sedi_get_max_id,
	.complete = ipm_sedi_complete,
	.set_enabled = ipm_sedi_set_enable
};

#define IPM_SEDI_DEV_DEFINE(n)						\
	static struct ipm_sedi_context ipm_data_##n;			\
	static void ipm_##n##_irq_config(void);				\
	static const struct ipm_sedi_config_t ipm_config_##n = {	\
		.ipc_device = DT_INST_PROP(n, peripheral_id),		\
		.irq_num = DT_INST_IRQN(n),				\
		.irq_config = ipm_##n##_irq_config,			\
	};								\
	static void ipm_##n##_irq_config(void)				\
	{								\
		IRQ_CONNECT(DT_INST_IRQN(n),				\
			    DT_INST_IRQ(n, priority), sedi_ipc_isr,	\
			    DT_INST_PROP(n, peripheral_id),		\
			    DT_INST_IRQ(n, sense));			\
	}								\
	PM_DEVICE_DT_DEFINE(DT_NODELABEL(ipm##n), ipm_power_ctrl);	\
	DEVICE_DT_INST_DEFINE(n,					\
			      &ipm_init,				\
			      PM_DEVICE_DT_GET(DT_NODELABEL(ipm##n)),   \
			      &ipm_data_##n,				\
			      &ipm_config_##n,				\
			      POST_KERNEL,				\
			      0,					\
			      &ipm_funcs);

DT_INST_FOREACH_STATUS_OKAY(IPM_SEDI_DEV_DEFINE)
