// SPDX-License-Identifier: GPL-2.0
/*
 * Author:
 * Miquel Raynal <miquel.raynal@bootlin.com>
 *
 * Description:
 * SPI-level driver for TCG/TIS TPM (trusted platform module).
 * Specifications at www.trustedcomputinggroup.org
 *
 * This device driver implements the TPM interface as defined in
 * the TCG SPI protocol stack version 2.0.
 *
 * It is based on the U-Boot driver tpm_tis_infineon_i2c.c.
 */

#include <common.h>
#include <dm.h>
#include <fdtdec.h>
#include <log.h>
#include <spi.h>
#include <tpm-v2.h>
#include <linux/bitops.h>
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/compiler.h>
#include <linux/types.h>
#include <linux/unaligned/be_byteshift.h>
#include <asm-generic/gpio.h>

#include "tpm_tis.h"
#include "tpm_internal.h"

#define TPM_ACCESS(l)			(0x0000 | ((l) << 12))
#define TPM_INT_ENABLE(l)               (0x0008 | ((l) << 12))
#define TPM_STS(l)			(0x0018 | ((l) << 12))
#define TPM_DATA_FIFO(l)		(0x0024 | ((l) << 12))
#define TPM_DID_VID(l)			(0x0F00 | ((l) << 12))
#define TPM_RID(l)			(0x0F04 | ((l) << 12))

#define MAX_SPI_FRAMESIZE 64

/* Number of wait states to wait for */
#define TPM_WAIT_STATES 100

/**
 * struct tpm_tis_chip_data - Non-discoverable TPM information
 *
 * @pcr_count:		Number of PCR per bank
 * @pcr_select_min:	Size in octets of the pcrSelect array
 */
struct tpm_tis_chip_data {
	unsigned int pcr_count;
	unsigned int pcr_select_min;
	unsigned int time_before_first_cmd_ms;
};

/**
 * tpm_tis_spi_read() - Read from TPM register
 *
 * @addr: register address to read from
 * @buffer: provided by caller
 * @len: number of bytes to read
 *
 * Read len bytes from TPM register and put them into
 * buffer (little-endian format, i.e. first byte is put into buffer[0]).
 *
 * NOTE: TPM is big-endian for multi-byte values. Multi-byte
 * values have to be swapped.
 *
 * @return -EIO on error, 0 on success.
 */
static int tpm_tis_spi_xfer(struct udevice *dev, u32 addr, const u8 *out,
			    u8 *in, u16 len)
{
	struct spi_slave *slave = dev_get_parent_priv(dev);
	int transfer_len, ret;
	u8 tx_buf[MAX_SPI_FRAMESIZE];
	u8 rx_buf[MAX_SPI_FRAMESIZE];

	if (in && out) {
		log(LOGC_NONE, LOGL_ERR, "%s: can't do full duplex\n",
		    __func__);
		return -EINVAL;
	}

	ret = spi_claim_bus(slave);
	if (ret < 0) {
		log(LOGC_NONE, LOGL_ERR, "%s: could not claim bus\n", __func__);
		return ret;
	}

	while (len) {
		/* Request */
		transfer_len = min_t(u16, len, MAX_SPI_FRAMESIZE);
		tx_buf[0] = (in ? BIT(7) : 0) | (transfer_len - 1);
		tx_buf[1] = 0xD4;
		tx_buf[2] = addr >> 8;
		tx_buf[3] = addr;

		ret = spi_xfer(slave, 4 * 8, tx_buf, rx_buf, SPI_XFER_BEGIN);
		if (ret < 0) {
			log(LOGC_NONE, LOGL_ERR,
			    "%s: spi request transfer failed (err: %d)\n",
			    __func__, ret);
			goto release_bus;
		}

		/* Wait state */
		if (!(rx_buf[3] & 0x1)) {
			int i;

			for (i = 0; i < TPM_WAIT_STATES; i++) {
				ret = spi_xfer(slave, 1 * 8, NULL, rx_buf, 0);
				if (ret) {
					log(LOGC_NONE, LOGL_ERR,
					    "%s: wait state failed: %d\n",
					    __func__, ret);
					goto release_bus;
				}

				if (rx_buf[0] & 0x1)
					break;
			}

			if (i == TPM_WAIT_STATES) {
				log(LOGC_NONE, LOGL_ERR,
				    "%s: timeout on wait state\n", __func__);
				ret = -ETIMEDOUT;
				goto release_bus;
			}
		}

		/* Read/Write */
		if (out) {
			memcpy(tx_buf, out, transfer_len);
			out += transfer_len;
		}

		ret = spi_xfer(slave, transfer_len * 8,
			       out ? tx_buf : NULL,
			       in ? rx_buf : NULL,
			       SPI_XFER_END);
		if (ret) {
			log(LOGC_NONE, LOGL_ERR,
			    "%s: spi read transfer failed (err: %d)\n",
			    __func__, ret);
			goto release_bus;
		}

		if (in) {
			memcpy(in, rx_buf, transfer_len);
			in += transfer_len;
		}

		len -= transfer_len;
	}

release_bus:
	/* If an error occurred, release the chip by deasserting the CS */
	if (ret < 0)
		spi_xfer(slave, 0, NULL, NULL, SPI_XFER_END);

	spi_release_bus(slave);

	return ret;
}

