/*
 * Copyright (c) 2018 SiFive Inc.
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#define LOG_LEVEL CONFIG_I2C_LOG_LEVEL
#include <logging/log.h>
LOG_MODULE_REGISTER(i2c_sifive);

#include <device.h>
#include <drivers/i2c.h>
#include <sys/sys_io.h>

#include "i2c-priv.h"

/* Macros */

#define I2C_REG(config, reg)	((mem_addr_t) ((config)->base + reg))
#define IS_SET(config, reg, value) (sys_read8(I2C_REG(config, reg)) & (value))

/* Register Offsets */

#define REG_PRESCALE_LOW	0x00
#define REG_PRESCALE_HIGH	0x04

#define REG_CONTROL		0x08

/* Transmit on write, receive on read */
#define REG_TRANSMIT		0x0c
#define REG_RECEIVE		0x0c

/* Command on write, status on read */
#define REG_COMMAND		0x10
#define REG_STATUS		0x10

/* Values */

#define SF_CONTROL_EN	(1 << 7)
#define SF_CONTROL_IE	(1 << 6)

#define SF_TX_WRITE	(0 << 0)
#define SF_TX_READ	(1 << 0)

#define SF_CMD_START	(1 << 7)
#define SF_CMD_STOP	(1 << 6)
#define SF_CMD_READ	(1 << 5)
#define SF_CMD_WRITE	(1 << 4)
#define SF_CMD_ACK	(1 << 3)
#define SF_CMD_IACK	(1 << 0)

#define SF_STATUS_RXACK	(1 << 7)
#define SF_STATUS_BUSY	(1 << 6)
#define SF_STATUS_AL	(1 << 5)
#define SF_STATUS_TIP	(1 << 1)
#define SF_STATUS_IP	(1 << 0)

/* Structure declarations */

struct i2c_sifive_cfg {
	u32_t base;
	u32_t f_sys;
	u32_t f_bus;
};

/* Helper functions */

static inline bool i2c_sifive_busy(struct device *dev)
{
	const struct i2c_sifive_cfg *config = dev->config->config_info;

	return IS_SET(config, REG_STATUS, SF_STATUS_TIP);
}

static int i2c_sifive_send_addr(struct device *dev,
				u16_t addr,
				u16_t rw_flag)
{
	const struct i2c_sifive_cfg *config = dev->config->config_info;
	u8_t command = 0U;

	/* Wait for a previous transfer to complete */
	while (i2c_sifive_busy(dev)) {
	}

	/* Set transmit register to address with read/write flag */
	sys_write8((addr | rw_flag), I2C_REG(config, REG_TRANSMIT));

	/* Addresses are always written */
	command = SF_CMD_WRITE | SF_CMD_START;

	/* Write the command register to start the transfer */
	sys_write8(command, I2C_REG(config, REG_COMMAND));

	while (i2c_sifive_busy(dev)) {
	}

	if (IS_SET(config, REG_STATUS, SF_STATUS_RXACK)) {
		LOG_ERR("I2C Rx failed to acknowledge\n");
		return -EIO;
	}

	return 0;
}

static int i2c_sifive_write_msg(struct device *dev,
				struct i2c_msg *msg,
				u16_t addr)
{
	const struct i2c_sifive_cfg *config = dev->config->config_info;
	int rc = 0;
	u8_t command = 0U;

	rc = i2c_sifive_send_addr(dev, addr, SF_TX_WRITE);
	if (rc != 0) {
		LOG_ERR("I2C failed to write message\n");
		return rc;
	}

	for (u32_t i = 0; i < msg->len; i++) {
		/* Wait for a previous transfer */
		while (i2c_sifive_busy(dev)) {
		}

		/* Put data in transmit reg */
		sys_write8((msg->buf)[i], I2C_REG(config, REG_TRANSMIT));

		/* Generate command byte */
		command = SF_CMD_WRITE;

		/* On the last byte of the message */
		if (i == (msg->len - 1)) {
			/* If the stop bit is requested, set it */
			if (msg->flags & I2C_MSG_STOP) {
				command |= SF_CMD_STOP;
			}
		}

		/* Write command reg */
		sys_write8(command, I2C_REG(config, REG_COMMAND));

		/* Wait for a previous transfer */
		while (i2c_sifive_busy(dev)) {
		}

		if (IS_SET(config, REG_STATUS, SF_STATUS_RXACK)) {
			LOG_ERR("I2C Rx failed to acknowledge\n");
			return -EIO;
		}
	}

	return 0;
}

static int i2c_sifive_read_msg(struct device *dev,
			       struct i2c_msg *msg,
			       u16_t addr)
{
	const struct i2c_sifive_cfg *config = dev->config->config_info;
	u8_t command = 0U;

	i2c_sifive_send_addr(dev, addr, SF_TX_READ);

	while (i2c_sifive_busy(dev)) {
	}

	for (int i = 0; i < msg->len; i++) {
		/* Generate command byte */
		command = SF_CMD_READ;

		/* On the last byte of the message */
		if (i == (msg->len - 1)) {
			/* Set NACK to end read */
			command |= SF_CMD_ACK;

			/* If the stop bit is requested, set it */
			if (msg->flags & I2C_MSG_STOP) {
				command |= SF_CMD_STOP;
			}
		}

		/* Write command reg */
		sys_write8(command, I2C_REG(config, REG_COMMAND));

		/* Wait for the read to complete */
		while (i2c_sifive_busy(dev)) {
		}

		/* Store the received byte */
		(msg->buf)[i] = sys_read8(I2C_REG(config, REG_RECEIVE));
	}

	return 0;
}

