/*
 * Copyright (c) 2018 Intel Corporation
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#define DT_DRV_COMPAT altr_nios2_i2c

#include <errno.h>
#include <drivers/i2c.h>
#include <soc.h>
#include <sys/util.h>
#include <altera_common.h>
#include "altera_avalon_i2c.h"

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

#define NIOS2_I2C_TIMEOUT_USEC		1000

struct i2c_nios2_config {
	ALT_AVALON_I2C_DEV_t	i2c_dev;
	IRQ_DATA_t		irq_data;
	struct k_sem		sem_lock;
};

static int i2c_nios2_configure(const struct device *dev, uint32_t dev_config)
{
	struct i2c_nios2_config *config = (struct i2c_nios2_config *)dev->config;
	int32_t rc = 0;

	k_sem_take(&config->sem_lock, K_FOREVER);
	if (!(I2C_MODE_MASTER & dev_config)) {
		LOG_ERR("i2c config mode error\n");
		rc = -EINVAL;
		goto i2c_cfg_err;
	}

	if (I2C_ADDR_10_BITS & dev_config) {
		LOG_ERR("i2c config addressing error\n");
		rc = -EINVAL;
		goto i2c_cfg_err;
	}

	if (I2C_SPEED_GET(dev_config) != I2C_SPEED_STANDARD) {
		LOG_ERR("i2c config speed error\n");
		rc = -EINVAL;
		goto i2c_cfg_err;
	}

	alt_avalon_i2c_init(&config->i2c_dev);

i2c_cfg_err:
	k_sem_give(&config->sem_lock);
	return rc;
}

static int i2c_nios2_transfer(const struct device *dev, struct i2c_msg *msgs,
			      uint8_t num_msgs, uint16_t addr)
{
	struct i2c_nios2_config *config = (struct i2c_nios2_config *)dev->config;
	ALT_AVALON_I2C_STATUS_CODE status;
	uint32_t restart, stop;
	int32_t i, timeout, rc = 0;

	k_sem_take(&config->sem_lock, K_FOREVER);
	/* register the optional interrupt callback */
	alt_avalon_i2c_register_optional_irq_handler(
			&config->i2c_dev, &config->irq_data);

	/* Iterate over all the messages */
	for (i = 0; i < num_msgs; i++) {

		/* convert restart flag */
		if (msgs->flags & I2C_MSG_RESTART) {
			restart = ALT_AVALON_I2C_RESTART;
		} else {
			restart = ALT_AVALON_I2C_NO_RESTART;
		}

		/* convert stop flag */
		if (msgs->flags & I2C_MSG_STOP) {
			stop = ALT_AVALON_I2C_STOP;
		} else {
			stop = ALT_AVALON_I2C_NO_STOP;
		}

		/* Set the slave device address */
		alt_avalon_i2c_master_target_set(&config->i2c_dev, addr);

		/* Start the transfer */
		if (msgs->flags & I2C_MSG_READ) {
			status = alt_avalon_i2c_master_receive_using_interrupts(
							&config->i2c_dev,
							msgs->buf, msgs->len,
							restart, stop);
		} else {
			status = alt_avalon_i2c_master_transmit_using_interrupts
							(&config->i2c_dev,
							msgs->buf, msgs->len,
							restart, stop);
		}

		/* Return an error if the transfer didn't
		 * start successfully e.g., if the bus was busy
		 */
		if (status != ALT_AVALON_I2C_SUCCESS) {
			LOG_ERR("i2c transfer error %lu\n", status);
			rc = -EIO;
			goto i2c_transfer_err;
		}

		timeout = NIOS2_I2C_TIMEOUT_USEC;
		while (timeout) {
			k_busy_wait(1);
			status = alt_avalon_i2c_interrupt_transaction_status(
							&config->i2c_dev);
			if (status == ALT_AVALON_I2C_SUCCESS) {
				break;
			}
			timeout--;
		}

		if (timeout <= 0) {
			LOG_ERR("i2c busy or timeout error %lu\n", status);
			rc = -EIO;
			goto i2c_transfer_err;
		}

		/* move to the next message */
		msgs++;
	}

i2c_transfer_err:
	alt_avalon_i2c_disable(&config->i2c_dev);
	k_sem_give(&config->sem_lock);
	return rc;
}

static void i2c_nios2_isr(const struct device *dev)
{
	struct i2c_nios2_config *config = (struct i2c_nios2_config *)dev->config;

	/* Call Altera HAL driver ISR */
	alt_handle_irq(&config->i2c_dev, DT_INST_IRQN(0));
}

static int i2c_nios2_init(const struct device *dev);

static struct i2c_driver_api i2c_nios2_driver_api = {
	.configure = i2c_nios2_configure,
	.transfer = i2c_nios2_transfer,
};

static struct i2c_nios2_config i2c_nios2_cfg = {
	.i2c_dev = {
		.i2c_base = (alt_u32 *)DT_INST_REG_ADDR(0),
		.irq_controller_ID = I2C_0_IRQ_INTERRUPT_CONTROLLER_ID,
		.irq_ID = DT_INST_IRQN(0),
		.ip_freq_in_hz = DT_INST_PROP(0, clock_frequency),
	},
};

I2C_DEVICE_DT_INST_DEFINE(0, i2c_nios2_init, NULL,
		    NULL, &i2c_nios2_cfg,
		    POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE,
		    &i2c_nios2_driver_api);

static int i2c_nios2_init(const struct device *dev)
{
	struct i2c_nios2_config *config = (struct i2c_nios2_config *)dev->config;
	int rc;

	/* initialize semaphore */
	k_sem_init(&config->sem_lock, 1, 1);

	rc = i2c_nios2_configure(dev,
			I2C_MODE_MASTER |
			I2C_SPEED_SET(I2C_SPEED_STANDARD));
	if (rc) {
		LOG_ERR("i2c configure failed %d\n", rc);
		return rc;
	}

	/* clear ISR register content */
	alt_avalon_i2c_int_clear(&config->i2c_dev,
			ALT_AVALON_I2C_ISR_ALL_CLEARABLE_INTS_MSK);
	IRQ_CONNECT(DT_INST_IRQN(0), DT_INST_IRQ(0, priority),
			i2c_nios2_isr, DEVICE_DT_INST_GET(0), 0);
	irq_enable(DT_INST_IRQN(0));
	return 0;
}
