drivers/nvmem/bcm-ocotp.c

Source file repositories/reference/linux-study-clean/drivers/nvmem/bcm-ocotp.c

File Facts

System
Linux kernel
Corpus path
drivers/nvmem/bcm-ocotp.c
Extension
.c
Size
7736 bytes
Lines
314
Domain
Driver Families
Bucket
drivers/nvmem
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 otpc_map {
	/* in words. */
	u32 otpc_row_size;
	/* 128 bit row / 4 words support. */
	u16 data_r_offset[4];
	/* 128 bit row / 4 words support. */
	u16 data_w_offset[4];
};

static struct otpc_map otp_map = {
	.otpc_row_size = 1,
	.data_r_offset = {0x10},
	.data_w_offset = {0x2c},
};

static struct otpc_map otp_map_v2 = {
	.otpc_row_size = 2,
	.data_r_offset = {0x10, 0x5c},
	.data_w_offset = {0x2c, 0x64},
};

struct otpc_priv {
	struct device *dev;
	void __iomem *base;
	const struct otpc_map *map;
	struct nvmem_config *config;
};

static inline void set_command(void __iomem *base, u32 command)
{
	writel(command & OTPC_CMD_MASK, base + OTPC_COMMAND_OFFSET);
}

static inline void set_cpu_address(void __iomem *base, u32 addr)
{
	writel(addr & OTPC_ADDR_MASK, base + OTPC_CPUADDR_REG_OFFSET);
}

static inline void set_start_bit(void __iomem *base)
{
	writel(1 << OTPC_CMD_START_START, base + OTPC_CMD_START_OFFSET);
}

static inline void reset_start_bit(void __iomem *base)
{
	writel(0, base + OTPC_CMD_START_OFFSET);
}

static inline void write_cpu_data(void __iomem *base, u32 value)
{
	writel(value, base + OTPC_CPU_WRITE_REG_OFFSET);
}

static int poll_cpu_status(void __iomem *base, u32 value)
{
	u32 status;
	u32 retries;

	for (retries = 0; retries < OTPC_RETRIES; retries++) {
		status = readl(base + OTPC_CPU_STATUS_OFFSET);
		if (status & value)
			break;
		udelay(1);
	}
	if (retries == OTPC_RETRIES)
		return -EAGAIN;

	return 0;
}

static int enable_ocotp_program(void __iomem *base)
{
	static const u32 vals[] = OTPC_PROG_EN_SEQ;
	int i;
	int ret;

	/* Write the magic sequence to enable programming */
	set_command(base, OTPC_CMD_OTP_PROG_ENABLE);
	for (i = 0; i < ARRAY_SIZE(vals); i++) {
		write_cpu_data(base, vals[i]);
		set_start_bit(base);
		ret = poll_cpu_status(base, OTPC_STAT_CMD_DONE);
		reset_start_bit(base);
		if (ret)
			return ret;
	}

	return poll_cpu_status(base, OTPC_STAT_PROG_OK);
}

Annotation

Implementation Notes