/*
 * Copyright (c), 2023 Basalte bv
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#define DT_DRV_COMPAT nxp_sc18im704_i2c

#include <errno.h>
#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/init.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/drivers/i2c.h>
#include <zephyr/drivers/uart.h>

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

#include "i2c_sc18im704.h"

struct i2c_sc18im_config {
	const struct device *bus;
	uint32_t bus_speed;
	const struct gpio_dt_spec reset_gpios;
};

struct i2c_sc18im_data {
	struct k_mutex lock;
	uint32_t i2c_config;
};

int sc18im704_claim(const struct device *dev)
{
	struct i2c_sc18im_data *data = dev->data;

	return k_mutex_lock(&data->lock, K_FOREVER);
}

int sc18im704_release(const struct device *dev)
{
	struct i2c_sc18im_data *data = dev->data;

	return k_mutex_unlock(&data->lock);
}

int sc18im704_transfer(const struct device *dev,
		       const uint8_t *tx_data, uint8_t tx_len,
		       uint8_t *rx_data, uint8_t rx_len)
{
	const struct i2c_sc18im_config *cfg = dev->config;
	struct i2c_sc18im_data *data = dev->data;
	int ret = 0;

	ret = k_mutex_lock(&data->lock, K_FOREVER);
	if (ret < 0) {
		return ret;
	}

	if (tx_data != NULL) {
		for (uint8_t i = 0; i < tx_len; ++i)  {
			uart_poll_out(cfg->bus, tx_data[i]);
		}
	}

	if (rx_data != NULL) {
		uint64_t end;

		for (uint8_t i = 0; i < rx_len && ret == 0; ++i)  {
			/* Make sure we don't wait forever */
			end = sys_clock_timeout_end_calc(K_SECONDS(1));

			do {
				ret = uart_poll_in(cfg->bus, &rx_data[i]);
			} while (ret == -1 && end > k_uptime_ticks());
		}

		/* -1 indicates we timed out */
		ret = ret == -1 ? -EAGAIN : ret;

		if (ret < 0) {
			LOG_ERR("Failed to read data (%d)", ret);
		}
	}

	k_mutex_unlock(&data->lock);

	return ret;
}

static int i2c_sc18im_configure(const struct device *dev, uint32_t config)
{
	struct i2c_sc18im_data *data = dev->data;

	if (!(I2C_MODE_CONTROLLER & config)) {
		return -EINVAL;
	}

	if (I2C_ADDR_10_BITS & config) {
		return -EINVAL;
	}

	if (I2C_SPEED_GET(config) != I2C_SPEED_GET(data->i2c_config)) {
		uint8_t buf[] = {
			SC18IM704_CMD_WRITE_REG,
			SC18IM704_REG_I2C_CLK_L,
			0,
			SC18IM704_CMD_STOP,
		};
		int ret;

		/* CLK value is calculated as 15000000 / (8 * freq), see datasheet */
		switch (I2C_SPEED_GET(config)) {
		case I2C_SPEED_STANDARD:
			buf[2] = 0x13; /* 99 kHz */
			break;
		case I2C_SPEED_FAST:
			buf[2] = 0x05; /* 375 kHz */
			break;
		default:
			return -EINVAL;
		}

		ret = sc18im704_transfer(dev, buf, sizeof(buf), NULL, 0);
		if (ret < 0) {
			LOG_ERR("Failed to set I2C speed (%d)", ret);
			return -EIO;
		}
	}

	data->i2c_config = config;

	return 0;
}

static int i2c_sc18im_get_config(const struct device *dev, uint32_t *config)
{
	struct i2c_sc18im_data *data = dev->data;

	*config = data->i2c_config;

	return 0;
}

static int i2c_sc18im_transfer_msg(const struct device *dev,
				   struct i2c_msg *msg,
				   uint16_t addr)
{
	uint8_t start[] = {
		SC18IM704_CMD_I2C_START,
		0x00,
		0x00,
	};
	uint8_t stop = SC18IM704_CMD_STOP;
	int ret;

	if (msg->flags & I2C_MSG_ADDR_10_BITS || msg->len > UINT8_MAX) {
		return -EINVAL;
	}

	start[1] = addr | (msg->flags & I2C_MSG_RW_MASK);
	start[2] = msg->len;

	ret = sc18im704_transfer(dev, start, sizeof(start), NULL, 0);
	if (ret < 0) {
		return ret;
	}

	if (msg->flags & I2C_MSG_READ) {
		/* Send the stop character before reading */
		ret = sc18im704_transfer(dev, &stop, 1, msg->buf, msg->len);
		if (ret < 0) {
			return ret;
		}

	} else {
		ret = sc18im704_transfer(dev, msg->buf, msg->len, NULL, 0);
		if (ret < 0) {
			return ret;
		}

		if (msg->flags & I2C_MSG_STOP) {
			ret = sc18im704_transfer(dev, &stop, 1, NULL, 0);
			if (ret < 0) {
				return ret;
			}
		}
	}

	return 0;
}

