drivers/nvmem/sprd-efuse.c

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

File Facts

System
Linux kernel
Corpus path
drivers/nvmem/sprd-efuse.c
Extension
.c
Size
11006 bytes
Lines
444
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 sprd_efuse_variant_data {
	u32 blk_nums;
	u32 blk_offset;
	bool blk_double;
};

struct sprd_efuse {
	struct device *dev;
	struct clk *clk;
	struct hwspinlock *hwlock;
	struct mutex mutex;
	void __iomem *base;
	const struct sprd_efuse_variant_data *data;
};

static const struct sprd_efuse_variant_data ums312_data = {
	.blk_nums = SPRD_EFUSE_NORMAL_BLOCK_NUMS,
	.blk_offset = SPRD_EFUSE_NORMAL_BLOCK_OFFSET,
	.blk_double = false,
};

/*
 * On Spreadtrum platform, we have multi-subsystems will access the unique
 * efuse controller, so we need one hardware spinlock to synchronize between
 * the multiple subsystems.
 */
static int sprd_efuse_lock(struct sprd_efuse *efuse)
{
	int ret;

	mutex_lock(&efuse->mutex);

	ret = hwspin_lock_timeout_raw(efuse->hwlock,
				      SPRD_EFUSE_HWLOCK_TIMEOUT);
	if (ret) {
		dev_err(efuse->dev, "timeout get the hwspinlock\n");
		mutex_unlock(&efuse->mutex);
		return ret;
	}

	return 0;
}

static void sprd_efuse_unlock(struct sprd_efuse *efuse)
{
	hwspin_unlock_raw(efuse->hwlock);
	mutex_unlock(&efuse->mutex);
}

static void sprd_efuse_set_prog_power(struct sprd_efuse *efuse, bool en)
{
	u32 val = readl(efuse->base + SPRD_EFUSE_PW_SWT);

	if (en)
		val &= ~SPRD_EFUSE_ENK2_ON;
	else
		val &= ~SPRD_EFUSE_ENK1_ON;

	writel(val, efuse->base + SPRD_EFUSE_PW_SWT);

	/* Open or close efuse power need wait 1000us to make power stable. */
	usleep_range(1000, 1200);

	if (en)
		val |= SPRD_EFUSE_ENK1_ON;
	else
		val |= SPRD_EFUSE_ENK2_ON;

	writel(val, efuse->base + SPRD_EFUSE_PW_SWT);

	/* Open or close efuse power need wait 1000us to make power stable. */
	usleep_range(1000, 1200);
}

static void sprd_efuse_set_read_power(struct sprd_efuse *efuse, bool en)
{
	u32 val = readl(efuse->base + SPRD_EFUSE_ENABLE);

	if (en)
		val |= SPRD_EFUSE_VDD_EN;
	else
		val &= ~SPRD_EFUSE_VDD_EN;

	writel(val, efuse->base + SPRD_EFUSE_ENABLE);

	/* Open or close efuse power need wait 1000us to make power stable. */
	usleep_range(1000, 1200);
}

static void sprd_efuse_set_prog_lock(struct sprd_efuse *efuse, bool en)

Annotation

Implementation Notes