static int tpm_tis_spi_read(struct udevice *dev, u16 addr, u8 *in, u16 len)
{
	return tpm_tis_spi_xfer(dev, addr, NULL, in, len);
}

static int tpm_tis_spi_read32(struct udevice *dev, u32 addr, u32 *result)
{
	__le32 result_le;
	int ret;

	ret = tpm_tis_spi_read(dev, addr, (u8 *)&result_le, sizeof(u32));
	if (!ret)
		*result = le32_to_cpu(result_le);

	return ret;
}

static int tpm_tis_spi_write(struct udevice *dev, u16 addr, const u8 *out,
			     u16 len)
{
	return tpm_tis_spi_xfer(dev, addr, out, NULL, len);
}

static int tpm_tis_spi_check_locality(struct udevice *dev, int loc)
{
	const u8 mask = TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID;
	struct tpm_chip *chip = dev_get_priv(dev);
	u8 buf;
	int ret;

	ret = tpm_tis_spi_read(dev, TPM_ACCESS(loc), &buf, 1);
	if (ret)
		return ret;

	if ((buf & mask) == mask) {
		chip->locality = loc;
		return 0;
	}

	return -ENOENT;
}

static void tpm_tis_spi_release_locality(struct udevice *dev, int loc,
					 bool force)
{
	const u8 mask = TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID;
	u8 buf;

	if (tpm_tis_spi_read(dev, TPM_ACCESS(loc), &buf, 1) < 0)
		return;

	if (force || (buf & mask) == mask) {
		buf = TPM_ACCESS_ACTIVE_LOCALITY;
		tpm_tis_spi_write(dev, TPM_ACCESS(loc), &buf, 1);
	}
}

static int tpm_tis_spi_request_locality(struct udevice *dev, int loc)
{
	struct tpm_chip *chip = dev_get_priv(dev);
	unsigned long start, stop;
	u8 buf = TPM_ACCESS_REQUEST_USE;
	int ret;

	ret = tpm_tis_spi_check_locality(dev, loc);
	if (!ret)
		return 0;

	if (ret != -ENOENT) {
		log(LOGC_NONE, LOGL_ERR, "%s: Failed to get locality: %d\n",
		    __func__, ret);
		return ret;
	}

	ret = tpm_tis_spi_write(dev, TPM_ACCESS(loc), &buf, 1);
	if (ret) {
		log(LOGC_NONE, LOGL_ERR, "%s: Failed to write to TPM: %d\n",
		    __func__, ret);
		return ret;
	}

	start = get_timer(0);
	stop = chip->timeout_a;
	do {
		ret = tpm_tis_spi_check_locality(dev, loc);
		if (!ret)
			return 0;

		if (ret != -ENOENT) {
			log(LOGC_NONE, LOGL_ERR,
			    "%s: Failed to get locality: %d\n", __func__, ret);
			return ret;
		}

		mdelay(TPM_TIMEOUT_MS);
	} while (get_timer(start) < stop);

	log(LOGC_NONE, LOGL_ERR, "%s: Timeout getting locality: %d\n", __func__,
	    ret);

	return ret;
}

static u8 tpm_tis_spi_status(struct udevice *dev, u8 *status)
{
	struct tpm_chip *chip = dev_get_priv(dev);

	return tpm_tis_spi_read(dev, TPM_STS(chip->locality), status, 1);
}

