/*
 * Copyright (c) 2015 Google, Inc
 * Written by Simon Glass <sjg@chromium.org>
 *
 * SMBus block read/write support added by Stefan Roese:
 * Copyright (C) 2016 Stefan Roese <sr@denx.de>
 *
 * SPDX-License-Identifier:     GPL-2.0+
 */

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

/* PCI Configuration Space (D31:F3): SMBus */
#define SMB_BASE		0x20
#define HOSTC			0x40
#define  HST_EN			(1 << 0)
#define SMB_RCV_SLVA		0x09

/* SMBus I/O bits. */
#define SMBHSTSTAT		0x0
#define SMBHSTCTL		0x2
#define SMBHSTCMD		0x3
#define SMBXMITADD		0x4
#define SMBHSTDAT0		0x5
#define SMBHSTDAT1		0x6
#define SMBBLKDAT		0x7
#define SMBTRNSADD		0x9
#define SMBSLVDATA		0xa
#define SMBAUXCTL		0xd
#define SMLINK_PIN_CTL		0xe
#define SMBUS_PIN_CTL		0xf

/* I801 Hosts Status register bits */
#define SMBHSTSTS_BYTE_DONE	0x80
#define SMBHSTSTS_INUSE_STS	0x40
#define SMBHSTSTS_SMBALERT_STS	0x20
#define SMBHSTSTS_FAILED	0x10
#define SMBHSTSTS_BUS_ERR	0x08
#define SMBHSTSTS_DEV_ERR	0x04
#define SMBHSTSTS_INTR		0x02
#define SMBHSTSTS_HOST_BUSY	0x01

/* I801 Host Control register bits */
#define SMBHSTCNT_INTREN	0x01
#define SMBHSTCNT_KILL		0x02
#define SMBHSTCNT_LAST_BYTE	0x20
#define SMBHSTCNT_START		0x40
#define SMBHSTCNT_PEC_EN	0x80	/* ICH3 and later */

/* Auxiliary control register bits, ICH4+ only */
#define SMBAUXCTL_CRC		1
#define SMBAUXCTL_E32B		2

#define SMBUS_TIMEOUT	100	/* 100 ms */

struct intel_i2c {
	u32 base;
	int running;
};

static int smbus_wait_until_ready(u32 base)
{
	unsigned long ts;
	u8 byte;

	ts = get_timer(0);
	do {
		byte = inb(base + SMBHSTSTAT);
		if (!(byte & 1))
			return 0;
	} while (get_timer(ts) < SMBUS_TIMEOUT);

	return -ETIMEDOUT;
}

static int smbus_wait_until_done(u32 base)
{
	unsigned long ts;
	u8 byte;

	ts = get_timer(0);
	do {
		byte = inb(base + SMBHSTSTAT);
		if (!((byte & 1) || (byte & ~((1 << 6) | (1 << 0))) == 0))
			return 0;
	} while (get_timer(ts) < SMBUS_TIMEOUT);

	return -ETIMEDOUT;
}

static int smbus_block_read(u32 base, u8 dev, u8 *buffer,
			    int offset, int len)
{
	u8 buf_temp[32];
	int count;
	int i;

	debug("%s (%d): dev=0x%x offs=0x%x len=0x%x\n",
	      __func__, __LINE__, dev, offset, len);
	if (smbus_wait_until_ready(base) < 0)
		return -ETIMEDOUT;

	/* Setup transaction */

	/* Reset the data buffer index */
	inb(base + SMBHSTCTL);

	/* Set the device I'm talking too */
	outb(((dev & 0x7f) << 1) | 1, base + SMBXMITADD);
	/* Set the command/address... */
	outb(offset & 0xff, base + SMBHSTCMD);
	/* Set up for a block read */
	outb((inb(base + SMBHSTCTL) & (~(0x7) << 2)) | (0x5 << 2),
	     (base + SMBHSTCTL));
	/* Clear any lingering errors, so the transaction will run */
	outb(inb(base + SMBHSTSTAT), base + SMBHSTSTAT);

	/* Start the command */
	outb((inb(base + SMBHSTCTL) | SMBHSTCNT_START), base + SMBHSTCTL);

	/* Poll for transaction completion */
	if (smbus_wait_until_done(base) < 0) {
		printf("SMBUS read transaction timeout (dev=0x%x)\n", dev);
		return -ETIMEDOUT;
	}

	count = inb(base + SMBHSTDAT0);
	debug("%s (%d): count=%d (len=%d)\n", __func__, __LINE__, count, len);
	if (count == 0) {
		debug("ERROR: len=0 on read\n");
		return -EIO;
	}

	if (count < len) {
		debug("ERROR: too few bytes read\n");
		return -EIO;
	}

	if (count > 32) {
		debug("ERROR: count=%d too high\n", count);
		return -EIO;
	}

	/* Read all available bytes from buffer */
	for (i = 0; i < count; i++)
		buf_temp[i] = inb(base + SMBBLKDAT);

	memcpy(buffer, buf_temp, len);

	/* Return results of transaction */
	if (!(inb(base + SMBHSTSTAT) & SMBHSTSTS_INTR))
		return -EIO;

	return 0;
}

