drivers/platform/chrome/cros_ec_i2c.c

Source file repositories/reference/linux-study-clean/drivers/platform/chrome/cros_ec_i2c.c

File Facts

System
Linux kernel
Corpus path
drivers/platform/chrome/cros_ec_i2c.c
Extension
.c
Size
9193 bytes
Lines
380
Domain
Driver Families
Bucket
drivers/platform
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

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 inline struct cros_ec_device *to_ec_dev(struct device *dev)
{
	struct i2c_client *client = to_i2c_client(dev);

	return i2c_get_clientdata(client);
}

static int cros_ec_pkt_xfer_i2c(struct cros_ec_device *ec_dev,
				struct cros_ec_command *msg)
{
	struct i2c_client *client = ec_dev->priv;
	int ret = -ENOMEM;
	int i;
	int packet_len;
	u8 *out_buf = NULL;
	u8 *in_buf = NULL;
	u8 sum;
	struct i2c_msg i2c_msg[2];
	struct ec_host_response *ec_response;
	struct ec_host_request_i2c *ec_request_i2c;
	struct ec_host_response_i2c *ec_response_i2c;
	int request_header_size = sizeof(struct ec_host_request_i2c);
	int response_header_size = sizeof(struct ec_host_response_i2c);

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

	packet_len = msg->insize + response_header_size;
	if (packet_len > ec_dev->din_size) {
		ret = -EINVAL;
		goto done;
	}
	in_buf = ec_dev->din;
	i2c_msg[1].len = packet_len;
	i2c_msg[1].buf = (char *) in_buf;

	packet_len = msg->outsize + request_header_size;
	if (packet_len > ec_dev->dout_size) {
		ret = -EINVAL;
		goto done;
	}
	out_buf = ec_dev->dout;
	i2c_msg[0].len = packet_len;
	i2c_msg[0].buf = (char *) out_buf;

	/* create request data */
	ec_request_i2c = (struct ec_host_request_i2c *) out_buf;
	ec_request_i2c->command_protocol = EC_COMMAND_PROTOCOL_3;

	ec_dev->dout++;
	ret = cros_ec_prepare_tx(ec_dev, msg);
	if (ret < 0)
		goto done;
	ec_dev->dout--;

	/* send command to EC and read answer */
	ret = i2c_transfer(client->adapter, i2c_msg, 2);
	if (ret < 0) {
		dev_dbg(ec_dev->dev, "i2c transfer failed: %d\n", ret);
		goto done;
	} else if (ret != 2) {
		dev_err(ec_dev->dev, "failed to get response: %d\n", ret);
		ret = -EIO;
		goto done;
	}

	ec_response_i2c = (struct ec_host_response_i2c *) in_buf;
	msg->result = ec_response_i2c->result;

Annotation

Implementation Notes