drivers/spi/spi-qup.c

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

File Facts

System
Linux kernel
Corpus path
drivers/spi/spi-qup.c
Extension
.c
Size
35606 bytes
Lines
1375
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 spi_qup {
	void __iomem		*base;
	struct device		*dev;
	struct clk		*cclk;	/* core clock */
	struct clk		*iclk;	/* interface clock */
	struct icc_path		*icc_path; /* interconnect to RAM */
	int			irq;
	spinlock_t		lock;

	int			in_fifo_sz;
	int			out_fifo_sz;
	int			in_blk_sz;
	int			out_blk_sz;

	struct spi_transfer	*xfer;
	struct completion	done;
	int			error;
	int			w_size;	/* bytes per SPI word */
	int			n_words;
	int			tx_bytes;
	int			rx_bytes;
	const u8		*tx_buf;
	u8			*rx_buf;
	int			qup_v1;

	int			mode;
	struct dma_slave_config	rx_conf;
	struct dma_slave_config	tx_conf;

	u32			bw_speed_hz;
};

static int spi_qup_io_config(struct spi_device *spi, struct spi_transfer *xfer);

static inline bool spi_qup_is_flag_set(struct spi_qup *controller, u32 flag)
{
	u32 opflag = readl_relaxed(controller->base + QUP_OPERATIONAL);

	return (opflag & flag) != 0;
}

static inline bool spi_qup_is_dma_xfer(int mode)
{
	if (mode == QUP_IO_M_MODE_DMOV || mode == QUP_IO_M_MODE_BAM)
		return true;

	return false;
}

/* get's the transaction size length */
static inline unsigned int spi_qup_len(struct spi_qup *controller)
{
	return controller->n_words * controller->w_size;
}

static inline bool spi_qup_is_valid_state(struct spi_qup *controller)
{
	u32 opstate = readl_relaxed(controller->base + QUP_STATE);

	return opstate & QUP_STATE_VALID;
}

static int spi_qup_vote_bw(struct spi_qup *controller, u32 speed_hz)
{
	u32 needed_peak_bw;
	int ret;

	if (controller->bw_speed_hz == speed_hz)
		return 0;

	needed_peak_bw = Bps_to_icc(speed_hz * SPI_BUS_WIDTH);
	ret = icc_set_bw(controller->icc_path, 0, needed_peak_bw);
	if (ret)
		return ret;

	controller->bw_speed_hz = speed_hz;
	return 0;
}

static int spi_qup_set_state(struct spi_qup *controller, u32 state)
{
	unsigned long loop;
	u32 cur_state;

	loop = 0;
	while (!spi_qup_is_valid_state(controller)) {

		usleep_range(SPI_DELAY_THRESHOLD, SPI_DELAY_THRESHOLD * 2);

		if (++loop > SPI_DELAY_RETRY)

Annotation

Implementation Notes