/*
 * Copyright (c) 2023 Cypress Semiconductor Corporation (an Infineon company) or
 * an affiliate of Cypress Semiconductor Corporation
 *
 * SPDX-License-Identifier: Apache-2.0
 */

/**
 * @brief I2C driver for Infineon XMC MCU family.
 */

#define DT_DRV_COMPAT infineon_xmc4xxx_i2c

#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(i2c_infineon_xmc4, CONFIG_I2C_LOG_LEVEL);

#include <zephyr/drivers/i2c.h>
#include <zephyr/drivers/pinctrl.h>

#include "i2c-priv.h"

#include <xmc_i2c.h>
#include <xmc_usic.h>

#define USIC_IRQ_MIN  84
#define IRQS_PER_USIC 6

#define I2C_XMC_EVENTS_MASK ( \
	XMC_I2C_CH_EVENT_RECEIVE_START | \
	XMC_I2C_CH_EVENT_DATA_LOST | \
	XMC_I2C_CH_EVENT_TRANSMIT_SHIFT | \
	XMC_I2C_CH_EVENT_TRANSMIT_BUFFER | \
	XMC_I2C_CH_EVENT_STANDARD_RECEIVE | \
	XMC_I2C_CH_EVENT_ALTERNATIVE_RECEIVE | \
	XMC_I2C_CH_EVENT_BAUD_RATE_GENERATOR | \
	XMC_I2C_CH_EVENT_START_CONDITION_RECEIVED | \
	XMC_I2C_CH_EVENT_REPEATED_START_CONDITION_RECEIVED | \
	XMC_I2C_CH_EVENT_STOP_CONDITION_RECEIVED | \
	XMC_I2C_CH_EVENT_NACK | \
	XMC_I2C_CH_EVENT_ARBITRATION_LOST | \
	XMC_I2C_CH_EVENT_SLAVE_READ_REQUEST | \
	XMC_I2C_CH_EVENT_ERROR | \
	XMC_I2C_CH_EVENT_ACK)

#define I2C_XMC_STATUS_FLAG_ERROR_MASK ( \
	XMC_I2C_CH_STATUS_FLAG_WRONG_TDF_CODE_FOUND | \
	XMC_I2C_CH_STATUS_FLAG_NACK_RECEIVED | \
	XMC_I2C_CH_STATUS_FLAG_ARBITRATION_LOST | \
	XMC_I2C_CH_STATUS_FLAG_ERROR | \
	XMC_I2C_CH_STATUS_FLAG_DATA_LOST_INDICATION)

/* I2C speed */
#define XMC4_I2C_SPEED_STANDARD     (100000UL)
#define XMC4_I2C_SPEED_FAST         (400000UL)

/* Data structure */
struct ifx_xmc4_i2c_data {
	XMC_I2C_CH_CONFIG_t cfg;
	struct k_sem operation_sem;
	struct k_sem target_sem;
	struct i2c_target_config *p_target_config;
	uint32_t dev_config;
	uint8_t target_wr_byte;
	uint8_t target_wr_buffer[CONFIG_I2C_INFINEON_XMC4_TARGET_BUF];
	bool ignore_slave_select;
	bool is_configured;
};

/* Device config structure */
struct ifx_xmc4_i2c_config {
	XMC_USIC_CH_t *i2c;
	const struct pinctrl_dev_config *pcfg;
	uint8_t scl_src;
	uint8_t sda_src;
	uint32_t bitrate;
	void (*irq_config_func)(const struct device *dev);
};

