drivers/spi/spi-wpcm-fiu.c

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

File Facts

System
Linux kernel
Corpus path
drivers/spi/spi-wpcm-fiu.c
Extension
.c
Size
14245 bytes
Lines
504
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 wpcm_fiu_spi {
	struct device *dev;
	struct clk *clk;
	void __iomem *regs;
	void __iomem *memory;
	size_t memory_size;
	struct regmap *shm_regmap;
};

static void wpcm_fiu_set_opcode(struct wpcm_fiu_spi *fiu, u8 opcode)
{
	writeb(opcode, fiu->regs + FIU_UMA_CODE);
}

static void wpcm_fiu_set_addr(struct wpcm_fiu_spi *fiu, u32 addr)
{
	writeb((addr >>  0) & 0xff, fiu->regs + FIU_UMA_AB0);
	writeb((addr >>  8) & 0xff, fiu->regs + FIU_UMA_AB1);
	writeb((addr >> 16) & 0xff, fiu->regs + FIU_UMA_AB2);
}

static void wpcm_fiu_set_data(struct wpcm_fiu_spi *fiu, const u8 *data, unsigned int nbytes)
{
	int i;

	for (i = 0; i < nbytes; i++)
		writeb(data[i], fiu->regs + FIU_UMA_DB0 + i);
}

static void wpcm_fiu_get_data(struct wpcm_fiu_spi *fiu, u8 *data, unsigned int nbytes)
{
	int i;

	for (i = 0; i < nbytes; i++)
		data[i] = readb(fiu->regs + FIU_UMA_DB0 + i);
}

/*
 * Perform a UMA (User Mode Access) operation, i.e. a software-controlled SPI transfer.
 */
static int wpcm_fiu_do_uma(struct wpcm_fiu_spi *fiu, unsigned int cs,
			   bool use_addr, bool write, int data_bytes)
{
	int i = 0;
	u8 cts = FIU_UMA_CTS_EXEC_DONE | FIU_UMA_CTS_CS(cs);

	if (use_addr)
		cts |= FIU_UMA_CTS_A_SIZE;
	if (write)
		cts |= FIU_UMA_CTS_WR;
	cts |= FIU_UMA_CTS_D_SIZE(data_bytes);

	writeb(cts, fiu->regs + FIU_UMA_CTS);

	for (i = 0; i < UMA_WAIT_ITERATIONS; i++)
		if (!(readb(fiu->regs + FIU_UMA_CTS) & FIU_UMA_CTS_EXEC_DONE))
			return 0;

	dev_info(fiu->dev, "UMA transfer has not finished in %d iterations\n", UMA_WAIT_ITERATIONS);
	return -EIO;
}

static void wpcm_fiu_ects_assert(struct wpcm_fiu_spi *fiu, unsigned int cs)
{
	u8 ects = readb(fiu->regs + FIU_UMA_ECTS);

	ects &= ~BIT(cs);
	writeb(ects, fiu->regs + FIU_UMA_ECTS);
}

static void wpcm_fiu_ects_deassert(struct wpcm_fiu_spi *fiu, unsigned int cs)
{
	u8 ects = readb(fiu->regs + FIU_UMA_ECTS);

	ects |= BIT(cs);
	writeb(ects, fiu->regs + FIU_UMA_ECTS);
}

struct wpcm_fiu_op_shape {
	bool (*match)(const struct spi_mem_op *op);
	int (*exec)(struct spi_mem *mem, const struct spi_mem_op *op);
};

static bool wpcm_fiu_normal_match(const struct spi_mem_op *op)
{
	// Opcode 0x0b (FAST READ) is treated differently in hardware
	if (op->cmd.opcode == 0x0b)
		return false;

	return (op->addr.nbytes == 0 || op->addr.nbytes == 3) &&

Annotation

Implementation Notes