/*
 * Copyright (c) 2017 Linaro Ltd.
 *
 * SPDX-License-Identifier: Apache-2.0
 */

/**
 * @file
 * @brief Software driven 'bit-banging' library for I2C
 *
 * This code implements the I2C single master protocol in software by directly
 * manipulating the levels of the SCL and SDA lines of an I2C bus. It supports
 * the Standard-mode and Fast-mode speeds and doesn't support optional
 * protocol feature like 10-bit addresses or clock stretching.
 *
 * Timings and protocol are based Rev. 6 of the I2C specification:
 * http://www.nxp.com/documents/user_manual/UM10204.pdf
 */

#include <errno.h>
#include <i2c.h>
#include <i2c_bitbang.h>
#include <kernel.h>

/*
 * Indexes into delay table for each part of I2C timing waveform we are
 * interested in. In practice, for Standard and Fast modes, there are only two
 * different numerical values (T_LOW and T_HIGH) so we alias the others to
 * these. (Actually, we're simplifying a little, T_SU_STA could be T_HIGH on
 * Fast mode)
 */
#define T_LOW		0
#define T_HIGH		1
#define T_SU_STA	T_LOW
#define T_HD_STA	T_HIGH
#define T_SU_STP	T_HIGH
#define T_BUF		T_LOW

#define NS_TO_SYS_CLOCK_HW_CYCLES(ns) \
	((u64_t)CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC * (ns) / NSEC_PER_SEC + 1)

static const u32_t delays_fast[] = {
	[T_LOW] = NS_TO_SYS_CLOCK_HW_CYCLES(1300),
	[T_HIGH] = NS_TO_SYS_CLOCK_HW_CYCLES(600),
};

static const u32_t delays_standard[] = {
	[T_LOW] = NS_TO_SYS_CLOCK_HW_CYCLES(4700),
	[T_HIGH] = NS_TO_SYS_CLOCK_HW_CYCLES(4000),
};

int i2c_bitbang_configure(struct i2c_bitbang *context, u32_t dev_config)
{
	union dev_config config = { .raw = dev_config };

	/* Check for features we don't support */
	if (config.bits.is_slave_read) {
		return -ENOTSUP;
	}
	if (config.bits.use_10_bit_addr) {
		return -ENOTSUP;
	}

	/* Setup speed to use */
	switch (config.bits.speed) {
	case I2C_SPEED_STANDARD:
		context->delays = delays_standard;
		break;
	case I2C_SPEED_FAST:
		context->delays = delays_fast;
		break;
	default:
		return -ENOTSUP;
	}

	return 0;
}

static void i2c_set_scl(struct i2c_bitbang *context, int state)
{
	context->io->set_scl(context->io_context, state);
}

static void i2c_set_sda(struct i2c_bitbang *context, int state)
{
	context->io->set_sda(context->io_context, state);
}

static int i2c_get_sda(struct i2c_bitbang *context)
{
	return context->io->get_sda(context->io_context);
}

static void i2c_delay(unsigned int cycles_to_wait)
{
	u32_t start = k_cycle_get_32();

	/* Wait until the given number of cycles have passed */
	while (k_cycle_get_32() - start < cycles_to_wait) {
	}
}

static void i2c_start(struct i2c_bitbang *context)
{
	if (!i2c_get_sda(context)) {
		/*
		 * SDA is already low, so we need to do something to make it
		 * high. Try pulsing clock low to get slave to release SDA.
		 */
		i2c_set_scl(context, 0);
		i2c_delay(context->delays[T_LOW]);
		i2c_set_scl(context, 1);
		i2c_delay(context->delays[T_SU_STA]);
	}
	i2c_set_sda(context, 0);
	i2c_delay(context->delays[T_HD_STA]);
}

static void i2c_repeated_start(struct i2c_bitbang *context)
{
	i2c_delay(context->delays[T_SU_STA]);
	i2c_start(context);
}

static void i2c_stop(struct i2c_bitbang *context)
{
	if (i2c_get_sda(context)) {
		/*
		 * SDA is already high, so we need to make it low so that
		 * we can create a rising edge. This means we're effectively
		 * doing a START.
		 */
		i2c_delay(context->delays[T_SU_STA]);
		i2c_set_sda(context, 0);
		i2c_delay(context->delays[T_HD_STA]);
	}
	i2c_delay(context->delays[T_SU_STP]);
	i2c_set_sda(context, 1);
	i2c_delay(context->delays[T_BUF]); /* In case we start again too soon */
}

