drivers/nvmem/vf610-ocotp.c
Source file repositories/reference/linux-study-clean/drivers/nvmem/vf610-ocotp.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/nvmem/vf610-ocotp.c- Extension
.c- Size
- 6102 bytes
- Lines
- 255
- 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.
- 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.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/clk.hlinux/delay.hlinux/device.hlinux/io.hlinux/module.hlinux/nvmem-provider.hlinux/of.hlinux/platform_device.hlinux/slab.h
Detected Declarations
struct vf610_ocotpfunction vf610_ocotp_wait_busyfunction vf610_ocotp_calculate_timingfunction vf610_get_fuse_addressfunction vf610_ocotp_readfunction vf610_ocotp_probe
Annotated Snippet
struct vf610_ocotp {
void __iomem *base;
struct clk *clk;
struct device *dev;
struct nvmem_device *nvmem;
int timing;
};
static int vf610_ocotp_wait_busy(void __iomem *base)
{
int timeout = VF610_OCOTP_TIMEOUT;
while ((readl(base) & OCOTP_CTRL_BUSY) && --timeout)
udelay(10);
if (!timeout) {
writel(OCOTP_CTRL_ERR, base + OCOTP_CTRL_CLR);
return -ETIMEDOUT;
}
udelay(10);
return 0;
}
static int vf610_ocotp_calculate_timing(struct vf610_ocotp *ocotp_dev)
{
u32 clk_rate;
u32 relax, strobe_read, strobe_prog;
u32 timing;
clk_rate = clk_get_rate(ocotp_dev->clk);
/* Refer section OTP read/write timing parameters in TRM */
relax = clk_rate / (1000000000 / DEF_RELAX) - 1;
strobe_prog = clk_rate / (1000000000 / 10000) + 2 * (DEF_RELAX + 1) - 1;
strobe_read = clk_rate / (1000000000 / 40) + 2 * (DEF_RELAX + 1) - 1;
timing = BF(relax, OCOTP_TIMING_RELAX);
timing |= BF(strobe_read, OCOTP_TIMING_STROBE_READ);
timing |= BF(strobe_prog, OCOTP_TIMING_STROBE_PROG);
return timing;
}
static int vf610_get_fuse_address(int base_addr_offset)
{
int i;
for (i = 0; i < ARRAY_SIZE(base_to_fuse_addr_mappings); i++) {
if (base_to_fuse_addr_mappings[i][0] == base_addr_offset)
return base_to_fuse_addr_mappings[i][1];
}
return -EINVAL;
}
static int vf610_ocotp_read(void *context, unsigned int offset,
void *val, size_t bytes)
{
struct vf610_ocotp *ocotp = context;
void __iomem *base = ocotp->base;
u32 reg, *buf = val;
int fuse_addr;
int ret;
while (bytes > 0) {
fuse_addr = vf610_get_fuse_address(offset);
if (fuse_addr > 0) {
writel(ocotp->timing, base + OCOTP_TIMING);
ret = vf610_ocotp_wait_busy(base + OCOTP_CTRL_REG);
if (ret)
return ret;
reg = readl(base + OCOTP_CTRL_REG);
reg &= ~OCOTP_CTRL_ADDR_MASK;
reg &= ~OCOTP_CTRL_WR_UNLOCK_MASK;
reg |= BF(fuse_addr, OCOTP_CTRL_ADDR);
writel(reg, base + OCOTP_CTRL_REG);
writel(OCOTP_READ_CTRL_READ_FUSE,
base + OCOTP_READ_CTRL_REG);
ret = vf610_ocotp_wait_busy(base + OCOTP_CTRL_REG);
if (ret)
return ret;
if (readl(base) & OCOTP_CTRL_ERR) {
dev_dbg(ocotp->dev, "Error reading from fuse address %x\n",
fuse_addr);
writel(OCOTP_CTRL_ERR, base + OCOTP_CTRL_CLR);
Annotation
- Immediate include surface: `linux/clk.h`, `linux/delay.h`, `linux/device.h`, `linux/io.h`, `linux/module.h`, `linux/nvmem-provider.h`, `linux/of.h`, `linux/platform_device.h`.
- Detected declarations: `struct vf610_ocotp`, `function vf610_ocotp_wait_busy`, `function vf610_ocotp_calculate_timing`, `function vf610_get_fuse_address`, `function vf610_ocotp_read`, `function vf610_ocotp_probe`.
- Atlas domain: Driver Families / drivers/nvmem.
- Implementation status: source implementation candidate.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.