drivers/nvmem/imx-ocotp.c

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

File Facts

System
Linux kernel
Corpus path
drivers/nvmem/imx-ocotp.c
Extension
.c
Size
19160 bytes
Lines
646
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 ocotp_priv {
	struct device *dev;
	struct clk *clk;
	void __iomem *base;
	const struct ocotp_params *params;
	struct nvmem_config *config;
};

struct ocotp_ctrl_reg {
	u32 bm_addr;
	u32 bm_busy;
	u32 bm_error;
	u32 bm_rel_shadows;
};

struct ocotp_params {
	unsigned int nregs;
	unsigned int bank_address_words;
	void (*set_timing)(struct ocotp_priv *priv);
	struct ocotp_ctrl_reg ctrl;
};

static int imx_ocotp_wait_for_busy(struct ocotp_priv *priv, u32 flags)
{
	int count;
	u32 c, mask;
	u32 bm_ctrl_busy, bm_ctrl_error;
	void __iomem *base = priv->base;

	bm_ctrl_busy = priv->params->ctrl.bm_busy;
	bm_ctrl_error = priv->params->ctrl.bm_error;

	mask = bm_ctrl_busy | bm_ctrl_error | flags;

	for (count = 10000; count >= 0; count--) {
		c = readl(base + IMX_OCOTP_ADDR_CTRL);
		if (!(c & mask))
			break;
		cpu_relax();
	}

	if (count < 0) {
		/* HW_OCOTP_CTRL[ERROR] will be set under the following
		 * conditions:
		 * - A write is performed to a shadow register during a shadow
		 *   reload (essentially, while HW_OCOTP_CTRL[RELOAD_SHADOWS] is
		 *   set. In addition, the contents of the shadow register shall
		 *   not be updated.
		 * - A write is performed to a shadow register which has been
		 *   locked.
		 * - A read is performed to from a shadow register which has
		 *   been read locked.
		 * - A program is performed to a fuse word which has been locked
		 * - A read is performed to from a fuse word which has been read
		 *   locked.
		 */
		if (c & bm_ctrl_error)
			return -EPERM;
		return -ETIMEDOUT;
	}

	return 0;
}

static void imx_ocotp_clr_err_if_set(struct ocotp_priv *priv)
{
	u32 c, bm_ctrl_error;
	void __iomem *base = priv->base;

	bm_ctrl_error = priv->params->ctrl.bm_error;

	c = readl(base + IMX_OCOTP_ADDR_CTRL);
	if (!(c & bm_ctrl_error))
		return;

	writel(bm_ctrl_error, base + IMX_OCOTP_ADDR_CTRL_CLR);
}

static int imx_ocotp_read(void *context, unsigned int offset,
			  void *val, size_t bytes)
{
	struct ocotp_priv *priv = context;
	unsigned int count;
	u8 *buf, *p;
	int i, ret;
	u32 index, num_bytes;

	index = offset >> 2;
	num_bytes = round_up((offset % 4) + bytes, 4);
	count = num_bytes >> 2;

Annotation

Implementation Notes