/*
 * 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 <i2c.h>
#include <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 = 0;

	/* 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 = 0;

	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 = 0;

	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 = 0;
	u16_t prescale = 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;
	}

	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 = 100000; /* 100 KHz */
		break;
	case I2C_SPEED_FAST:
		i2c_speed = 400000; /* 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 / (5 * i2c_speed)) - 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 = 0;
	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_SIFIVE_I2C0_0_LABEL
I2C_SIFIVE_INIT(0);
#endif