static int ifx_xmc4_i2c_configure(const struct device *dev, uint32_t dev_config)
{
	struct ifx_xmc4_i2c_data *data = dev->data;
	const struct ifx_xmc4_i2c_config *config = dev->config;

	/* This is deprecated and could be ignored in the future */
	if (dev_config & I2C_ADDR_10_BITS) {
		LOG_ERR("Use I2C_MSG_ADDR_10_BITS instead of I2C_ADDR_10_BITS");
		return -EIO;
	}

	switch (I2C_SPEED_GET(dev_config)) {
	case I2C_SPEED_STANDARD:
		data->cfg.baudrate = XMC4_I2C_SPEED_STANDARD;
		break;
	case I2C_SPEED_FAST:
		data->cfg.baudrate = XMC4_I2C_SPEED_FAST;
		break;
	default:
		LOG_ERR("Unsupported speed");
		return -ERANGE;
	}

	data->dev_config = dev_config;

	/* Acquire semaphore (block I2C operation for another thread) */
	if (k_sem_take(&data->operation_sem, K_FOREVER)) {
		return -EIO;
	}

	XMC_I2C_CH_Stop(config->i2c);

	/* Configure the I2C resource */
	data->cfg.normal_divider_mode = false;
	XMC_I2C_CH_Init(config->i2c, &data->cfg);
	XMC_I2C_CH_SetInputSource(config->i2c, XMC_I2C_CH_INPUT_SCL, config->scl_src);
	XMC_I2C_CH_SetInputSource(config->i2c, XMC_I2C_CH_INPUT_SDA, config->sda_src);
	if (data->dev_config & I2C_MODE_CONTROLLER) {
		XMC_USIC_CH_SetFractionalDivider(config->i2c,
						 XMC_USIC_CH_BRG_CLOCK_DIVIDER_MODE_FRACTIONAL,
						 1023U);
	} else {
		config->irq_config_func(dev);
	}
	XMC_I2C_CH_Start(config->i2c);
	data->is_configured = true;

	/* Release semaphore */
	k_sem_give(&data->operation_sem);

	return 0;
}

static int ifx_xmc4_i2c_get_config(const struct device *dev, uint32_t *dev_config)
{
	struct ifx_xmc4_i2c_data *data = dev->data;
	const struct ifx_xmc4_i2c_config *config = dev->config;

	if (!data->is_configured) {
		/* if not yet configured return configuration that will be used */
		/* when transfer() is called */
		uint32_t bitrate_cfg = i2c_map_dt_bitrate(config->bitrate);

		*dev_config = I2C_MODE_CONTROLLER | bitrate_cfg;
		return 0;
	}

	*dev_config = data->dev_config;

	return 0;
}

static int ifx_xmc4_i2c_msg_validate(struct i2c_msg *msg, uint8_t num_msgs)
{
	for (uint32_t i = 0u; i < num_msgs; i++) {
		if ((I2C_MSG_ADDR_10_BITS & msg[i].flags) || (msg[i].buf == NULL)) {
			return -EINVAL;
		}
	}
	return 0;
}

