NVMEM Provider Device Tree Bindings
Free Linux Device Drivers Course — NVMEM Framework, Part 4
So far in this free embedded systems course we’ve written the C side of an NVMEM
provider — registration, cells, and read/write callbacks. None of that storage is useful to a consumer
driver until it’s described somewhere discoverable, and on any DT-based platform that description lives in
the device tree. This lecture covers NVMEM device tree bindings: how a provider node
declares its storage as child cell nodes, and how a completely unrelated consumer node references those
cells by name using nvmem-cells and nvmem-cell-names.
What You Will Learn
- Why NVMEM providers don’t get their own top-level DT binding
- How child nodes under a provider become individual data cells
- The
regand optionalbitscell properties, byte-level and bit-level - How consumer nodes bind to named cells with
nvmem-cells/nvmem-cell-names - A complete original DT example: an MMIO fuse-box provider and an unrelated consumer node
Prerequisites
struct nvmem_cell_infoand software-declared cells from Lecture 2 of this chapter- Basic device tree syntax: nodes,
reg,#address-cells/#size-cells, phandles
Providers Borrow Their Parent’s Binding
The first thing to internalize is that NVMEM, as a framework, does not define its own device tree binding
for the provider node itself. An NVMEM provider is described purely in terms of whatever bus it actually sits
on — if it’s an I2C EEPROM, it’s described using the I2C binding as a child of the I2C controller node; if it’s
a memory-mapped fuse block, it’s described using the standard reg-based MMIO binding. NVMEM adds
exactly one optional property on top of that: a boolean read-only property that marks the whole
device as non-writable from the framework’s side.
What NVMEM does define is the meaning of that provider node’s children: every child node under a provider is treated as one data cell — a named region of the provider’s storage.
Cell Properties: reg and bits
| Property | Required? | Meaning |
|---|---|---|
reg | Mandatory | Two cells: byte offset into the provider, then size in bytes of the region |
bits | Optional | Two cells: bit offset (0-7) within the byte range, then number of bits — for sub-byte fields packed inside a larger register |
A cell without bits simply covers whole bytes as given by reg. A cell with
bits narrows that further down to individual bits inside the addressed range — useful for things
like a single calibration trim bit packed alongside unrelated flags in the same byte.
An Original Provider Example: MMIO Fuse Box
Consider a fictional SoC fuse block, ep-fuse, mapped at a fixed physical address, exposing a
factory-programmed serial number cell and a single-bit “secure boot enabled” flag packed into another byte:
epfuse_serial covers 4 whole bytes starting at offset 0x10 — a plain byte-range cell. The
epfuse_secure_flag cell narrows further: it addresses byte offset 0x30, then within that single
byte picks out just bit 3, one bit wide. The framework builds an internal nvmem_cell for each
child node and adds it to the system-wide cell list automatically — no driver code is needed to declare these
cells when they come from DT; only the provider’s reg_read/reg_write callbacks and
registration are required in C, as covered in the previous lecture.
Consumer Binding: nvmem-cells and nvmem-cell-names
A completely separate node — the consumer — references these cells by phandle, giving each one a lookup name of its own choosing:
Inside the ep-secmon driver, C code never needs to know that “serial” lives at offset 0x10 in
some fuse block — it simply asks for the cell named "serial" through the standard NVMEM consumer
API (devm_nvmem_cell_get() / nvmem_cell_read()), and the binding resolves the rest.
This indirection is the entire point of the framework: swap the fuse box for a completely different chip on a
new board revision, update only the DT, and the consumer driver doesn’t change at all.
Architecture: Why This Split Matters
The provider node owns the physical layout knowledge (offsets, bit positions, bus details). The consumer
node owns only logical names. The NVMEM core sits between them, resolving phandles to cells and cells to
provider callbacks at runtime — no consumer driver ever calls reg_read directly.
Common Mistakes
- Giving the provider node its own made-up binding. There isn’t one — describe it purely per its parent bus (I2C, SPI, MMIO/syscon), and let NVMEM cell semantics apply only to its children.
- Mismatched
nvmem-cellsandnvmem-cell-namesarray lengths. Every phandle innvmem-cellsneeds a matching string at the same index innvmem-cell-names; a length mismatch breaks lookup for cells after the mismatch point. - Using
bitswithout checking the offset range. The bit offset must be 0-7 — it addresses a position within the byte(s) selected byreg, not an absolute bit address into the whole device. - Forgetting
#address-cells/#size-cellson the provider node. Without them, child cell nodes’regproperties won’t parse the way you expect.
Best Practices
- Name cell nodes descriptively in DT (
serial@10, notcell0@10) — it makes the binding self-documenting when someone reads the board DTS later. - Keep cell names in
nvmem-cell-namesstable across board revisions even if the underlying provider or offsets change — that’s the whole benefit of the indirection. - Reserve
bitsfor genuinely sub-byte fields; if a cell always aligns to whole bytes, leavebitsout entirely rather than specifying0 8. - Document the
read-onlyproperty explicitly on provider nodes holding factory-programmed data like serials or calibration trims, so accidental writes fail at the framework level.
Summary / Key Takeaways
- NVMEM providers reuse their parent bus’s DT binding — there is no NVMEM-specific provider binding beyond
the optional
read-onlyproperty. - Every child node of a provider becomes a data cell;
regis mandatory,bitsis optional for sub-byte fields. - Consumers bind to cells purely by phandle and logical name via
nvmem-cells/nvmem-cell-names, staying completely decoupled from physical layout.
Conclusion
Device tree bindings are what turn a working NVMEM provider driver into something the rest of the system can actually discover and use — without them, cells only exist as hardcoded C structures tied to one board. Once you’re comfortable declaring provider nodes, cells, and consumer references, you have the full picture needed to both write new NVMEM providers and wire arbitrary consumer drivers to whatever storage a given board exposes. That completes the practical core of the NVMEM framework in this free linux device drivers course.
Interview Questions
Does the NVMEM framework define its own device tree binding for provider nodes?
No — a provider node is described using its parent bus’s binding (I2C, SPI, MMIO/syscon); NVMEM only adds
an optional read-only property on top.
What does a child node under an NVMEM provider node represent?
It represents a single data cell — a named region of the provider’s storage, described by the mandatory
reg property and the optional bits property.
What do the two cells of the bits property mean?
The bit offset (0-7) within the byte range selected by reg, followed by the number of bits —
used for sub-byte fields packed inside a larger register.
How does a consumer node reference NVMEM cells, and why is that useful?
Through the nvmem-cells phandle list paired with nvmem-cell-names; it lets the
consumer driver ask for a cell by logical name, staying decoupled from the provider’s physical layout.
What happens if nvmem-cells and nvmem-cell-names have mismatched lengths?
Name-based lookup breaks for the cells past the point where the arrays diverge, since each name is matched to a phandle by matching array index.
FAQ
Can an NVMEM provider be entirely software-only, with no device tree node at all?
Yes — providers can declare cells purely in C via nvmem_config.cells, as shown in an earlier
lecture; DT-based cells are an alternative, not a requirement.
Is reg required on every cell node?
Yes, it’s the one mandatory cell property — it defines the byte offset and size of the cell within the provider’s storage.
Can a single provider expose both byte-range cells and bit-level cells?
Yes — some child nodes can use reg alone for whole-byte regions while others add
bits for sub-byte fields, all under the same provider node.
Does the consumer driver need to know which bus the provider sits on?
No — that’s the point of the cell/consumer indirection; the consumer only deals with logical cell names through the standard NVMEM consumer API.
Where is the full official NVMEM device tree binding documented?
In the kernel’s device tree bindings documentation under the NVMEM section, alongside bindings for individual provider types.
Continue the Free Embedded Linux Course
Next: consumer drivers that read NVMEM cells at runtime.
Next Lecture Browse Full Course