// SPDX-License-Identifier: GPL-2.0+
/*
 * Chromium OS cros_ec driver - I2C interface
 *
 * Copyright (c) 2012 The Chromium OS Authors.
 */

/*
 * The Matrix Keyboard Protocol driver handles talking to the keyboard
 * controller chip. Mostly this is for keyboard functions, but some other
 * things have slipped in, so we provide generic services to talk to the
 * KBC.
 */

#include <dm.h>
#include <i2c.h>
#include <cros_ec.h>
#include <log.h>

#ifdef DEBUG_TRACE
#define debug_trace(fmt, b...)	debug(fmt, #b)
#else
#define debug_trace(fmt, b...)
#endif

/**
 * Request format for protocol v3
 * byte 0	0xda (EC_COMMAND_PROTOCOL_3)
 * byte 1-8	struct ec_host_request
 * byte 10-	response data
 */
struct ec_host_request_i2c {
	/* Always 0xda to backward compatible with v2 struct */
	uint8_t  command_protocol;
	struct ec_host_request ec_request;
} __packed;

/*
 * Response format for protocol v3
 * byte 0	result code
 * byte 1	packet_length
 * byte 2-9	struct ec_host_response
 * byte 10-	response data
 */
struct ec_host_response_i2c {
	uint8_t result;
	uint8_t packet_length;
	struct ec_host_response ec_response;
} __packed;

static int cros_ec_i2c_packet(struct udevice *udev, int out_bytes, int in_bytes)
{
	struct cros_ec_dev *dev = dev_get_uclass_priv(udev);
	struct dm_i2c_chip *chip = dev_get_parent_plat(udev);
	struct ec_host_request_i2c *ec_request_i2c =
		(struct ec_host_request_i2c *)dev->dout;
	struct ec_host_response_i2c *ec_response_i2c =
		(struct ec_host_response_i2c *)dev->din;
	struct i2c_msg i2c_msg[2];
	int ret;

	i2c_msg[0].addr = chip->chip_addr;
	i2c_msg[0].flags = 0;
	i2c_msg[1].addr = chip->chip_addr;
	i2c_msg[1].flags = I2C_M_RD;

	/* one extra byte, to indicate v3 */
	i2c_msg[0].len = out_bytes + 1;
	i2c_msg[0].buf = dev->dout;

	/* stitch on EC_COMMAND_PROTOCOL_3 */
	memmove(&ec_request_i2c->ec_request, dev->dout, out_bytes);
	ec_request_i2c->command_protocol = EC_COMMAND_PROTOCOL_3;

	/* two extra bytes for v3 */
	i2c_msg[1].len = in_bytes + 2;
	i2c_msg[1].buf = dev->din;

	ret = dm_i2c_xfer(udev, &i2c_msg[0], 2);
	if (ret) {
		printf("%s: Could not execute transfer: %d\n", __func__, ret);
		return ret;
	}

	/* When we send a v3 request to v2 ec, ec won't recognize the 0xda
	 * (EC_COMMAND_PROTOCOL_3) and will return with status
	 * EC_RES_INVALID_COMMAND with zero data length
	 *
	 * In case of invalid command for v3 protocol the data length
	 * will be at least sizeof(struct ec_host_response)
	 */
	if (ec_response_i2c->result == EC_RES_INVALID_COMMAND &&
	    ec_response_i2c->packet_length == 0)
		return -EPROTONOSUPPORT;

	if (ec_response_i2c->packet_length < sizeof(struct ec_host_response)) {
		printf("%s: response of %u bytes too short; not a full hdr\n",
		       __func__, ec_response_i2c->packet_length);
		return -EBADMSG;
	}

	/* drop result and packet_len */
	memmove(dev->din, &ec_response_i2c->ec_response, in_bytes);

	return in_bytes;
}