/* API Functions */

static int i2c_sifive_configure(struct device *dev, u32_t dev_config)
{
	const struct i2c_sifive_cfg *config = NULL;
	u32_t i2c_speed = 0U;
	u16_t prescale = 0U;

	/* Check for NULL pointers */
	if (dev == NULL) {
		LOG_ERR("Device handle is NULL");
		return -EINVAL;
	}
	if (dev->config == NULL) {
		LOG_ERR("Device handle config is NULL");
		return -EINVAL;
	}

	config = dev->config->config_info;
	if (config == NULL) {
		LOG_ERR("Device config is NULL");
		return -EINVAL;
	}

	/* Disable the I2C peripheral */
	sys_write8(0, I2C_REG(config, REG_CONTROL));

	/* Configure bus frequency */
	switch (I2C_SPEED_GET(dev_config)) {
	case I2C_SPEED_STANDARD:
		i2c_speed = 100000U; /* 100 KHz */
		break;
	case I2C_SPEED_FAST:
		i2c_speed = 400000U; /* 400 KHz */
		break;
	case I2C_SPEED_FAST_PLUS:
	case I2C_SPEED_HIGH:
	case I2C_SPEED_ULTRA:
	default:
		LOG_ERR("Unsupported I2C speed requested");
		return -ENOTSUP;
	}

	/* Calculate prescale value */
	prescale = (config->f_sys / (i2c_speed * 5U)) - 1;

	/* Configure peripheral with calculated prescale */
	sys_write8((u8_t) (0xFF & prescale), I2C_REG(config, REG_PRESCALE_LOW));
	sys_write8((u8_t) (0xFF & (prescale >> 8)),
		   I2C_REG(config, REG_PRESCALE_HIGH));

	/* Support I2C Master mode only */
	if (!(dev_config & I2C_MODE_MASTER)) {
		LOG_ERR("I2C only supports operation as master");
		return -ENOTSUP;
	}

	/*
	 * Driver does not support 10-bit addressing. This can be added
	 * in the future when needed.
	 */
	if (dev_config & I2C_ADDR_10_BITS) {
		LOG_ERR("I2C driver does not support 10-bit addresses");
		return -ENOTSUP;
	}

	/* Enable the I2C peripheral */
	sys_write8(SF_CONTROL_EN, I2C_REG(config, REG_CONTROL));

	return 0;
}

static int i2c_sifive_transfer(struct device *dev,
			       struct i2c_msg *msgs,
			       u8_t num_msgs,
			       u16_t addr)
{
	int rc = 0;

	/* Check for NULL pointers */
	if (dev == NULL) {
		LOG_ERR("Device handle is NULL");
		return -EINVAL;
	}
	if (dev->config == NULL) {
		LOG_ERR("Device handle config is NULL");
		return -EINVAL;
	}
	if (dev->config->config_info == NULL) {
		LOG_ERR("Device config is NULL");
		return -EINVAL;
	}
	if (msgs == NULL) {
		return -EINVAL;
	}

	for (int i = 0; i < num_msgs; i++) {
		if (msgs[i].flags & I2C_MSG_READ) {
			rc = i2c_sifive_read_msg(dev, &(msgs[i]), addr);
		} else {
			rc = i2c_sifive_write_msg(dev, &(msgs[i]), addr);
		}

		if (rc != 0) {
			LOG_ERR("I2C failed to transfer messages\n");
			return rc;
		}
	}

	return 0;
};

static int i2c_sifive_init(struct device *dev)
{
	const struct i2c_sifive_cfg *config = dev->config->config_info;
	u32_t dev_config = 0U;
	int rc = 0;

	dev_config = (I2C_MODE_MASTER | i2c_map_dt_bitrate(config->f_bus));

	rc = i2c_sifive_configure(dev, dev_config);
	if (rc != 0) {
		LOG_ERR("Failed to configure I2C on init");
		return rc;
	}

	return 0;
}


static struct i2c_driver_api i2c_sifive_api = {
	.configure = i2c_sifive_configure,
	.transfer = i2c_sifive_transfer,
};

/* Device instantiation */

#define I2C_SIFIVE_INIT(n) \
	static struct i2c_sifive_cfg i2c_sifive_cfg_##n = { \
		.base = DT_SIFIVE_I2C0_##n##_BASE_ADDRESS, \
		.f_sys = DT_SIFIVE_I2C0_##n##_INPUT_FREQUENCY, \
		.f_bus = DT_SIFIVE_I2C0_##n##_CLOCK_FREQUENCY, \
	}; \
	DEVICE_AND_API_INIT(i2c_##n, \
			    DT_SIFIVE_I2C0_##n##_LABEL, \
			    i2c_sifive_init, \
			    NULL, \
			    &i2c_sifive_cfg_##n, \
			    POST_KERNEL, \
			    CONFIG_I2C_INIT_PRIORITY, \
			    &i2c_sifive_api)

#ifdef DT_INST_0_SIFIVE_I2C0_LABEL
I2C_SIFIVE_INIT(0);
#endif