static int tpm_tis_spi_wait_for_stat(struct udevice *dev, u8 mask,
				     unsigned long timeout, u8 *status)
{
	unsigned long start = get_timer(0);
	unsigned long stop = timeout;
	int ret;

	do {
		mdelay(TPM_TIMEOUT_MS);
		ret = tpm_tis_spi_status(dev, status);
		if (ret)
			return ret;

		if ((*status & mask) == mask)
			return 0;
	} while (get_timer(start) < stop);

	return -ETIMEDOUT;
}

static u8 tpm_tis_spi_valid_status(struct udevice *dev, u8 *status)
{
	struct tpm_chip *chip = dev_get_priv(dev);

	return tpm_tis_spi_wait_for_stat(dev, TPM_STS_VALID,
		chip->timeout_c, status);
}

static int tpm_tis_spi_get_burstcount(struct udevice *dev)
{
	struct tpm_chip *chip = dev_get_priv(dev);
	unsigned long start, stop;
	u32 burstcount, ret;

	/* wait for burstcount */
	start = get_timer(0);
	stop = chip->timeout_d;
	do {
		ret = tpm_tis_spi_read32(dev, TPM_STS(chip->locality),
					 &burstcount);
		if (ret)
			return -EBUSY;

		burstcount = (burstcount >> 8) & 0xFFFF;
		if (burstcount)
			return burstcount;

		mdelay(TPM_TIMEOUT_MS);
	} while (get_timer(start) < stop);

	return -EBUSY;
}

static int tpm_tis_spi_cancel(struct udevice *dev)
{
	struct tpm_chip *chip = dev_get_priv(dev);
	u8 data = TPM_STS_COMMAND_READY;

	return tpm_tis_spi_write(dev, TPM_STS(chip->locality), &data, 1);
}

static int tpm_tis_spi_recv_data(struct udevice *dev, u8 *buf, size_t count)
{
	struct tpm_chip *chip = dev_get_priv(dev);
	int size = 0, burstcnt, len, ret;
	u8 status;

	while (size < count &&
	       tpm_tis_spi_wait_for_stat(dev,
					 TPM_STS_DATA_AVAIL | TPM_STS_VALID,
					 chip->timeout_c, &status) == 0) {
		burstcnt = tpm_tis_spi_get_burstcount(dev);
		if (burstcnt < 0)
			return burstcnt;

		len = min_t(int, burstcnt, count - size);
		ret = tpm_tis_spi_read(dev, TPM_DATA_FIFO(chip->locality),
				       buf + size, len);
		if (ret < 0)
			return ret;

		size += len;
	}

	return size;
}

static int tpm_tis_spi_recv(struct udevice *dev, u8 *buf, size_t count)
{
	struct tpm_chip *chip = dev_get_priv(dev);
	int size, expected;

	if (!chip)
		return -ENODEV;

	if (count < TPM_HEADER_SIZE) {
		size = -EIO;
		goto out;
	}

	size = tpm_tis_spi_recv_data(dev, buf, TPM_HEADER_SIZE);
	if (size < TPM_HEADER_SIZE) {
		log(LOGC_NONE, LOGL_ERR, "TPM error, unable to read header\n");
		goto out;
	}

	expected = get_unaligned_be32(buf + 2);
	if (expected > count) {
		size = -EIO;
		goto out;
	}

	size += tpm_tis_spi_recv_data(dev, &buf[TPM_HEADER_SIZE],
				   expected - TPM_HEADER_SIZE);
	if (size < expected) {
		log(LOGC_NONE, LOGL_ERR,
		    "TPM error, unable to read remaining bytes of result\n");
		size = -EIO;
		goto out;
	}

out:
	tpm_tis_spi_cancel(dev);
	tpm_tis_spi_release_locality(dev, chip->locality, false);

	return size;
}

