/*
 * Faraday I2C Controller
 *
 * (C) Copyright 2010 Faraday Technology
 * Dante Su <dantesu@faraday-tech.com>
 *
 * SPDX-License-Identifier:	GPL-2.0+
 */

#include <common.h>
#include <asm/io.h>
#include <i2c.h>

#include "fti2c010.h"

#ifndef CONFIG_SYS_I2C_SPEED
#define CONFIG_SYS_I2C_SPEED    5000
#endif

#ifndef CONFIG_SYS_I2C_SLAVE
#define CONFIG_SYS_I2C_SLAVE    0
#endif

#ifndef CONFIG_FTI2C010_CLOCK
#define CONFIG_FTI2C010_CLOCK   clk_get_rate("I2C")
#endif

#ifndef CONFIG_FTI2C010_TIMEOUT
#define CONFIG_FTI2C010_TIMEOUT 10 /* ms */
#endif

/* 7-bit dev address + 1-bit read/write */
#define I2C_RD(dev)             ((((dev) << 1) & 0xfe) | 1)
#define I2C_WR(dev)             (((dev) << 1) & 0xfe)

struct fti2c010_chip {
	struct fti2c010_regs *regs;
};

static struct fti2c010_chip chip_list[] = {
	{
		.regs = (struct fti2c010_regs *)CONFIG_FTI2C010_BASE,
	},
#ifdef CONFIG_FTI2C010_BASE1
	{
		.regs = (struct fti2c010_regs *)CONFIG_FTI2C010_BASE1,
	},
#endif
#ifdef CONFIG_FTI2C010_BASE2
	{
		.regs = (struct fti2c010_regs *)CONFIG_FTI2C010_BASE2,
	},
#endif
#ifdef CONFIG_FTI2C010_BASE3
	{
		.regs = (struct fti2c010_regs *)CONFIG_FTI2C010_BASE3,
	},
#endif
};

static int fti2c010_reset(struct fti2c010_chip *chip)
{
	ulong ts;
	int ret = -1;
	struct fti2c010_regs *regs = chip->regs;

	writel(CR_I2CRST, &regs->cr);
	for (ts = get_timer(0); get_timer(ts) < CONFIG_FTI2C010_TIMEOUT; ) {
		if (!(readl(&regs->cr) & CR_I2CRST)) {
			ret = 0;
			break;
		}
	}

	if (ret)
		printf("fti2c010: reset timeout\n");

	return ret;
}

static int fti2c010_wait(struct fti2c010_chip *chip, uint32_t mask)
{
	int ret = -1;
	uint32_t stat, ts;
	struct fti2c010_regs *regs = chip->regs;

	for (ts = get_timer(0); get_timer(ts) < CONFIG_FTI2C010_TIMEOUT; ) {
		stat = readl(&regs->sr);
		if ((stat & mask) == mask) {
			ret = 0;
			break;
		}
	}

	return ret;
}

static unsigned int set_i2c_bus_speed(struct fti2c010_chip *chip,
	unsigned int speed)
{
	struct fti2c010_regs *regs = chip->regs;
	unsigned int clk = CONFIG_FTI2C010_CLOCK;
	unsigned int gsr = 0;
	unsigned int tsr = 32;
	unsigned int div, rate;

	for (div = 0; div < 0x3ffff; ++div) {
		/* SCLout = PCLK/(2*(COUNT + 2) + GSR) */
		rate = clk / (2 * (div + 2) + gsr);
		if (rate <= speed)
			break;
	}

	writel(TGSR_GSR(gsr) | TGSR_TSR(tsr), &regs->tgsr);
	writel(CDR_DIV(div), &regs->cdr);

	return rate;
}

/*
 * Initialization, must be called once on start up, may be called
 * repeatedly to change the speed and slave addresses.
 */
static void fti2c010_init(struct i2c_adapter *adap, int speed, int slaveaddr)
{
	struct fti2c010_chip *chip = chip_list + adap->hwadapnr;

	if (adap->init_done)
		return;

#ifdef CONFIG_SYS_I2C_INIT_BOARD
	/* Call board specific i2c bus reset routine before accessing the
	 * environment, which might be in a chip on that bus. For details
	 * about this problem see doc/I2C_Edge_Conditions.
	*/
	i2c_init_board();
#endif

	/* master init */

	fti2c010_reset(chip);

	set_i2c_bus_speed(chip, speed);

	/* slave init, don't care */

#ifdef CONFIG_SYS_I2C_BOARD_LATE_INIT
	/* Call board specific i2c bus reset routine AFTER the bus has been
	 * initialized. Use either this callpoint or i2c_init_board;
	 * which is called before fti2c010_init operations.
	 * For details about this problem see doc/I2C_Edge_Conditions.
	*/
	i2c_board_late_init();
#endif
}

/*
 * Probe the given I2C chip address.  Returns 0 if a chip responded,
 * not 0 on failure.
 */
static int fti2c010_probe(struct i2c_adapter *adap, u8 dev)
{
	struct fti2c010_chip *chip = chip_list + adap->hwadapnr;
	struct fti2c010_regs *regs = chip->regs;
	int ret;

	/* 1. Select slave device (7bits Address + 1bit R/W) */
	writel(I2C_WR(dev), &regs->dr);
	writel(CR_ENABLE | CR_TBEN | CR_START, &regs->cr);
	ret = fti2c010_wait(chip, SR_DT);
	if (ret)
		return ret;

	/* 2. Select device register */
	writel(0, &regs->dr);
	writel(CR_ENABLE | CR_TBEN, &regs->cr);
	ret = fti2c010_wait(chip, SR_DT);

	return ret;
}

