drivers/spi/spi-amlogic-spifc-a1.c

Source file repositories/reference/linux-study-clean/drivers/spi/spi-amlogic-spifc-a1.c

File Facts

System
Linux kernel
Corpus path
drivers/spi/spi-amlogic-spifc-a1.c
Extension
.c
Size
12817 bytes
Lines
466
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 amlogic_spifc_a1 {
	struct spi_controller *ctrl;
	struct clk *clk;
	struct device *dev;
	void __iomem *base;
	u32 curr_speed_hz;
};

static int amlogic_spifc_a1_request(struct amlogic_spifc_a1 *spifc, bool read)
{
	u32 mask = SPIFC_A1_USER_REQUEST_FINISH |
		   (read ? SPIFC_A1_USER_DATA_UPDATED : 0);
	u32 val;

	writel(SPIFC_A1_USER_REQUEST_ENABLE,
	       spifc->base + SPIFC_A1_USER_CTRL0_REG);

	return readl_poll_timeout(spifc->base + SPIFC_A1_USER_CTRL0_REG,
				  val, (val & mask) == mask, 0,
				  200 * USEC_PER_MSEC);
}

static void amlogic_spifc_a1_drain_buffer(struct amlogic_spifc_a1 *spifc,
					  char *buf, u32 len)
{
	u32 data;
	const u32 count = len / sizeof(data);
	const u32 pad = len % sizeof(data);

	writel(SPIFC_A1_DBUF_AUTO_UPDATE_ADDR,
	       spifc->base + SPIFC_A1_DBUF_CTRL_REG);
	ioread32_rep(spifc->base + SPIFC_A1_DBUF_DATA_REG, buf, count);

	if (pad) {
		data = readl(spifc->base + SPIFC_A1_DBUF_DATA_REG);
		memcpy(buf + len - pad, &data, pad);
	}
}

static void amlogic_spifc_a1_fill_buffer(struct amlogic_spifc_a1 *spifc,
					 const char *buf, u32 len)
{
	u32 data;
	const u32 count = len / sizeof(data);
	const u32 pad = len % sizeof(data);

	writel(SPIFC_A1_DBUF_DIR | SPIFC_A1_DBUF_AUTO_UPDATE_ADDR,
	       spifc->base + SPIFC_A1_DBUF_CTRL_REG);
	iowrite32_rep(spifc->base + SPIFC_A1_DBUF_DATA_REG, buf, count);

	if (pad) {
		memcpy(&data, buf + len - pad, pad);
		writel(data, spifc->base + SPIFC_A1_DBUF_DATA_REG);
	}
}

static void amlogic_spifc_a1_user_init(struct amlogic_spifc_a1 *spifc)
{
	writel(0, spifc->base + SPIFC_A1_USER_CTRL0_REG);
	writel(0, spifc->base + SPIFC_A1_USER_CTRL1_REG);
	writel(0, spifc->base + SPIFC_A1_USER_CTRL2_REG);
	writel(0, spifc->base + SPIFC_A1_USER_CTRL3_REG);
}

static void amlogic_spifc_a1_set_cmd(struct amlogic_spifc_a1 *spifc,
				     u32 cmd_cfg)
{
	u32 val;

	val = readl(spifc->base + SPIFC_A1_USER_CTRL1_REG);
	val &= ~(SPIFC_A1_USER_CMD_MODE | SPIFC_A1_USER_CMD_CODE);
	val |= cmd_cfg;
	writel(val, spifc->base + SPIFC_A1_USER_CTRL1_REG);
}

static void amlogic_spifc_a1_set_addr(struct amlogic_spifc_a1 *spifc, u32 addr,
				      u32 addr_cfg)
{
	u32 val;

	writel(addr, spifc->base + SPIFC_A1_USER_ADDR_REG);

	val = readl(spifc->base + SPIFC_A1_USER_CTRL1_REG);
	val &= ~(SPIFC_A1_USER_ADDR_MODE | SPIFC_A1_USER_ADDR_BYTES);
	val |= addr_cfg;
	writel(val, spifc->base + SPIFC_A1_USER_CTRL1_REG);
}

static void amlogic_spifc_a1_set_dummy(struct amlogic_spifc_a1 *spifc,
				       u32 dummy_cfg)

Annotation

Implementation Notes