static int tpm_tis_spi_send(struct udevice *dev, const u8 *buf, size_t len)
{
	struct tpm_chip *chip = dev_get_priv(dev);
	u32 i, size;
	u8 status;
	int burstcnt, ret;
	u8 data;

	if (!chip)
		return -ENODEV;

	if (len > TPM_DEV_BUFSIZE)
		return -E2BIG;  /* Command is too long for our tpm, sorry */

	ret = tpm_tis_spi_request_locality(dev, 0);
	if (ret < 0)
		return -EBUSY;

	/*
	 * Check if the TPM is ready. If not, if not, cancel the pending command
	 * and poll on the status to be finally ready.
	 */
	ret = tpm_tis_spi_status(dev, &status);
	if (ret)
		return ret;

	if (!(status & TPM_STS_COMMAND_READY)) {
		/* Force the transition, usually this will be done at startup */
		ret = tpm_tis_spi_cancel(dev);
		if (ret) {
			log(LOGC_NONE, LOGL_ERR,
			    "%s: Could not cancel previous operation\n",
			    __func__);
			goto out_err;
		}

		ret = tpm_tis_spi_wait_for_stat(dev, TPM_STS_COMMAND_READY,
						chip->timeout_b, &status);
		if (ret < 0 || !(status & TPM_STS_COMMAND_READY)) {
			log(LOGC_NONE, LOGL_ERR,
			    "status %d after wait for stat returned %d\n",
			    status, ret);
			goto out_err;
		}
	}

	for (i = 0; i < len - 1;) {
		burstcnt = tpm_tis_spi_get_burstcount(dev);
		if (burstcnt < 0)
			return burstcnt;

		size = min_t(int, len - i - 1, burstcnt);
		ret = tpm_tis_spi_write(dev, TPM_DATA_FIFO(chip->locality),
					buf + i, size);
		if (ret < 0)
			goto out_err;

		i += size;
	}

	ret = tpm_tis_spi_valid_status(dev, &status);
	if (ret)
		goto out_err;

	if ((status & TPM_STS_DATA_EXPECT) == 0) {
		ret = -EIO;
		goto out_err;
	}

	ret = tpm_tis_spi_write(dev, TPM_DATA_FIFO(chip->locality),
				buf + len - 1, 1);
	if (ret)
		goto out_err;

	ret = tpm_tis_spi_valid_status(dev, &status);
	if (ret)
		goto out_err;

	if ((status & TPM_STS_DATA_EXPECT) != 0) {
		ret = -EIO;
		goto out_err;
	}

	data = TPM_STS_GO;
	ret = tpm_tis_spi_write(dev, TPM_STS(chip->locality), &data, 1);
	if (ret)
		goto out_err;

	return len;

out_err:
	tpm_tis_spi_cancel(dev);
	tpm_tis_spi_release_locality(dev, chip->locality, false);

	return ret;
}

static int tpm_tis_spi_cleanup(struct udevice *dev)
{
	struct tpm_chip *chip = dev_get_priv(dev);

	tpm_tis_spi_cancel(dev);
	/*
	 * The TPM needs some time to clean up here,
	 * so we sleep rather than keeping the bus busy
	 */
	mdelay(2);
	tpm_tis_spi_release_locality(dev, chip->locality, false);

	return 0;
}

static int tpm_tis_spi_open(struct udevice *dev)
{
	struct tpm_chip *chip = dev_get_priv(dev);

	if (chip->is_open)
		return -EBUSY;

	chip->is_open = 1;

	return 0;
}

static int tpm_tis_spi_close(struct udevice *dev)
{
	struct tpm_chip *chip = dev_get_priv(dev);

	if (chip->is_open) {
		tpm_tis_spi_release_locality(dev, chip->locality, true);
		chip->is_open = 0;
	}

	return 0;
}

static int tpm_tis_get_desc(struct udevice *dev, char *buf, int size)
{
	struct tpm_chip *chip = dev_get_priv(dev);

	if (size < 80)
		return -ENOSPC;

	return snprintf(buf, size,
			"%s v2.0: VendorID 0x%04x, DeviceID 0x%04x, RevisionID 0x%02x [%s]",
			dev->name, chip->vend_dev & 0xFFFF,
			chip->vend_dev >> 16, chip->rid,
			(chip->is_open ? "open" : "closed"));
}

static int tpm_tis_wait_init(struct udevice *dev, int loc)
{
	struct tpm_chip *chip = dev_get_priv(dev);
	unsigned long start, stop;
	u8 status;
	int ret;

	start = get_timer(0);
	stop = chip->timeout_b;
	do {
		mdelay(TPM_TIMEOUT_MS);

		ret = tpm_tis_spi_read(dev, TPM_ACCESS(loc), &status, 1);
		if (ret)
			break;

		if (status & TPM_ACCESS_VALID)
			return 0;
	} while (get_timer(start) < stop);

	return -EIO;
}

