drivers/input/rmi4/rmi_spi.c

Source file repositories/reference/linux-study-clean/drivers/input/rmi4/rmi_spi.c

File Facts

System
Linux kernel
Corpus path
drivers/input/rmi4/rmi_spi.c
Extension
.c
Size
12048 bytes
Lines
529
Domain
Driver Families
Bucket
drivers/input
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 rmi_spi_cmd {
	enum rmi_spi_op op;
	u16 addr;
};

struct rmi_spi_xport {
	struct rmi_transport_dev xport;
	struct spi_device *spi;

	struct mutex page_mutex;
	int page;

	u8 *rx_buf;
	u8 *tx_buf;
	int xfer_buf_size;

	struct spi_transfer *rx_xfers;
	struct spi_transfer *tx_xfers;
	int rx_xfer_count;
	int tx_xfer_count;
};

static int rmi_spi_manage_pools(struct rmi_spi_xport *rmi_spi, int len)
{
	struct spi_device *spi = rmi_spi->spi;
	int buf_size = rmi_spi->xfer_buf_size
		? rmi_spi->xfer_buf_size : RMI_SPI_DEFAULT_XFER_BUF_SIZE;
	struct spi_transfer *xfer_buf;
	void *buf;
	void *tmp;

	while (buf_size < len)
		buf_size *= 2;

	if (buf_size > RMI_SPI_XFER_SIZE_LIMIT)
		buf_size = RMI_SPI_XFER_SIZE_LIMIT;

	tmp = rmi_spi->rx_buf;
	buf = devm_kcalloc(&spi->dev, buf_size, 2,
				GFP_KERNEL | GFP_DMA);
	if (!buf)
		return -ENOMEM;

	rmi_spi->rx_buf = buf;
	rmi_spi->tx_buf = &rmi_spi->rx_buf[buf_size];
	rmi_spi->xfer_buf_size = buf_size;

	if (tmp)
		devm_kfree(&spi->dev, tmp);

	if (rmi_spi->xport.pdata.spi_data.read_delay_us)
		rmi_spi->rx_xfer_count = buf_size;
	else
		rmi_spi->rx_xfer_count = 1;

	if (rmi_spi->xport.pdata.spi_data.write_delay_us)
		rmi_spi->tx_xfer_count = buf_size;
	else
		rmi_spi->tx_xfer_count = 1;

	/*
	 * Allocate a pool of spi_transfer buffers for devices which need
	 * per byte delays.
	 */
	tmp = rmi_spi->rx_xfers;
	xfer_buf = devm_kcalloc(&spi->dev,
		rmi_spi->rx_xfer_count + rmi_spi->tx_xfer_count,
		sizeof(struct spi_transfer),
		GFP_KERNEL);
	if (!xfer_buf)
		return -ENOMEM;

	rmi_spi->rx_xfers = xfer_buf;
	rmi_spi->tx_xfers = &xfer_buf[rmi_spi->rx_xfer_count];

	if (tmp)
		devm_kfree(&spi->dev, tmp);

	return 0;
}

static int rmi_spi_xfer(struct rmi_spi_xport *rmi_spi,
			const struct rmi_spi_cmd *cmd, const u8 *tx_buf,
			int tx_len, u8 *rx_buf, int rx_len)
{
	struct spi_device *spi = rmi_spi->spi;
	struct rmi_device_platform_data_spi *spi_data =
					&rmi_spi->xport.pdata.spi_data;
	struct spi_message msg;
	struct spi_transfer *xfer;

Annotation

Implementation Notes