drivers/fpga/lattice-sysconfig-spi.c

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

File Facts

System
Linux kernel
Corpus path
drivers/fpga/lattice-sysconfig-spi.c
Extension
.c
Size
3840 bytes
Lines
154
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

// SPDX-License-Identifier: GPL-2.0
/*
 * Lattice FPGA programming over slave SPI sysCONFIG interface.
 */

#include <linux/of.h>
#include <linux/spi/spi.h>

#include "lattice-sysconfig.h"

static const u32 ecp5_spi_max_speed_hz = 60000000;

static int sysconfig_spi_cmd_transfer(struct sysconfig_priv *priv,
				      const void *tx_buf, size_t tx_len,
				      void *rx_buf, size_t rx_len)
{
	struct spi_device *spi = to_spi_device(priv->dev);

	return spi_write_then_read(spi, tx_buf, tx_len, rx_buf, rx_len);
}

static int sysconfig_spi_bitstream_burst_init(struct sysconfig_priv *priv)
{
	const u8 lsc_bitstream_burst[] = SYSCONFIG_LSC_BITSTREAM_BURST;
	struct spi_device *spi = to_spi_device(priv->dev);
	struct spi_transfer xfer = {};
	struct spi_message msg;
	size_t buf_len;
	void *buf;
	int ret;

	buf_len = sizeof(lsc_bitstream_burst);

	buf = kmemdup(lsc_bitstream_burst, buf_len, GFP_KERNEL);
	if (!buf)
		return -ENOMEM;

	xfer.len = buf_len;
	xfer.tx_buf = buf;
	xfer.cs_change = 1;

	spi_message_init_with_transfers(&msg, &xfer, 1);

	/*
	 * Lock SPI bus for exclusive usage until FPGA programming is done.
	 * SPI bus will be released in sysconfig_spi_bitstream_burst_complete().
	 */
	spi_bus_lock(spi->controller);

	ret = spi_sync_locked(spi, &msg);
	if (ret)
		spi_bus_unlock(spi->controller);

	kfree(buf);

	return ret;
}

static int sysconfig_spi_bitstream_burst_write(struct sysconfig_priv *priv,
					       const char *buf, size_t len)
{
	struct spi_device *spi = to_spi_device(priv->dev);
	struct spi_transfer xfer = {
		.tx_buf = buf,
		.len = len,
		.cs_change = 1,
	};
	struct spi_message msg;

	spi_message_init_with_transfers(&msg, &xfer, 1);

	return spi_sync_locked(spi, &msg);
}

static int sysconfig_spi_bitstream_burst_complete(struct sysconfig_priv *priv)
{
	struct spi_device *spi = to_spi_device(priv->dev);

	/* Bitstream burst write is done, release SPI bus */
	spi_bus_unlock(spi->controller);

	/* Toggle CS to finish bitstream write */
	return spi_write(spi, NULL, 0);
}

static int sysconfig_spi_probe(struct spi_device *spi)
{
	const struct spi_device_id *dev_id;
	struct device *dev = &spi->dev;
	struct sysconfig_priv *priv;

Annotation

Implementation Notes