drivers/platform/chrome/cros_ec_spi.c

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

File Facts

System
Linux kernel
Corpus path
drivers/platform/chrome/cros_ec_spi.c
Extension
.c
Size
21702 bytes
Lines
837
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 cros_ec_spi {
	struct spi_device *spi;
	s64 last_transfer_ns;
	unsigned int start_of_msg_delay;
	unsigned int end_of_msg_delay;
	struct kthread_worker *high_pri_worker;
};

typedef int (*cros_ec_xfer_fn_t) (struct cros_ec_device *ec_dev,
				  struct cros_ec_command *ec_msg);

/**
 * struct cros_ec_xfer_work_params - params for our high priority workers
 *
 * @work: The work_struct needed to queue work
 * @fn: The function to use to transfer
 * @ec_dev: ChromeOS EC device
 * @ec_msg: Message to transfer
 * @ret: The return value of the function
 */

struct cros_ec_xfer_work_params {
	struct kthread_work work;
	cros_ec_xfer_fn_t fn;
	struct cros_ec_device *ec_dev;
	struct cros_ec_command *ec_msg;
	int ret;
};

static void debug_packet(struct device *dev, const char *name, u8 *ptr,
			 int len)
{
#ifdef DEBUG
	dev_dbg(dev, "%s: %*ph\n", name, len, ptr);
#endif
}

static int terminate_request(struct cros_ec_device *ec_dev)
{
	struct cros_ec_spi *ec_spi = ec_dev->priv;
	struct spi_message msg;
	struct spi_transfer trans;
	int ret;

	/*
	 * Turn off CS, possibly adding a delay to ensure the rising edge
	 * doesn't come too soon after the end of the data.
	 */
	spi_message_init(&msg);
	memset(&trans, 0, sizeof(trans));
	trans.delay.value = ec_spi->end_of_msg_delay;
	trans.delay.unit = SPI_DELAY_UNIT_USECS;
	spi_message_add_tail(&trans, &msg);

	ret = spi_sync_locked(ec_spi->spi, &msg);

	/* Reset end-of-response timer */
	ec_spi->last_transfer_ns = ktime_get_ns();
	if (ret < 0) {
		dev_err(ec_dev->dev,
			"cs-deassert spi transfer failed: %d\n",
			ret);
	}

	return ret;
}

/**
 * receive_n_bytes - receive n bytes from the EC.
 *
 * Assumes buf is a pointer into the ec_dev->din buffer
 *
 * @ec_dev: ChromeOS EC device.
 * @buf: Pointer to the buffer receiving the data.
 * @n: Number of bytes received.
 */
static int receive_n_bytes(struct cros_ec_device *ec_dev, u8 *buf, int n)
{
	struct cros_ec_spi *ec_spi = ec_dev->priv;
	struct spi_transfer trans;
	struct spi_message msg;
	int ret;

	if (buf - ec_dev->din + n > ec_dev->din_size)
		return -EINVAL;

	memset(&trans, 0, sizeof(trans));
	trans.cs_change = 1;
	trans.rx_buf = buf;
	trans.len = n;

Annotation

Implementation Notes