static void i2c_write_bit(struct i2c_bitbang *context, int bit)
{
	i2c_set_scl(context, 0);
	/* SDA hold time is zero, so no need for a delay here */
	i2c_set_sda(context, bit);
	i2c_delay(context->delays[T_LOW]);
	i2c_set_scl(context, 1);
	i2c_delay(context->delays[T_HIGH]);
}

static bool i2c_read_bit(struct i2c_bitbang *context)
{
	bool bit;

	i2c_set_scl(context, 0);
	/* SDA hold time is zero, so no need for a delay here */
	i2c_set_sda(context, 1); /* Stop driving low, so slave has control */
	i2c_delay(context->delays[T_LOW]);
	bit = i2c_get_sda(context);
	i2c_set_scl(context, 1);
	i2c_delay(context->delays[T_HIGH]);
	return bit;
}

static bool i2c_write_byte(struct i2c_bitbang *context, u8_t byte)
{
	u8_t mask = 1 << 7;

	do {
		i2c_write_bit(context, byte & mask);
	} while (mask >>= 1);

	/* Return inverted ACK bit, i.e. 'true' for ACK, 'false' for NACK */
	return !i2c_read_bit(context);
}

static u8_t i2c_read_byte(struct i2c_bitbang *context)
{
	unsigned int byte = 1;

	do {
		byte <<= 1;
		byte |= i2c_read_bit(context);
	} while (!(byte & (1 << 8)));

	return byte;
}

int i2c_bitbang_transfer(struct i2c_bitbang *context,
			   struct i2c_msg *msgs, u8_t num_msgs,
			   u16_t slave_address)
{
	u8_t *buf, *buf_end;
	unsigned int flags;
	int result = -EIO;

	if (!num_msgs) {
		return 0;
	}

	/* We want an initial Start condition */
	flags = I2C_MSG_RESTART;

	/* Make sure we're in a good state so slave recognises the Start */
	i2c_set_scl(context, 1);
	flags |= I2C_MSG_STOP;

	do {
		/* Stop flag from previous message? */
		if (flags & I2C_MSG_STOP) {
			i2c_stop(context);
		}

		/* Forget old flags except start flag */
		flags &= I2C_MSG_RESTART;

		/* Start condition? */
		if (flags & I2C_MSG_RESTART) {
			i2c_start(context);
		} else if (msgs->flags & I2C_MSG_RESTART) {
			i2c_repeated_start(context);
		}

		/* Get flags for new message */
		flags |= msgs->flags;

		/* Send address after any Start condition */
		if (flags & I2C_MSG_RESTART) {
			unsigned int byte0 = slave_address << 1;

			byte0 |= (flags & I2C_MSG_RW_MASK) == I2C_MSG_READ;
			if (!i2c_write_byte(context, byte0)) {
				goto finish; /* No ACK received */
			}
			flags &= ~I2C_MSG_RESTART;
		}

		/* Transfer data */
		buf = msgs->buf;
		buf_end = buf + msgs->len;
		if ((flags & I2C_MSG_RW_MASK) == I2C_MSG_READ) {
			/* Read */
			while (buf < buf_end) {
				*buf++ = i2c_read_byte(context);
				/* ACK the byte, except for the last one */
				i2c_write_bit(context, buf == buf_end);
			}
		} else {
			/* Write */
			while (buf < buf_end) {
				if (!i2c_write_byte(context, *buf++)) {
					goto finish; /* No ACK received */
				}
			}
		}

		/* Next message */
		msgs++;
		num_msgs--;
	} while (num_msgs);

	/* Complete without error */
	result = 0;
finish:
	i2c_stop(context);

	return result;
}

void i2c_bitbang_init(struct i2c_bitbang *context,
			const struct i2c_bitbang_io *io, void *io_context)
{
	union dev_config dev_config = { .bits.speed = I2C_SPEED_STANDARD };

	context->io = io;
	context->io_context = io_context;
	i2c_bitbang_configure(context, dev_config.raw);
}
