drivers/nvmem/meson-mx-efuse.c

Source file repositories/reference/linux-study-clean/drivers/nvmem/meson-mx-efuse.c

File Facts

System
Linux kernel
Corpus path
drivers/nvmem/meson-mx-efuse.c
Extension
.c
Size
6668 bytes
Lines
244
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 meson_mx_efuse_platform_data {
	const char *name;
	unsigned int word_size;
};

struct meson_mx_efuse {
	void __iomem *base;
	struct clk *core_clk;
	struct nvmem_config config;
};

static void meson_mx_efuse_mask_bits(struct meson_mx_efuse *efuse, u32 reg,
				     u32 mask, u32 set)
{
	u32 data;

	data = readl(efuse->base + reg);
	data &= ~mask;
	data |= (set & mask);

	writel(data, efuse->base + reg);
}

static int meson_mx_efuse_hw_enable(struct meson_mx_efuse *efuse)
{
	int err;

	err = clk_prepare_enable(efuse->core_clk);
	if (err)
		return err;

	/* power up the efuse */
	meson_mx_efuse_mask_bits(efuse, MESON_MX_EFUSE_CNTL1,
				 MESON_MX_EFUSE_CNTL1_PD_ENABLE, 0);

	meson_mx_efuse_mask_bits(efuse, MESON_MX_EFUSE_CNTL4,
				 MESON_MX_EFUSE_CNTL4_ENCRYPT_ENABLE, 0);

	return 0;
}

static void meson_mx_efuse_hw_disable(struct meson_mx_efuse *efuse)
{
	meson_mx_efuse_mask_bits(efuse, MESON_MX_EFUSE_CNTL1,
				 MESON_MX_EFUSE_CNTL1_PD_ENABLE,
				 MESON_MX_EFUSE_CNTL1_PD_ENABLE);

	clk_disable_unprepare(efuse->core_clk);
}

static int meson_mx_efuse_read_addr(struct meson_mx_efuse *efuse,
				    unsigned int addr, u32 *value)
{
	int err;
	u32 regval;

	/* write the address to read */
	regval = FIELD_PREP(MESON_MX_EFUSE_CNTL1_BYTE_ADDR_MASK, addr);
	meson_mx_efuse_mask_bits(efuse, MESON_MX_EFUSE_CNTL1,
				 MESON_MX_EFUSE_CNTL1_BYTE_ADDR_MASK, regval);

	/* inform the hardware that we changed the address */
	meson_mx_efuse_mask_bits(efuse, MESON_MX_EFUSE_CNTL1,
				 MESON_MX_EFUSE_CNTL1_BYTE_ADDR_SET,
				 MESON_MX_EFUSE_CNTL1_BYTE_ADDR_SET);
	meson_mx_efuse_mask_bits(efuse, MESON_MX_EFUSE_CNTL1,
				 MESON_MX_EFUSE_CNTL1_BYTE_ADDR_SET, 0);

	/* start the read process */
	meson_mx_efuse_mask_bits(efuse, MESON_MX_EFUSE_CNTL1,
				 MESON_MX_EFUSE_CNTL1_AUTO_RD_START,
				 MESON_MX_EFUSE_CNTL1_AUTO_RD_START);
	meson_mx_efuse_mask_bits(efuse, MESON_MX_EFUSE_CNTL1,
				 MESON_MX_EFUSE_CNTL1_AUTO_RD_START, 0);

	/*
	 * perform a dummy read to ensure that the HW has the RD_BUSY bit set
	 * when polling for the status below.
	 */
	readl(efuse->base + MESON_MX_EFUSE_CNTL1);

	err = readl_poll_timeout_atomic(efuse->base + MESON_MX_EFUSE_CNTL1,
			regval,
			(!(regval & MESON_MX_EFUSE_CNTL1_AUTO_RD_BUSY)),
			1, 1000);
	if (err) {
		dev_err(efuse->config.dev,
			"Timeout while reading efuse address %u\n", addr);
		return err;
	}

Annotation

Implementation Notes