free linux kernel development course
free linux device drivers course
of_compatible mfd_cell
free embedded systems course
This lecture on MFD device tree binding continues the free linux kernel development course by connecting the mfd_cell array from the previous lecture to real device tree nodes. You will learn how a single MFD parent node in the device tree describes child nodes for each sub-function, and how the kernel automatically matches those child nodes to the right cell using of_compatible and the child node’s reg property.
What You Will Learn
- How an MFD parent device tree node and its children are structured
- How
#address-cells/#size-cellsandregapply inside an MFD node - Two ways the kernel matches DT child nodes to
mfd_cellentries - How to extend the original
ep_mfd_demodriver with a matching device tree overlay
Prerequisites
- Completed Lecture 1: Linux MFD Subsystem Explained
- Comfortable reading and writing basic device tree source (.dts) syntax from this course’s device tree chapter
Why MFD Nodes Need Child Nodes
A device tree describes physical hardware, and an MFD chip is physically one device on the bus. So the device tree represents it as one parent node — matching the MFD core driver’s of_device_id table — with one child node per sub-function. Each child node’s compatible string is what the MFD core compares against each cell’s of_compatible field to decide which platform device belongs to which node.
Two Matching Strategies Used by the MFD Core
| Strategy | How it works | When to use it |
|---|---|---|
| Compatible-string matching | MFD core walks the parent node’s children looking for a node whose compatible equals cell->of_compatible |
Sub-functions with no numeric address, e.g. an LED or status cell |
| Reg-based matching | MFD core compares the child node’s reg property against cell->of_reg when cell->use_of_reg is set |
Sub-functions that live at a specific offset inside a shared register map, such as syscon-backed cells |
Original Device Tree Example
The following overlay matches the ep_mfd_demo driver built in Lecture 1. It is written for an I2C-attached MFD chip; adapt the bus node to your board.
/* ep-mfd-demo.dtsi — original EmbeddedPathashala teaching overlay */
&i2c1 {
status = "okay";
mfd_demo: mfd-demo@50 {
compatible = "ep,mfd-demo";
reg = <0x50>;
#address-cells = <1>;
#size-cells = <0>;
mfd_led: led {
compatible = "ep,mfd-led";
};
mfd_status: status {
compatible = "ep,mfd-status";
};
};
};
Notice that #address-cells and #size-cells are declared on the parent node even though this example does not use numeric reg matching for its children — it is good practice to declare them whenever a node has children, so the binding stays consistent if a reg-based cell is added later.
Extending the Cell Table for of_compatible Matching
// unchanged from Lecture 1 — of_compatible strings must match the DTS exactly
static const struct mfd_cell ep_mfd_cells[] = {
{ .name = "ep-mfd-led", .of_compatible = "ep,mfd-led" },
{ .name = "ep-mfd-status", .of_compatible = "ep,mfd-status" },
};
Build and Test Steps
# Compile the overlay (adjust paths to your board's dts include tree)
dtc -@ -I dts -O dtb -o ep-mfd-demo.dtbo ep-mfd-demo.dtsi
# On boards using U-Boot overlays, copy the dtbo to the overlays directory
sudo cp ep-mfd-demo.dtbo /boot/overlays/
# After reboot, confirm the parent and child nodes are visible
ls /proc/device-tree/i2c@*/mfd-demo@50/
# expect: led status compatible reg name ...
# Load the core driver from Lecture 1
sudo insmod ep_mfd_demo.ko
# Confirm both child platform devices exist
ls /sys/bus/platform/devices/ | grep -i ep-mfd
Expected Output
ep-mfd-led.0.auto
ep-mfd-status.1.auto
Each name ends in .auto because the driver used PLATFORM_DEVID_AUTO; the MFD core assigned the numeric suffix automatically when it created the platform devices from the matched device tree children.
Common Mistakes
- Compatible string typos between the DTS child node and the driver’s
of_compatiblefield — matching is exact and case-sensitive - Leaving out
#address-cells/#size-cellson the parent when children later need numericregvalues - Disabling a child node with
status = "disabled"and expecting the cell to still register — it will be skipped - Confusing the MFD parent’s own
reg(its I2C/SPI address) with a child cell’sof_regoffset
Best Practices
- Give every sub-function node a clear, documented
compatiblestring in your binding documentation - Prefer compatible-string matching for functionally distinct cells, and reg-based matching only for register-offset-defined sub-blocks
- Keep the DT binding and the
mfd_cellarray in the same commit/patch so they never drift out of sync
Real-World Use Cases
Vendor PMIC bindings such as those for axp20x and tps65086 place regulator, RTC, and power-key child nodes directly under the PMIC’s I2C node, exactly following the pattern shown here. Understanding this binding style is essential before writing or reviewing any PMIC, audio-codec, or system-controller driver in mainline Linux.
Summary / Key Takeaways
- The MFD parent DT node matches the core driver; child nodes represent each sub-function
- Compatible-string matching is the common case; reg-based matching is used for register-offset cells
- The cell table and the DT binding must be kept in sync string-for-string
Conclusion
With the device tree binding in place, the ep_mfd_demo driver from Lecture 1 now creates real, DT-backed platform devices for each sub-function. The final lecture in this mini-series introduces syscon and the simple-mfd binding, which lets you skip writing a core driver entirely for the simplest register-sharing use case.
Frequently Asked Questions
Can an MFD child node be disabled independently of the parent?
Yes. Setting status = "disabled" on a child node prevents that specific cell from being registered, while the parent and other children are unaffected.
Does every MFD cell need a reg property?
No. Only cells matched by of_reg/use_of_reg need a numeric reg; compatible-string-matched cells typically omit it.
What happens if a compatible string in the DTS has no matching cell?
The MFD core simply does not create a platform device for that node; no error is raised for an unmatched child by default.
Can I mix compatible-string and reg-based matching in the same driver?
Yes, different cells in the same array can use either matching strategy independently.
Where should I document a new MFD device tree binding?
New bindings should be documented as YAML schema files under Documentation/devicetree/bindings/mfd/ in the kernel source tree.
Do overlay-based systems like Raspberry Pi support MFD bindings?
Yes, MFD parent/child bindings work the same way whether compiled into the base DTB or loaded as a .dtbo overlay.
Continue the Free Linux Kernel Development Course
Next up: Syscon and the simple-mfd Driver