static int i2c_sc18im_transfer(const struct device *dev,
			       struct i2c_msg *msgs,
			       uint8_t num_msgs, uint16_t addr)
{
	int ret;

	if (num_msgs == 0) {
		return 0;
	}

	ret = sc18im704_claim(dev);
	if (ret < 0) {
		LOG_ERR("Failed to claim I2C bridge (%d)", ret);
		return ret;
	}

	for (uint8_t i = 0; i < num_msgs && ret == 0; ++i) {
		ret = i2c_sc18im_transfer_msg(dev, &msgs[i], addr);
	}

#ifdef CONFIG_I2C_SC18IM704_VERIFY
	if (ret == 0) {
		uint8_t buf[] = {
			SC18IM704_CMD_READ_REG,
			SC18IM704_REG_I2C_STAT,
			SC18IM704_CMD_STOP,
		};
		uint8_t data;

		ret = sc18im704_transfer(dev, buf, sizeof(buf), &data, 1);

		if (ret == 0 && data != SC18IM704_I2C_STAT_OK) {
			ret = -EIO;
		}
	}
#endif /* CONFIG_I2C_SC18IM704_VERIFY */

	sc18im704_release(dev);

	return ret;
}

static int i2c_sc18im_init(const struct device *dev)
{
	const struct i2c_sc18im_config *cfg = dev->config;
	struct i2c_sc18im_data *data = dev->data;
	int ret;

	/* The device baudrate after reset is 9600 */
	struct uart_config uart_cfg = {
		.baudrate = 9600,
		.parity = UART_CFG_PARITY_NONE,
		.stop_bits = UART_CFG_STOP_BITS_1,
		.data_bits = UART_CFG_DATA_BITS_8,
		.flow_ctrl = UART_CFG_FLOW_CTRL_NONE,
	};

	k_mutex_init(&data->lock);

	if (!device_is_ready(cfg->bus)) {
		LOG_ERR("UART bus not ready");
		return -ENODEV;
	}

	ret = uart_configure(cfg->bus, &uart_cfg);
	if (ret < 0) {
		LOG_ERR("Failed to configure UART (%d)", ret);
		return ret;
	}

	if (cfg->reset_gpios.port) {
		uint8_t buf[2];

		if (!device_is_ready(cfg->reset_gpios.port)) {
			LOG_ERR("Reset GPIO device not ready");
			return -ENODEV;
		}

		ret = gpio_pin_configure_dt(&cfg->reset_gpios, GPIO_OUTPUT_ACTIVE);
		if (ret < 0) {
			LOG_ERR("Failed to configure reset GPIO (%d)", ret);
			return ret;
		}

		ret = gpio_pin_set_dt(&cfg->reset_gpios, 0);
		if (ret < 0) {
			LOG_ERR("Failed to set reset GPIO (%d)", ret);
			return ret;
		}

		/* The device sends "OK" */
		ret = sc18im704_transfer(dev, NULL, 0, buf, sizeof(buf));
		if (ret < 0) {
			LOG_ERR("Failed to get OK (%d)", ret);
			return ret;
		}
	}

	if (cfg->bus_speed != 9600) {
		uint16_t brg = (7372800 / cfg->bus_speed) - 16;
		uint8_t buf[] = {
			SC18IM704_CMD_WRITE_REG,
			SC18IM704_REG_BRG0,
			brg & 0xff,
			SC18IM704_REG_BRG1,
			brg >> 8,
			SC18IM704_CMD_STOP,
		};

		ret = sc18im704_transfer(dev, buf, sizeof(buf), NULL, 0);
		if (ret < 0) {
			LOG_ERR("Failed to set baudrate (%d)", ret);
			return ret;
		}

		/* Make sure UART buffer is sent */
		k_msleep(1);

		/* Re-configure the UART controller with the new baudrate */
		uart_cfg.baudrate = cfg->bus_speed;
		ret = uart_configure(cfg->bus, &uart_cfg);
		if (ret < 0) {
			LOG_ERR("Failed to re-configure UART (%d)", ret);
			return ret;
		}
	}

	return 0;
}

static const struct i2c_driver_api i2c_sc18im_driver_api = {
	.configure = i2c_sc18im_configure,
	.get_config = i2c_sc18im_get_config,
	.transfer = i2c_sc18im_transfer,
};

#define I2C_SC18IM_DEFINE(n)									\
												\
	static const struct i2c_sc18im_config i2c_sc18im_config_##n = {				\
		.bus = DEVICE_DT_GET(DT_BUS(DT_INST_PARENT(n))),				\
		.bus_speed = DT_PROP_OR(DT_INST_PARENT(n), target_speed, 9600),			\
		.reset_gpios = GPIO_DT_SPEC_GET_OR(DT_INST_PARENT(n), reset_gpios, {0}),	\
	};											\
	static struct i2c_sc18im_data i2c_sc18im_data_##n = {					\
		.i2c_config = I2C_MODE_CONTROLLER | (I2C_SPEED_STANDARD << I2C_SPEED_SHIFT),	\
	};											\
												\
	DEVICE_DT_INST_DEFINE(n, i2c_sc18im_init, NULL,						\
			      &i2c_sc18im_data_##n, &i2c_sc18im_config_##n,			\
			      POST_KERNEL, CONFIG_I2C_SC18IM704_INIT_PRIORITY,			\
			      &i2c_sc18im_driver_api);

DT_INST_FOREACH_STATUS_OKAY(I2C_SC18IM_DEFINE)
