drivers/spi/spi-stm32-qspi.c

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

File Facts

System
Linux kernel
Corpus path
drivers/spi/spi-stm32-qspi.c
Extension
.c
Size
24082 bytes
Lines
982
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 stm32_qspi_flash {
	u32 cs;
	u32 presc;
};

struct stm32_qspi {
	struct device *dev;
	struct spi_controller *ctrl;
	phys_addr_t phys_base;
	void __iomem *io_base;
	void __iomem *mm_base;
	resource_size_t mm_size;
	struct clk *clk;
	u32 clk_rate;
	struct stm32_qspi_flash flash[STM32_QSPI_MAX_NORCHIP];
	struct completion match_completion;
	u32 fmode;

	struct dma_chan *dma_chtx;
	struct dma_chan *dma_chrx;
	struct completion dma_completion;

	u32 cr_reg;
	u32 dcr_reg;
	unsigned long status_timeout;

	/*
	 * to protect device configuration, could be different between
	 * 2 flash access (bk1, bk2)
	 */
	struct mutex lock;
};

static irqreturn_t stm32_qspi_irq(int irq, void *dev_id)
{
	struct stm32_qspi *qspi = (struct stm32_qspi *)dev_id;
	u32 cr, sr;

	cr = readl_relaxed(qspi->io_base + QSPI_CR);
	sr = readl_relaxed(qspi->io_base + QSPI_SR);

	if (sr & SR_SMF) {
		/* disable irq */
		cr &= ~CR_SMIE;
		writel_relaxed(cr, qspi->io_base + QSPI_CR);
		complete(&qspi->match_completion);
	}

	return IRQ_HANDLED;
}

static void stm32_qspi_read_fifo(void *val, void __iomem *addr, u8 len)
{
	switch (len) {
	case sizeof(u32):
		*((u32 *)val) = readl_relaxed(addr);
		break;
	case sizeof(u16):
		*((u16 *)val) = readw_relaxed(addr);
		break;
	case sizeof(u8):
		*((u8 *)val) = readb_relaxed(addr);
	}
}

static void stm32_qspi_write_fifo(void *val, void __iomem *addr, u8 len)
{
	switch (len) {
	case sizeof(u32):
		writel_relaxed(*((u32 *)val), addr);
		break;
	case sizeof(u16):
		writew_relaxed(*((u16 *)val), addr);
		break;
	case sizeof(u8):
		writeb_relaxed(*((u8 *)val), addr);
	}
}

static int stm32_qspi_tx_poll(struct stm32_qspi *qspi,
			      const struct spi_mem_op *op)
{
	void (*fifo)(void *val, void __iomem *addr, u8 len);
	u32 len = op->data.nbytes, sr;
	void *buf;
	int ret;
	u8 step;

	if (op->data.dir == SPI_MEM_DATA_IN) {
		fifo = stm32_qspi_read_fifo;

Annotation

Implementation Notes