static int cros_ec_i2c_command(struct udevice *udev, uint8_t cmd,
			       int cmd_version, const uint8_t *dout,
			       int dout_len, uint8_t **dinp, int din_len)
{
	struct cros_ec_dev *dev = dev_get_uclass_priv(udev);
	struct dm_i2c_chip *chip = dev_get_parent_plat(udev);
	struct i2c_msg i2c_msg[2];
	/* version8, cmd8, arglen8, out8[dout_len], csum8 */
	int out_bytes = dout_len + 4;
	/* response8, arglen8, in8[din_len], checksum8 */
	int in_bytes = din_len + 3;
	uint8_t *ptr;
	/* Receive input data, so that args will be dword aligned */
	uint8_t *in_ptr;
	int len, csum, ret;

	/*
	 * Sanity-check I/O sizes given transaction overhead in internal
	 * buffers.
	 */
	if (out_bytes > sizeof(dev->dout)) {
		debug("%s: Cannot send %d bytes\n", __func__, dout_len);
		return -1;
	}
	if (in_bytes > sizeof(dev->din)) {
		debug("%s: Cannot receive %d bytes\n", __func__, din_len);
		return -1;
	}
	assert(dout_len >= 0);
	assert(dinp);

	i2c_msg[0].addr = chip->chip_addr;
	i2c_msg[0].len = out_bytes;
	i2c_msg[0].buf = dev->dout;
	i2c_msg[0].flags = 0;

	/*
	 * Copy command and data into output buffer so we can do a single I2C
	 * burst transaction.
	 */
	ptr = dev->dout;

	/*
	 * in_ptr starts of pointing to a dword-aligned input data buffer.
	 * We decrement it back by the number of header bytes we expect to
	 * receive, so that the first parameter of the resulting input data
	 * will be dword aligned.
	 */
	in_ptr = dev->din + sizeof(int64_t);

	if (dev->protocol_version != 2) {
		/* Something we don't support */
		debug("%s: Protocol version %d unsupported\n",
		      __func__, dev->protocol_version);
		return -1;
	}

	*ptr++ = EC_CMD_VERSION0 + cmd_version;
	*ptr++ = cmd;
	*ptr++ = dout_len;
	in_ptr -= 2;	/* Expect status, length bytes */

	memcpy(ptr, dout, dout_len);
	ptr += dout_len;

	*ptr++ = (uint8_t)
		cros_ec_calc_checksum(dev->dout, dout_len + 3);

	i2c_msg[1].addr = chip->chip_addr;
	i2c_msg[1].len = in_bytes;
	i2c_msg[1].buf = in_ptr;
	i2c_msg[1].flags = I2C_M_RD;

	/* Send output data */
	cros_ec_dump_data("out", -1, dev->dout, out_bytes);

	ret = dm_i2c_xfer(udev, &i2c_msg[0], 2);
	if (ret) {
		debug("%s: Could not execute transfer to %s\n", __func__,
		      udev->name);
		ret = -1;
	}

	if (*in_ptr != EC_RES_SUCCESS) {
		debug("%s: Received bad result code %d\n", __func__, *in_ptr);
		return -(int)*in_ptr;
	}

	len = in_ptr[1];
	if (len + 3 > sizeof(dev->din)) {
		debug("%s: Received length %#02x too large\n",
		      __func__, len);
		return -1;
	}
	csum = cros_ec_calc_checksum(in_ptr, 2 + len);
	if (csum != in_ptr[2 + len]) {
		debug("%s: Invalid checksum rx %#02x, calced %#02x\n",
		      __func__, in_ptr[2 + din_len], csum);
		return -1;
	}
	din_len = min(din_len, len);
	cros_ec_dump_data("in", -1, in_ptr, din_len + 3);

	/* Return pointer to dword-aligned input data, if any */
	*dinp = dev->din + sizeof(int64_t);

	return din_len;
}

static int cros_ec_probe(struct udevice *dev)
{
	return cros_ec_register(dev);
}

static struct dm_cros_ec_ops cros_ec_ops = {
	.command = cros_ec_i2c_command,
	.packet = cros_ec_i2c_packet,
};

static const struct udevice_id cros_ec_ids[] = {
	{ .compatible = "google,cros-ec-i2c" },
	{ }
};

U_BOOT_DRIVER(google_cros_ec_i2c) = {
	.name		= "google_cros_ec_i2c",
	.id		= UCLASS_CROS_EC,
	.of_match	= cros_ec_ids,
	.probe		= cros_ec_probe,
	.ops		= &cros_ec_ops,
};
