drivers/spi/spi-fsl-espi.c

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

File Facts

System
Linux kernel
Corpus path
drivers/spi/spi-fsl-espi.c
Extension
.c
Size
21583 bytes
Lines
842
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 fsl_espi {
	struct device *dev;
	void __iomem *reg_base;

	struct list_head *m_transfers;
	struct spi_transfer *tx_t;
	unsigned int tx_pos;
	bool tx_done;
	struct spi_transfer *rx_t;
	unsigned int rx_pos;
	bool rx_done;

	bool swab;
	unsigned int rxskip;

	spinlock_t lock;

	u32 spibrg;             /* SPIBRG input clock */

	struct completion done;
};

struct fsl_espi_cs {
	u32 hw_mode;
};

static inline u32 fsl_espi_read_reg(struct fsl_espi *espi, int offset)
{
	return ioread32be(espi->reg_base + offset);
}

static inline u16 fsl_espi_read_reg16(struct fsl_espi *espi, int offset)
{
	return ioread16be(espi->reg_base + offset);
}

static inline u8 fsl_espi_read_reg8(struct fsl_espi *espi, int offset)
{
	return ioread8(espi->reg_base + offset);
}

static inline void fsl_espi_write_reg(struct fsl_espi *espi, int offset,
				      u32 val)
{
	iowrite32be(val, espi->reg_base + offset);
}

static inline void fsl_espi_write_reg16(struct fsl_espi *espi, int offset,
					u16 val)
{
	iowrite16be(val, espi->reg_base + offset);
}

static inline void fsl_espi_write_reg8(struct fsl_espi *espi, int offset,
				       u8 val)
{
	iowrite8(val, espi->reg_base + offset);
}

static int fsl_espi_check_message(struct spi_message *m)
{
	struct fsl_espi *espi = spi_controller_get_devdata(m->spi->controller);
	struct spi_transfer *t, *first;

	if (m->frame_length > SPCOM_TRANLEN_MAX) {
		dev_err(espi->dev, "message too long, size is %u bytes\n",
			m->frame_length);
		return -EMSGSIZE;
	}

	first = list_first_entry(&m->transfers, struct spi_transfer,
				 transfer_list);

	list_for_each_entry(t, &m->transfers, transfer_list) {
		if (first->bits_per_word != t->bits_per_word ||
		    first->speed_hz != t->speed_hz) {
			dev_err(espi->dev, "bits_per_word/speed_hz should be the same for all transfers\n");
			return -EINVAL;
		}
	}

	/* ESPI supports MSB-first transfers for word size 8 / 16 only */
	if (!(m->spi->mode & SPI_LSB_FIRST) && first->bits_per_word != 8 &&
	    first->bits_per_word != 16) {
		dev_err(espi->dev,
			"MSB-first transfer not supported for wordsize %u\n",
			first->bits_per_word);
		return -EINVAL;
	}

Annotation

Implementation Notes