static void to_i2c_addr(u8 *buf, uint32_t addr, int alen)
{
	int i, shift;

	if (!buf || alen <= 0)
		return;

	/* MSB first */
	i = 0;
	shift = (alen - 1) * 8;
	while (alen-- > 0) {
		buf[i] = (u8)(addr >> shift);
		shift -= 8;
	}
}

static int fti2c010_read(struct i2c_adapter *adap,
			u8 dev, uint addr, int alen, uchar *buf, int len)
{
	struct fti2c010_chip *chip = chip_list + adap->hwadapnr;
	struct fti2c010_regs *regs = chip->regs;
	int ret, pos;
	uchar paddr[4];

	to_i2c_addr(paddr, addr, alen);

	/*
	 * Phase A. Set register address
	 */

	/* A.1 Select slave device (7bits Address + 1bit R/W) */
	writel(I2C_WR(dev), &regs->dr);
	writel(CR_ENABLE | CR_TBEN | CR_START, &regs->cr);
	ret = fti2c010_wait(chip, SR_DT);
	if (ret)
		return ret;

	/* A.2 Select device register */
	for (pos = 0; pos < alen; ++pos) {
		uint32_t ctrl = CR_ENABLE | CR_TBEN;

		writel(paddr[pos], &regs->dr);
		writel(ctrl, &regs->cr);
		ret = fti2c010_wait(chip, SR_DT);
		if (ret)
			return ret;
	}

	/*
	 * Phase B. Get register data
	 */

	/* B.1 Select slave device (7bits Address + 1bit R/W) */
	writel(I2C_RD(dev), &regs->dr);
	writel(CR_ENABLE | CR_TBEN | CR_START, &regs->cr);
	ret = fti2c010_wait(chip, SR_DT);
	if (ret)
		return ret;

	/* B.2 Get register data */
	for (pos = 0; pos < len; ++pos) {
		uint32_t ctrl = CR_ENABLE | CR_TBEN;
		uint32_t stat = SR_DR;

		if (pos == len - 1) {
			ctrl |= CR_NAK | CR_STOP;
			stat |= SR_ACK;
		}
		writel(ctrl, &regs->cr);
		ret = fti2c010_wait(chip, stat);
		if (ret)
			break;
		buf[pos] = (uchar)(readl(&regs->dr) & 0xFF);
	}

	return ret;
}

static int fti2c010_write(struct i2c_adapter *adap,
			u8 dev, uint addr, int alen, u8 *buf, int len)
{
	struct fti2c010_chip *chip = chip_list + adap->hwadapnr;
	struct fti2c010_regs *regs = chip->regs;
	int ret, pos;
	uchar paddr[4];

	to_i2c_addr(paddr, addr, alen);

	/*
	 * Phase A. Set register address
	 *
	 * A.1 Select slave device (7bits Address + 1bit R/W)
	 */
	writel(I2C_WR(dev), &regs->dr);
	writel(CR_ENABLE | CR_TBEN | CR_START, &regs->cr);
	ret = fti2c010_wait(chip, SR_DT);
	if (ret)
		return ret;

	/* A.2 Select device register */
	for (pos = 0; pos < alen; ++pos) {
		uint32_t ctrl = CR_ENABLE | CR_TBEN;

		writel(paddr[pos], &regs->dr);
		writel(ctrl, &regs->cr);
		ret = fti2c010_wait(chip, SR_DT);
		if (ret)
			return ret;
	}

	/*
	 * Phase B. Set register data
	 */
	for (pos = 0; pos < len; ++pos) {
		uint32_t ctrl = CR_ENABLE | CR_TBEN;

		if (pos == len - 1)
			ctrl |= CR_STOP;
		writel(buf[pos], &regs->dr);
		writel(ctrl, &regs->cr);
		ret = fti2c010_wait(chip, SR_DT);
		if (ret)
			break;
	}

	return ret;
}

static unsigned int fti2c010_set_bus_speed(struct i2c_adapter *adap,
			unsigned int speed)
{
	struct fti2c010_chip *chip = chip_list + adap->hwadapnr;
	int ret;

	fti2c010_reset(chip);
	ret = set_i2c_bus_speed(chip, speed);

	return ret;
}

/*
 * Register i2c adapters
 */
U_BOOT_I2C_ADAP_COMPLETE(i2c_0, fti2c010_init, fti2c010_probe, fti2c010_read,
			fti2c010_write, fti2c010_set_bus_speed,
			CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE,
			0)
#ifdef CONFIG_FTI2C010_BASE1
U_BOOT_I2C_ADAP_COMPLETE(i2c_1, fti2c010_init, fti2c010_probe, fti2c010_read,
			fti2c010_write, fti2c010_set_bus_speed,
			CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE,
			1)
#endif
#ifdef CONFIG_FTI2C010_BASE2
U_BOOT_I2C_ADAP_COMPLETE(i2c_2, fti2c010_init, fti2c010_probe, fti2c010_read,
			fti2c010_write, fti2c010_set_bus_speed,
			CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE,
			2)
#endif
#ifdef CONFIG_FTI2C010_BASE3
U_BOOT_I2C_ADAP_COMPLETE(i2c_3, fti2c010_init, fti2c010_probe, fti2c010_read,
			fti2c010_write, fti2c010_set_bus_speed,
			CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE,
			3)
#endif
