drivers/fpga/microchip-spi.c

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

File Facts

System
Linux kernel
Corpus path
drivers/fpga/microchip-spi.c
Extension
.c
Size
9960 bytes
Lines
413
Domain
Driver Families
Bucket
drivers/fpga
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 mpf_priv {
	struct spi_device *spi;
	bool program_mode;
	u8 tx __aligned(ARCH_KMALLOC_MINALIGN);
	u8 rx;
};

static int mpf_read_status(struct mpf_priv *priv)
{
	/*
	 * HW status is returned on MISO in the first byte after CS went
	 * active. However, first reading can be inadequate, so we submit
	 * two identical SPI transfers and use result of the later one.
	 */
	struct spi_transfer xfers[2] = {
		{
			.tx_buf = &priv->tx,
			.rx_buf = &priv->rx,
			.len = 1,
			.cs_change = 1,
		}, {
			.tx_buf = &priv->tx,
			.rx_buf = &priv->rx,
			.len = 1,
		},
	};
	u8 status;
	int ret;

	priv->tx = MPF_SPI_READ_STATUS;

	ret = spi_sync_transfer(priv->spi, xfers, 2);
	if (ret)
		return ret;

	status = priv->rx;

	if ((status & MPF_STATUS_SPI_VIOLATION) ||
	    (status & MPF_STATUS_SPI_ERROR))
		return -EIO;

	return status;
}

static enum fpga_mgr_states mpf_ops_state(struct fpga_manager *mgr)
{
	struct mpf_priv *priv = mgr->priv;
	bool program_mode;
	int status;

	program_mode = priv->program_mode;
	status = mpf_read_status(priv);

	if (!program_mode && !status)
		return FPGA_MGR_STATE_OPERATING;

	return FPGA_MGR_STATE_UNKNOWN;
}

static int mpf_ops_parse_header(struct fpga_manager *mgr,
				struct fpga_image_info *info,
				const char *buf, size_t count)
{
	size_t component_size_byte_num, component_size_byte_off,
	       components_size_start, bitstream_start,
	       block_id_offset, block_start_offset;
	u8 header_size, blocks_num, block_id;
	u32 block_start, component_size;
	u16 components_num, i;

	if (!buf) {
		dev_err(&mgr->dev, "Image buffer is not provided\n");
		return -EINVAL;
	}

	header_size = *(buf + MPF_HEADER_SIZE_OFFSET);
	if (header_size > count) {
		info->header_size = header_size;
		return -EAGAIN;
	}

	/*
	 * Go through look-up table to find out where actual bitstream starts
	 * and where sizes of components of the bitstream lies.
	 */
	blocks_num = *(buf + header_size - 1);
	block_id_offset = header_size + MPF_LOOKUP_TABLE_BLOCK_ID_OFFSET;
	block_start_offset = header_size + MPF_LOOKUP_TABLE_BLOCK_START_OFFSET;

	header_size += blocks_num * MPF_LOOKUP_TABLE_RECORD_SIZE;

Annotation

Implementation Notes