static int ifx_xmc4_i2c_transfer(const struct device *dev, struct i2c_msg *msg, uint8_t num_msgs,
				 uint16_t addr)
{
	struct ifx_xmc4_i2c_data *data = dev->data;
	const struct ifx_xmc4_i2c_config *config = dev->config;
	XMC_I2C_CH_CMD_t cmd_type;

	if (!num_msgs) {
		return 0;
	}

	if (!data->is_configured) {
		int ret;
		uint32_t bitrate_cfg = i2c_map_dt_bitrate(config->bitrate);

		ret = ifx_xmc4_i2c_configure(dev, I2C_MODE_CONTROLLER | bitrate_cfg);
		if (ret) {
			return ret;
		}
	}

	/* Acquire semaphore (block I2C transfer for another thread) */
	if (k_sem_take(&data->operation_sem, K_FOREVER)) {
		return -EIO;
	}

	/* This function checks if msg.buf is not NULL and if target address is not 10 bit. */
	if (ifx_xmc4_i2c_msg_validate(msg, num_msgs) != 0) {
		k_sem_give(&data->operation_sem);
		return -EINVAL;
	}

	for (uint32_t msg_index = 0u; msg_index < num_msgs; msg_index++) {
		XMC_I2C_CH_ClearStatusFlag(config->i2c, 0xFFFFFFFF);

		if ((msg_index == 0) || (msg[msg_index].flags & I2C_MSG_RESTART)) {
			/* Send START conditon */
			cmd_type = ((msg[msg_index].flags & I2C_MSG_RW_MASK) == I2C_MSG_READ) ?
				XMC_I2C_CH_CMD_READ : XMC_I2C_CH_CMD_WRITE;

			if (msg[msg_index].flags & I2C_MSG_RESTART) {
				XMC_I2C_CH_MasterRepeatedStart(config->i2c, addr << 1, cmd_type);
			} else {
				XMC_I2C_CH_MasterStart(config->i2c, addr << 1, cmd_type);
			}

			/* Wait for acknowledge */
			while ((XMC_I2C_CH_GetStatusFlag(config->i2c) &
				XMC_I2C_CH_STATUS_FLAG_ACK_RECEIVED) == 0U) {
				/* wait for ACK from slave */
				if (XMC_I2C_CH_GetStatusFlag(config->i2c) &
				    I2C_XMC_STATUS_FLAG_ERROR_MASK) {
					k_sem_give(&data->operation_sem);
					return -EIO;
				}
			}
			XMC_I2C_CH_ClearStatusFlag(config->i2c,
						   XMC_I2C_CH_STATUS_FLAG_ACK_RECEIVED);
		}

		for (uint32_t buf_index = 0u; buf_index < msg[msg_index].len; buf_index++) {
			if (cmd_type == XMC_I2C_CH_CMD_WRITE) {
				/* Transmit next command from I2C master to I2C slave */
				XMC_I2C_CH_MasterTransmit(config->i2c,
							  msg[msg_index].buf[buf_index]);

				/* Wait for acknowledge */
				while ((XMC_I2C_CH_GetStatusFlag(config->i2c) &
					XMC_I2C_CH_STATUS_FLAG_ACK_RECEIVED) == 0U) {
					/* wait for ACK from slave */
					if (XMC_I2C_CH_GetStatusFlag(config->i2c) &
					    I2C_XMC_STATUS_FLAG_ERROR_MASK) {
						k_sem_give(&data->operation_sem);
						return -EIO;
					}
				}
				XMC_I2C_CH_ClearStatusFlag(config->i2c,
							   XMC_I2C_CH_STATUS_FLAG_ACK_RECEIVED);

				/* Wait until TX FIFO is empty */
				while (!XMC_USIC_CH_TXFIFO_IsEmpty(config->i2c)) {
					/* wait until all data is sent by HW */
					if (XMC_I2C_CH_GetStatusFlag(config->i2c) &
					    I2C_XMC_STATUS_FLAG_ERROR_MASK) {
						k_sem_give(&data->operation_sem);
						return -EIO;
					}
				}
			} else {
				if (buf_index == (msg[msg_index].len - 1)) {
					XMC_I2C_CH_MasterReceiveNack(config->i2c);
				} else {
					XMC_I2C_CH_MasterReceiveAck(config->i2c);
				}

				while ((XMC_I2C_CH_GetStatusFlag(config->i2c) &
				       (XMC_I2C_CH_STATUS_FLAG_ALTERNATIVE_RECEIVE_INDICATION |
					XMC_I2C_CH_STATUS_FLAG_RECEIVE_INDICATION)) == 0U) {
					/* wait for data byte from slave */
					if (XMC_I2C_CH_GetStatusFlag(config->i2c) &
					    I2C_XMC_STATUS_FLAG_ERROR_MASK) {
						k_sem_give(&data->operation_sem);
						return -EIO;
					}
				}
				XMC_I2C_CH_ClearStatusFlag(config->i2c,
					XMC_I2C_CH_STATUS_FLAG_ALTERNATIVE_RECEIVE_INDICATION |
					XMC_I2C_CH_STATUS_FLAG_RECEIVE_INDICATION);

				msg[msg_index].buf[buf_index] =
					XMC_I2C_CH_GetReceivedData(config->i2c);
			}
		}

		/* Send STOP conditon */
		if (msg[msg_index].flags & I2C_MSG_STOP) {
			XMC_I2C_CH_MasterStop(config->i2c);
		}
	}

	/* Release semaphore (After I2C transfer is complete) */
	k_sem_give(&data->operation_sem);
	return 0;
}