static int tpm_tis_spi_probe(struct udevice *dev)
{
	struct tpm_tis_chip_data *drv_data = (void *)dev_get_driver_data(dev);
	struct tpm_chip_priv *priv = dev_get_uclass_priv(dev);
	struct tpm_chip *chip = dev_get_priv(dev);
	int ret;

	/* Use the TPM v2 stack */
	priv->version = TPM_V2;

	if (CONFIG_IS_ENABLED(DM_GPIO)) {
		struct gpio_desc reset_gpio;

		ret = gpio_request_by_name(dev, "gpio-reset", 0,
					   &reset_gpio, GPIOD_IS_OUT);
		if (ret) {
			log(LOGC_NONE, LOGL_NOTICE, "%s: missing reset GPIO\n",
			    __func__);
		} else {
			dm_gpio_set_value(&reset_gpio, 1);
			mdelay(1);
			dm_gpio_set_value(&reset_gpio, 0);
		}
	}

	/* Ensure a minimum amount of time elapsed since reset of the TPM */
	mdelay(drv_data->time_before_first_cmd_ms);

	chip->locality = 0;
	chip->timeout_a = TIS_SHORT_TIMEOUT_MS;
	chip->timeout_b = TIS_LONG_TIMEOUT_MS;
	chip->timeout_c = TIS_SHORT_TIMEOUT_MS;
	chip->timeout_d = TIS_SHORT_TIMEOUT_MS;
	priv->pcr_count = drv_data->pcr_count;
	priv->pcr_select_min = drv_data->pcr_select_min;

	ret = tpm_tis_wait_init(dev, chip->locality);
	if (ret) {
		log(LOGC_DM, LOGL_ERR, "%s: no device found\n", __func__);
		return ret;
	}

	ret = tpm_tis_spi_request_locality(dev, chip->locality);
	if (ret) {
		log(LOGC_NONE, LOGL_ERR, "%s: could not request locality %d\n",
		    __func__, chip->locality);
		return ret;
	}

	ret = tpm_tis_spi_read32(dev, TPM_DID_VID(chip->locality),
				 &chip->vend_dev);
	if (ret) {
		log(LOGC_NONE, LOGL_ERR,
		    "%s: could not retrieve VendorID/DeviceID\n", __func__);
		return ret;
	}

	ret = tpm_tis_spi_read(dev, TPM_RID(chip->locality), &chip->rid, 1);
	if (ret) {
		log(LOGC_NONE, LOGL_ERR, "%s: could not retrieve RevisionID\n",
		    __func__);
		return ret;
	}

	log(LOGC_NONE, LOGL_ERR,
	    "SPI TPMv2.0 found (vid:%04x, did:%04x, rid:%02x)\n",
	    chip->vend_dev & 0xFFFF, chip->vend_dev >> 16, chip->rid);

	return 0;
}

static int tpm_tis_spi_remove(struct udevice *dev)
{
	struct tpm_chip *chip = dev_get_priv(dev);

	tpm_tis_spi_release_locality(dev, chip->locality, true);

	return 0;
}

static const struct tpm_ops tpm_tis_spi_ops = {
	.open		= tpm_tis_spi_open,
	.close		= tpm_tis_spi_close,
	.get_desc	= tpm_tis_get_desc,
	.send		= tpm_tis_spi_send,
	.recv		= tpm_tis_spi_recv,
	.cleanup	= tpm_tis_spi_cleanup,
};

static const struct tpm_tis_chip_data tpm_tis_std_chip_data = {
	.pcr_count = 24,
	.pcr_select_min = 3,
	.time_before_first_cmd_ms = 30,
};

static const struct udevice_id tpm_tis_spi_ids[] = {
	{
		.compatible = "tcg,tpm_tis-spi",
		.data = (ulong)&tpm_tis_std_chip_data,
	},
	{ }
};

U_BOOT_DRIVER(tpm_tis_spi) = {
	.name   = "tpm_tis_spi",
	.id     = UCLASS_TPM,
	.of_match = tpm_tis_spi_ids,
	.ops    = &tpm_tis_spi_ops,
	.probe	= tpm_tis_spi_probe,
	.remove	= tpm_tis_spi_remove,
	.priv_auto	= sizeof(struct tpm_chip),
};
