drivers/spi/spi-stm32-ospi.c

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

File Facts

System
Linux kernel
Corpus path
drivers/spi/spi-stm32-ospi.c
Extension
.c
Size
26447 bytes
Lines
1088
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_ospi {
	struct device *dev;
	struct spi_controller *ctrl;
	struct clk *clk;
	struct reset_control *rstc;

	struct completion match_completion;

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

	void __iomem *regs_base;
	void __iomem *mm_base;
	phys_addr_t regs_phys_base;
	resource_size_t mm_size;
	u32 clk_rate;
	u32 fmode;
	u32 cr_reg;
	u32 dcr_reg;
	u32 flash_presc[STM32_OSPI_MAX_NORCHIP];
	int irq;
	unsigned long status_timeout;

	/*
	 * To protect device configuration, could be different between
	 * 2 flash access
	 */
	struct mutex lock;
};

static void stm32_ospi_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_ospi_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_ospi_abort(struct stm32_ospi *ospi)
{
	void __iomem *regs_base = ospi->regs_base;
	u32 cr;
	int timeout;

	cr = readl_relaxed(regs_base + OSPI_CR) | CR_ABORT;
	writel_relaxed(cr, regs_base + OSPI_CR);

	/* wait clear of abort bit by hw */
	timeout = readl_relaxed_poll_timeout_atomic(regs_base + OSPI_CR,
						    cr, !(cr & CR_ABORT), 1,
						    STM32_ABT_TIMEOUT_US);

	if (timeout)
		dev_err(ospi->dev, "%s abort timeout:%d\n", __func__, timeout);

	return timeout;
}

static int stm32_ospi_poll(struct stm32_ospi *ospi, void *buf, u32 len, bool read)
{
	void __iomem *regs_base = ospi->regs_base;
	void (*fifo)(void *val, void __iomem *addr, u8 len);
	u32 sr;
	int ret;
	u8 step;

	if (read)
		fifo = stm32_ospi_read_fifo;
	else

Annotation

Implementation Notes