drivers/spi/spi-mpfs.c

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

File Facts

System
Linux kernel
Corpus path
drivers/spi/spi-mpfs.c
Extension
.c
Size
17037 bytes
Lines
629
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 mpfs_spi {
	void __iomem *regs;
	struct clk *clk;
	const u8 *tx_buf;
	u8 *rx_buf;
	u32 clk_gen; /* divider for spi output clock generated by the controller */
	u32 clk_mode;
	u32 pending_slave_select;
	int irq;
	int tx_len;
	int rx_len;
	int n_bytes;
};

static inline u32 mpfs_spi_read(struct mpfs_spi *spi, unsigned int reg)
{
	return readl(spi->regs + reg);
}

static inline void mpfs_spi_write(struct mpfs_spi *spi, unsigned int reg, u32 val)
{
	writel(val, spi->regs + reg);
}

static inline void mpfs_spi_disable(struct mpfs_spi *spi)
{
	u32 control = mpfs_spi_read(spi, REG_CONTROL);

	control &= ~CONTROL_ENABLE;

	mpfs_spi_write(spi, REG_CONTROL, control);
}

static inline void mpfs_spi_read_fifo(struct mpfs_spi *spi, int fifo_max)
{
	for (int i = 0; i < fifo_max; i++) {
		u32 data;

		while (mpfs_spi_read(spi, REG_STATUS) & STATUS_RXFIFO_EMPTY)
			;

		data = mpfs_spi_read(spi, REG_RX_DATA);

		spi->rx_len -= spi->n_bytes;

		if (!spi->rx_buf)
			continue;

		if (spi->n_bytes == 4)
			*((u32 *)spi->rx_buf) = data;
		else if (spi->n_bytes == 2)
			*((u16 *)spi->rx_buf) = data;
		else
			*spi->rx_buf = data;

		spi->rx_buf += spi->n_bytes;
	}
}

static void mpfs_spi_enable_ints(struct mpfs_spi *spi)
{
	u32 control = mpfs_spi_read(spi, REG_CONTROL);

	control |= INT_ENABLE_MASK;
	mpfs_spi_write(spi, REG_CONTROL, control);
}

static void mpfs_spi_disable_ints(struct mpfs_spi *spi)
{
	u32 control = mpfs_spi_read(spi, REG_CONTROL);

	control &= ~INT_ENABLE_MASK;
	mpfs_spi_write(spi, REG_CONTROL, control);
}

static inline void mpfs_spi_set_xfer_size(struct mpfs_spi *spi, int len)
{
	u32 control;
	u32 lenpart;
	u32 frames = mpfs_spi_read(spi, REG_FRAMESUP);

	/*
	 * Writing to FRAMECNT in REG_CONTROL will reset the frame count, taking
	 * a shortcut requires an explicit clear.
	 */
	if (frames == len) {
		mpfs_spi_write(spi, REG_COMMAND, COMMAND_CLRFRAMECNT);
		return;
	}

Annotation

Implementation Notes