static int smbus_block_write(u32 base, u8 dev, u8 *buffer,
			     int offset, int len)
{
	int i;

	debug("%s (%d): dev=0x%x offs=0x%x len=0x%x\n",
	      __func__, __LINE__, dev, offset, len);
	if (smbus_wait_until_ready(base) < 0)
		return -ETIMEDOUT;

	/* Setup transaction */
	/* Set the device I'm talking too */
	outb(((dev & 0x7f) << 1) & ~0x01, base + SMBXMITADD);
	/* Set the command/address... */
	outb(offset, base + SMBHSTCMD);
	/* Set up for a block write */
	outb((inb(base + SMBHSTCTL) & (~(0x7) << 2)) | (0x5 << 2),
	     (base + SMBHSTCTL));
	/* Clear any lingering errors, so the transaction will run */
	outb(inb(base + SMBHSTSTAT), base + SMBHSTSTAT);

	/* Write count in DAT0 register */
	outb(len, base + SMBHSTDAT0);

	/* Write data bytes... */
	for (i = 0; i < len; i++)
		outb(*buffer++, base + SMBBLKDAT);

	/* Start the command */
	outb((inb(base + SMBHSTCTL) | SMBHSTCNT_START), base + SMBHSTCTL);

	/* Poll for transaction completion */
	if (smbus_wait_until_done(base) < 0) {
		printf("SMBUS write transaction timeout (dev=0x%x)\n", dev);
		return -ETIMEDOUT;
	}

	/* Return results of transaction */
	if (!(inb(base + SMBHSTSTAT) & SMBHSTSTS_INTR))
		return -EIO;

	return 0;
}

static int intel_i2c_xfer(struct udevice *bus, struct i2c_msg *msg, int nmsgs)
{
	struct intel_i2c *i2c = dev_get_priv(bus);
	struct i2c_msg *dmsg, *omsg, dummy;

	debug("i2c_xfer: %d messages\n", nmsgs);

	memset(&dummy, 0, sizeof(struct i2c_msg));

	/*
	 * We expect either two messages (one with an offset and one with the
	 * actucal data) or one message (just data)
	 */
	if (nmsgs > 2 || nmsgs == 0) {
		debug("%s: Only one or two messages are supported", __func__);
		return -EIO;
	}

	omsg = nmsgs == 1 ? &dummy : msg;
	dmsg = nmsgs == 1 ? msg : msg + 1;

	if (dmsg->flags & I2C_M_RD)
		return smbus_block_read(i2c->base, dmsg->addr, &dmsg->buf[0],
					omsg->buf[0], dmsg->len);
	else
		return smbus_block_write(i2c->base, dmsg->addr, &dmsg->buf[1],
					 dmsg->buf[0], dmsg->len - 1);
}

static int intel_i2c_probe_chip(struct udevice *bus, uint chip_addr,
				uint chip_flags)
{
	struct intel_i2c *i2c = dev_get_priv(bus);
	u8 buf[4];

	return smbus_block_read(i2c->base, chip_addr, buf, 0, 1);
}

static int intel_i2c_set_bus_speed(struct udevice *bus, unsigned int speed)
{
	return 0;
}

static int intel_i2c_probe(struct udevice *dev)
{
	struct intel_i2c *priv = dev_get_priv(dev);
	ulong base;

	/* Save base address from PCI BAR */
	priv->base = (ulong)dm_pci_map_bar(dev, PCI_BASE_ADDRESS_4,
					   PCI_REGION_IO);
	base = priv->base;

	/* Set SMBus enable. */
	dm_pci_write_config8(dev, HOSTC, HST_EN);

	/* Disable interrupts */
	outb(inb(base + SMBHSTCTL) & ~SMBHSTCNT_INTREN, base + SMBHSTCTL);

	/* Set 32-byte data buffer mode */
	outb(inb(base + SMBAUXCTL) | SMBAUXCTL_E32B, base + SMBAUXCTL);

	return 0;
}

static int intel_i2c_bind(struct udevice *dev)
{
	static int num_cards __attribute__ ((section(".data")));
	char name[20];

	/* Create a unique device name for PCI type devices */
	if (device_is_on_pci_bus(dev)) {
		/*
		 * ToDo:
		 * Setting req_seq in the driver is probably not recommended.
		 * But without a DT alias the number is not configured. And
		 * using this driver is impossible for PCIe I2C devices.
		 * This can be removed, once a better (correct) way for this
		 * is found and implemented.
		 */
		dev->req_seq = num_cards;
		sprintf(name, "intel_i2c#%u", num_cards++);
		device_set_name(dev, name);
	}

	return 0;
}

static const struct dm_i2c_ops intel_i2c_ops = {
	.xfer		= intel_i2c_xfer,
	.probe_chip	= intel_i2c_probe_chip,
	.set_bus_speed	= intel_i2c_set_bus_speed,
};

static const struct udevice_id intel_i2c_ids[] = {
	{ .compatible = "intel,ich-i2c" },
	{ }
};

U_BOOT_DRIVER(intel_i2c) = {
	.name	= "i2c_intel",
	.id	= UCLASS_I2C,
	.of_match = intel_i2c_ids,
	.ops	= &intel_i2c_ops,
	.priv_auto_alloc_size = sizeof(struct intel_i2c),
	.bind	= intel_i2c_bind,
	.probe	= intel_i2c_probe,
};

static struct pci_device_id intel_smbus_pci_supported[] = {
	/* Intel BayTrail SMBus on the PCI bus */
	{ PCI_VDEVICE(INTEL, 0x0f12) },
	/* Intel IvyBridge (Panther Point PCH) SMBus on the PCI bus */
	{ PCI_VDEVICE(INTEL, 0x1e22) },
	{},
};

U_BOOT_PCI_DEVICE(intel_i2c, intel_smbus_pci_supported);
