/*
 * Copyright (c) 2018, NXP
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <errno.h>
#include <string.h>
#include <device.h>
#include <soc.h>
#include <ipm.h>
#include <mu_imx.h>

#define MU(config) ((MU_Type *)config->base)

#if ((CONFIG_IPM_IMX_MAX_DATA_SIZE % 4) != 0)
#error CONFIG_IPM_IMX_MAX_DATA_SIZE is invalid
#endif

#define IMX_IPM_DATA_REGS (CONFIG_IPM_IMX_MAX_DATA_SIZE / 4)

struct imx_mu_config {
	MU_Type *base;
	void (*irq_config_func)(struct device *dev);
};

struct imx_mu_data {
	ipm_callback_t callback;
	void *callback_ctx;
};

static void imx_mu_isr(void *arg)
{
	struct device *dev = (struct device *)arg;
	const struct imx_mu_config *config = dev->config->config_info;
	MU_Type *base = MU(config);
	struct imx_mu_data *data = dev->driver_data;
	u32_t data32[IMX_IPM_DATA_REGS];
	u32_t status_reg;
	s32_t id;
	s32_t i;
	bool all_registers_full;

	status_reg = base->SR >>= MU_SR_RFn_SHIFT;

	for (id = CONFIG_IPM_IMX_MAX_ID_VAL; id >= 0; id--) {
		if (status_reg & 0x1U) {
			/*
			 * Check if all receive registers are full. If not,
			 * it is violation of the protocol (status register
			 * are set earlier than all receive registers).
			 * Do not read any of the registers in such situation.
			 */
			all_registers_full = true;
			for (i = 0; i < IMX_IPM_DATA_REGS; i++) {
				if (!MU_IsRxFull(base,
						(id * IMX_IPM_DATA_REGS) + i)) {
					all_registers_full = false;
					break;
				}
			}
			if (all_registers_full) {
				for (i = 0; i < IMX_IPM_DATA_REGS; i++) {
					MU_ReceiveMsg(base,
						(id * IMX_IPM_DATA_REGS) + i,
						&data32[i]);
				}

				if (data->callback) {
					data->callback(data->callback_ctx,
						       (u32_t)id,
						       &data32[0]);
				}
			}
		}
		status_reg >>= IMX_IPM_DATA_REGS;
	}

	/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F
	 * Store immediate overlapping exception return operation
	 * might vector to incorrect interrupt
	 */
#if defined __CORTEX_M && (__CORTEX_M == 4U)
	__DSB();
#endif
}

static int imx_mu_ipm_send(struct device *dev, int wait, u32_t id,
			   const void *data, int size)
{
	const struct imx_mu_config *config = dev->config->config_info;
	MU_Type *base = MU(config);
	u32_t data32[IMX_IPM_DATA_REGS];
	mu_status_t status;
	int i;

	if (id > CONFIG_IPM_IMX_MAX_ID_VAL) {
		return -EINVAL;
	}

	if (size > CONFIG_IPM_IMX_MAX_DATA_SIZE) {
		return -EMSGSIZE;
	}

	/* Actual message is passing using 32 bits registers */
	memcpy(data32, data, size);

	for (i = 0; i < IMX_IPM_DATA_REGS; i++) {
		status = MU_TrySendMsg(base, id * IMX_IPM_DATA_REGS + i,
				       data32[i]);
		if (status == kStatus_MU_TxNotEmpty) {
			return -EBUSY;
		}
	}

	if (wait) {
		while (!MU_IsTxEmpty(base,
			(id * IMX_IPM_DATA_REGS) + IMX_IPM_DATA_REGS - 1)) {
		}
	}

	return 0;
}

static int imx_mu_ipm_max_data_size_get(struct device *dev)
{
	ARG_UNUSED(dev);

	return CONFIG_IPM_IMX_MAX_DATA_SIZE;
}

static u32_t imx_mu_ipm_max_id_val_get(struct device *dev)
{
	ARG_UNUSED(dev);

	return CONFIG_IPM_IMX_MAX_ID_VAL;
}

static void imx_mu_ipm_register_callback(struct device *dev,
					 ipm_callback_t cb,
					 void *context)
{
	struct imx_mu_data *driver_data = dev->driver_data;

	driver_data->callback = cb;
	driver_data->callback_ctx = context;
}

static int imx_mu_ipm_set_enabled(struct device *dev, int enable)
{
	const struct imx_mu_config *config = dev->config->config_info;
	MU_Type *base = MU(config);

#if CONFIG_IPM_IMX_MAX_DATA_SIZE_4
	if (enable) {
		MU_EnableRxFullInt(base, 0U);
		MU_EnableRxFullInt(base, 1U);
		MU_EnableRxFullInt(base, 2U);
		MU_EnableRxFullInt(base, 3U);
	} else {
		MU_DisableRxFullInt(base, 0U);
		MU_DisableRxFullInt(base, 1U);
		MU_DisableRxFullInt(base, 2U);
		MU_DisableRxFullInt(base, 3U);
	}
#elif CONFIG_IPM_IMX_MAX_DATA_SIZE_8
	if (enable) {
		MU_EnableRxFullInt(base, 1U);
		MU_EnableRxFullInt(base, 3U);
	} else {
		MU_DisableRxFullInt(base, 1U);
		MU_DisableRxFullInt(base, 3U);
	}
#elif CONFIG_IPM_IMX_MAX_DATA_SIZE_16
	if (enable) {
		MU_EnableRxFullInt(base, 3U);
	} else {
		MU_DisableRxFullInt(base, 3U);
	}
#else
#error "CONFIG_IPM_IMX_MAX_DATA_SIZE_n is not set"
#endif

	return 0;
}

static int imx_mu_init(struct device *dev)
{
	const struct imx_mu_config *config = dev->config->config_info;

	MU_Init(MU(config));
	config->irq_config_func(dev);

	return 0;
}

static const struct ipm_driver_api imx_mu_driver_api = {
	.send = imx_mu_ipm_send,
	.register_callback = imx_mu_ipm_register_callback,
	.max_data_size_get = imx_mu_ipm_max_data_size_get,
	.max_id_val_get = imx_mu_ipm_max_id_val_get,
	.set_enabled = imx_mu_ipm_set_enabled
};

/* Config MU */

static void imx_mu_config_func_b(struct device *dev);

static const struct imx_mu_config imx_mu_b_config = {
	.base = (MU_Type *)DT_IPM_IMX_MU_B_BASE_ADDRESS,
	.irq_config_func = imx_mu_config_func_b,
};

static struct imx_mu_data imx_mu_b_data;

DEVICE_AND_API_INIT(mu_b, DT_IPM_IMX_MU_B_NAME,
		    &imx_mu_init,
		    &imx_mu_b_data, &imx_mu_b_config,
		    PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
		    &imx_mu_driver_api);

static void imx_mu_config_func_b(struct device *dev)
{
	IRQ_CONNECT(DT_IPM_IMX_MU_B_IRQ,
		    DT_IPM_IMX_MU_B_IRQ_PRI,
		    imx_mu_isr, DEVICE_GET(mu_b), 0);

	irq_enable(DT_IPM_IMX_MU_B_IRQ);
}