static int ifx_xmc4_i2c_init(const struct device *dev)
{
	struct ifx_xmc4_i2c_data *data = dev->data;
	const struct ifx_xmc4_i2c_config *config = dev->config;
	int ret;

	/* Configure semaphores */
	ret = k_sem_init(&data->operation_sem, 1, 1);
	if (ret) {
		return ret;
	}

	ret = k_sem_init(&data->target_sem, 1, 1);
	if (ret) {
		return ret;
	}

	/* Configure dt provided device signals when available */
	return pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT);
}

static int ifx_xmc4_i2c_target_register(const struct device *dev, struct i2c_target_config *cfg)
{
	struct ifx_xmc4_i2c_data *data = dev->data;
	const struct ifx_xmc4_i2c_config *config = dev->config;
	uint32_t bitrate_cfg;

	if (!cfg ||
	    !cfg->callbacks->read_requested ||
	    !cfg->callbacks->read_processed ||
	    !cfg->callbacks->write_requested ||
	    !cfg->callbacks->write_received ||
	    !cfg->callbacks->stop) {
		return -EINVAL;
	}

	if (cfg->flags & I2C_TARGET_FLAGS_ADDR_10_BITS) {
		return -ENOTSUP;
	}

	/* Acquire semaphore (block I2C operation for another thread) */
	if (k_sem_take(&data->target_sem, K_FOREVER)) {
		return -EIO;
	}

	data->p_target_config = cfg;
	data->cfg.address = cfg->address << 1;

	if (data->is_configured) {
		uint32_t bitrate;

		bitrate = I2C_SPEED_GET(data->dev_config);
		bitrate_cfg = i2c_map_dt_bitrate(bitrate);
	} else {
		bitrate_cfg = i2c_map_dt_bitrate(config->bitrate);
	}

	if (ifx_xmc4_i2c_configure(dev, bitrate_cfg) != 0) {
		/* Release semaphore */
		k_sem_give(&data->target_sem);
		return -EIO;
	}

	k_sem_give(&data->target_sem);
	return 0;
}

static int ifx_xmc4_i2c_target_unregister(const struct device *dev, struct i2c_target_config *cfg)
{
	struct ifx_xmc4_i2c_data *data = dev->data;
	const struct ifx_xmc4_i2c_config *config = dev->config;

	/* Acquire semaphore (block I2C operation for another thread) */
	if (k_sem_take(&data->operation_sem, K_FOREVER)) {
		return -EIO;
	}

	data->p_target_config = NULL;
	XMC_I2C_CH_DisableEvent(config->i2c, I2C_XMC_EVENTS_MASK);

	/* Release semaphore */
	k_sem_give(&data->operation_sem);
	return 0;
}


static void i2c_xmc4_isr(const struct device *dev)
{
	struct ifx_xmc4_i2c_data *data = dev->data;
	const struct ifx_xmc4_i2c_config *config = dev->config;
	const struct i2c_target_callbacks *callbacks = data->p_target_config->callbacks;
	uint32_t status = XMC_I2C_CH_GetStatusFlag(config->i2c);

	while (status) {
		XMC_I2C_CH_ClearStatusFlag(config->i2c, status);

		if (status & XMC_I2C_CH_STATUS_FLAG_STOP_CONDITION_RECEIVED) {
			/* Flush the TX buffer */
			XMC_USIC_CH_SetTransmitBufferStatus(config->i2c,
							    XMC_USIC_CH_TBUF_STATUS_SET_IDLE);

			callbacks->stop(data->p_target_config);
			break;
		}

		if (!data->ignore_slave_select && (status & XMC_I2C_CH_STATUS_FLAG_SLAVE_SELECT)) {
			data->ignore_slave_select = true;

			/* Start a slave read */
			if (status & XMC_I2C_CH_STATUS_FLAG_SLAVE_READ_REQUESTED) {
				callbacks->read_requested(data->p_target_config,
							  &data->target_wr_byte);
				XMC_I2C_CH_SlaveTransmit(config->i2c, data->target_wr_byte);
			} else {
				callbacks->write_requested(data->p_target_config);
			}
		}

		/* Continue a slave read */
		if (status & XMC_I2C_CH_STATUS_FLAG_TRANSMIT_SHIFT_INDICATION) {
			callbacks->read_processed(data->p_target_config, &data->target_wr_byte);
			XMC_I2C_CH_SlaveTransmit(config->i2c, data->target_wr_byte);
		}

		/* Start/Continue a slave write */
		if (status & (XMC_I2C_CH_STATUS_FLAG_RECEIVE_INDICATION |
		    XMC_I2C_CH_STATUS_FLAG_ALTERNATIVE_RECEIVE_INDICATION)) {
			callbacks->write_received(data->p_target_config,
						  XMC_I2C_CH_GetReceivedData(config->i2c));
		}

		if ((status & XMC_I2C_CH_STATUS_FLAG_START_CONDITION_RECEIVED) ||
		    (status & XMC_I2C_CH_STATUS_FLAG_REPEATED_START_CONDITION_RECEIVED)) {
			data->ignore_slave_select = false;
		}

		status = XMC_I2C_CH_GetStatusFlag(config->i2c);
	}
}


