drivers/spi/spi-ljca.c

Source file repositories/reference/linux-study-clean/drivers/spi/spi-ljca.c

File Facts

System
Linux kernel
Corpus path
drivers/spi/spi-ljca.c
Extension
.c
Size
7407 bytes
Lines
297
Domain
Driver Families
Bucket
drivers/spi
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 ljca_spi_init_packet {
	u8 index;
	u8 speed;
	u8 mode;
} __packed;

struct ljca_spi_xfer_packet {
	u8 indicator;
	u8 len;
	u8 data[] __counted_by(len);
} __packed;

struct ljca_spi_dev {
	struct ljca_client *ljca;
	struct spi_controller *controller;
	struct ljca_spi_info *spi_info;
	u8 speed;
	u8 mode;

	u8 obuf[LJCA_SPI_BUF_SIZE];
	u8 ibuf[LJCA_SPI_BUF_SIZE];
};

static int ljca_spi_read_write(struct ljca_spi_dev *ljca_spi, const u8 *w_data,
			       u8 *r_data, int len, int id, int complete,
			       int cmd)
{
	struct ljca_spi_xfer_packet *w_packet =
			(struct ljca_spi_xfer_packet *)ljca_spi->obuf;
	struct ljca_spi_xfer_packet *r_packet =
			(struct ljca_spi_xfer_packet *)ljca_spi->ibuf;
	int ret;

	w_packet->indicator = FIELD_PREP(LJCA_SPI_XFER_INDICATOR_ID, id) |
			      FIELD_PREP(LJCA_SPI_XFER_INDICATOR_CMPL, complete) |
			      FIELD_PREP(LJCA_SPI_XFER_INDICATOR_INDEX,
					 ljca_spi->spi_info->id);

	if (cmd == LJCA_SPI_READ) {
		w_packet->len = sizeof(u16);
		*(__le16 *)&w_packet->data[0] = cpu_to_le16(len);
	} else {
		w_packet->len = len;
		memcpy(w_packet->data, w_data, len);
	}

	ret = ljca_transfer(ljca_spi->ljca, cmd, (u8 *)w_packet,
			    struct_size(w_packet, data, w_packet->len),
			    (u8 *)r_packet, LJCA_SPI_BUF_SIZE);
	if (ret < 0)
		return ret;
	else if (ret < sizeof(*r_packet) || r_packet->len <= 0)
		return -EIO;

	if (r_data)
		memcpy(r_data, r_packet->data, r_packet->len);

	return 0;
}

static int ljca_spi_init(struct ljca_spi_dev *ljca_spi, u8 div, u8 mode)
{
	struct ljca_spi_init_packet w_packet = {};
	int ret;

	if (ljca_spi->mode == mode && ljca_spi->speed == div)
		return 0;

	w_packet.index = ljca_spi->spi_info->id;
	w_packet.speed = div;
	w_packet.mode = FIELD_PREP(LJCA_SPI_CLK_MODE_POLARITY,
				   (mode & SPI_CPOL) ? LJCA_SPI_CLOCK_HIGH_POLARITY :
						       LJCA_SPI_CLOCK_LOW_POLARITY) |
			FIELD_PREP(LJCA_SPI_CLK_MODE_PHASE,
				   (mode & SPI_CPHA) ? LJCA_SPI_CLOCK_SECOND_PHASE :
						       LJCA_SPI_CLOCK_FIRST_PHASE);

	ret = ljca_transfer(ljca_spi->ljca, LJCA_SPI_INIT, (u8 *)&w_packet,
			    sizeof(w_packet), NULL, 0);
	if (ret < 0)
		return ret;

	ljca_spi->mode = mode;
	ljca_spi->speed = div;

	return 0;
}

static int ljca_spi_deinit(struct ljca_spi_dev *ljca_spi)
{

Annotation

Implementation Notes