/* I2C API structure */
static const struct i2c_driver_api i2c_xmc4_driver_api = {
	.configure = ifx_xmc4_i2c_configure,
	.transfer = ifx_xmc4_i2c_transfer,
	.get_config = ifx_xmc4_i2c_get_config,
	.target_register = ifx_xmc4_i2c_target_register,
	.target_unregister = ifx_xmc4_i2c_target_unregister};

/* Macros for I2C instance declaration */
#define XMC4_IRQ_HANDLER_INIT(index)                                                               \
	static void i2c_xmc4_irq_setup_##index(const struct device *dev)                           \
	{                                                                                          \
		const struct ifx_xmc4_i2c_config *config = dev->config;                            \
		uint8_t irq_num = DT_INST_IRQN(index);                                             \
		uint8_t service_request = (irq_num - USIC_IRQ_MIN) % IRQS_PER_USIC;                \
												   \
		XMC_I2C_CH_SelectInterruptNodePointer(config->i2c,                                 \
			XMC_I2C_CH_INTERRUPT_NODE_POINTER_RECEIVE, service_request);               \
		XMC_I2C_CH_SelectInterruptNodePointer(config->i2c,                                 \
			XMC_I2C_CH_INTERRUPT_NODE_POINTER_ALTERNATE_RECEIVE, service_request);     \
												   \
		XMC_I2C_CH_EnableEvent(config->i2c, I2C_XMC_EVENTS_MASK);                          \
												   \
		IRQ_CONNECT(DT_INST_IRQN(index), DT_INST_IRQ(index, priority), i2c_xmc4_isr,       \
			    DEVICE_DT_INST_GET(index), 0);                                         \
												   \
		irq_enable(irq_num);                                                               \
	}

#define XMC4_IRQ_HANDLER_STRUCT_INIT(index) .irq_config_func = i2c_xmc4_irq_setup_##index

#define INFINEON_XMC4_I2C_INIT(n)                                                                  \
	PINCTRL_DT_INST_DEFINE(n);                                                                 \
	XMC4_IRQ_HANDLER_INIT(n)                                                                   \
                                                                                                   \
	static struct ifx_xmc4_i2c_data ifx_xmc4_i2c_data##n;                                      \
                                                                                                   \
	static const struct ifx_xmc4_i2c_config i2c_xmc4_cfg_##n = {                               \
		.i2c = (XMC_USIC_CH_t *)DT_INST_REG_ADDR(n),                                       \
		.pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n),                                         \
		.scl_src = DT_INST_ENUM_IDX(n, scl_src),                                           \
		.sda_src = DT_INST_ENUM_IDX(n, sda_src),                                           \
		.bitrate = DT_INST_PROP_OR(n, clock_frequency, I2C_SPEED_STANDARD),                \
		XMC4_IRQ_HANDLER_STRUCT_INIT(n)                                                    \
	};                                                                                         \
                                                                                                   \
	I2C_DEVICE_DT_INST_DEFINE(n, ifx_xmc4_i2c_init, NULL, &ifx_xmc4_i2c_data##n,               \
				  &i2c_xmc4_cfg_##n, POST_KERNEL,                                  \
				  CONFIG_I2C_INIT_PRIORITY, &i2c_xmc4_driver_api);

DT_INST_FOREACH_STATUS_OKAY(INFINEON_XMC4_I2C_INIT)
