free linux kernel development course
free embedded linux course
syscon regmap lookup functions
simple-mfd device tree binding
Once a syscon regmap exists, every consumer driver needs a reliable way to find it — that’s exactly what the syscon regmap lookup functions are for. This closing lecture of the MFD and syscon chapter walks through all four lookup APIs with a single working example, then shows how simple-mfd lets you skip writing an MFD core driver entirely for MMIO-based chips, as part of this free linux device drivers course.
What You Will Learn
- All four syscon regmap lookup functions and when to use each one
- A complete driver demonstrating every lookup method against the same node
- How the
simple-mfdcompatible string spawns subdevices automatically - How
simple-mfdandsysconcombine to remove the need for a custom MFD driver - A chapter-wide summary tying MFD, device tree binding, and syscon together
Prerequisites
- The syscon framework basics (covered in Lecture 7)
- MFD cell and device tree binding rules (covered in Lecture 6)
- Regmap fundamentals (covered in our Regmap API series)
The Four Syscon Regmap Lookup Functions
A consumer driver can reach a syscon’s regmap in four different ways, depending on what information is available to it at probe time:
| Function | Looks up by | Typical use case |
|---|---|---|
| syscon_node_to_regmap() | a device_node pointer | you already hold the syscon’s own node (e.g. a parent node) |
| syscon_regmap_lookup_by_compatible() | a compatible string | you know the exact compatible string of the syscon node |
| syscon_regmap_lookup_by_phandle() | a phandle property on your own node | the device tree gives you a phandle reference, the most common case |
| syscon_regmap_lookup_by_pdevname() | a platform device name string | rare legacy fallback with almost no in-tree users today |
All four eventually resolve to the exact same underlying struct regmap * if they are pointed at the same syscon node — the choice is purely about what’s most convenient to reach from your driver.
Example Device Tree
The following original binding declares a syscon node with a child consumer device, so the demo driver below has something concrete to look up against:
ep_gpr: ep-gpr@20e0000 {
compatible = "ep,soc-gpr", "syscon";
reg = <0x020e0000 0x38>;
ep_consumer: ep-consumer {
compatible = "ep,regmap-consumer";
ep-syscon-phandle = <&ep_gpr>;
};
};
A Single Driver Demonstrating All Four Lookups
The following original probe function exercises all four APIs against the node above, purely to illustrate how each one is called:
static int ep_consumer_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct device_node *syscon_np;
struct regmap *by_node, *by_compat, *by_phandle;
/* 1. by node: walk up to the syscon's own device_node */
syscon_np = of_get_parent(np);
if (!syscon_np)
return -ENODEV;
by_node = syscon_node_to_regmap(syscon_np);
of_node_put(syscon_np);
if (IS_ERR(by_node))
return PTR_ERR(by_node);
/* 2. by compatible string */
by_compat = syscon_regmap_lookup_by_compatible("ep,soc-gpr");
if (IS_ERR(by_compat))
return PTR_ERR(by_compat);
/* 3. by phandle property on our own node */
by_phandle = syscon_regmap_lookup_by_phandle(np, "ep-syscon-phandle");
if (IS_ERR(by_phandle))
return PTR_ERR(by_phandle);
dev_info(&pdev->dev, "all three lookups resolved to regmap %p\n", by_node);
return 0;
}
syscon_regmap_lookup_by_pdevname() is intentionally left out of the demo above — it is the rare fallback used by a single in-tree serial driver, and expects a platform device name string like "syscon.1" rather than anything tied to the device tree.
Build and Run the Demo
$ make -C /lib/modules/$(uname -r)/build M=$PWD modules
$ sudo insmod ep_consumer_demo.ko
$ dmesg | tail -n 3
Expected output:
[ 455.10021] ep-consumer ep-consumer: all three lookups resolved to regmap ffffbf8021340c00
Seeing the same pointer value confirms that all three lookup styles indeed resolved to the same underlying regmap instance.
Introducing simple-mfd
For MMIO-based MFD chips, subdevices frequently need zero configuration before being added to the system — no dummy clients, no per-subdevice resource tables, nothing beyond “this child node is a device, please instantiate it.” Writing a full MFD core driver just to loop over child nodes and call mfd_add_devices() is unnecessary busywork the kernel already automates.
Adding "simple-mfd" to a node’s compatible string list makes the OF core spawn a platform device for every child node automatically, using the generic for_each_child_of_node() iterator — no custom probe function required on the parent side at all. Combined with syscon, this removes the need to write an MFD driver entirely for many MMIO devices.
Example: simple-mfd Combined With syscon
ep_pmu: ep-pmu@30000 {
compatible = "ep,soc-pmu", "syscon", "simple-mfd";
reg = <0x30000 0x1000>;
ep_pmu_rtc: ep-pmu-rtc {
compatible = "ep,soc-pmu-rtc";
regmap = <&ep_pmu>;
offset = <0x40>;
};
ep_pmu_poweroff: ep-pmu-poweroff {
compatible = "syscon-poweroff";
regmap = <&ep_pmu>;
offset = <0x44>;
value = <0x1>;
mask = <0x1>;
};
};
Here, ep_pmu gets its regmap from syscon automatically, and both ep_pmu_rtc and ep_pmu_poweroff are instantiated automatically as child platform devices by simple-mfd — the parent node needs no dedicated driver of its own.
Custom MFD Driver vs simple-mfd
| Aspect | Custom MFD core driver | simple-mfd + syscon |
|---|---|---|
| Parent driver code required | Yes, must call mfd_add_devices() manually | None — subdevices spawn automatically |
| Regmap creation | Manual, via devm_regmap_init_mmio() | Automatic, via syscon |
| Best suited for | Chips needing custom IRQ demux or shared init logic | Simple MMIO blocks with independent subdevices |
Common Mistakes
- Calling
syscon_regmap_lookup_by_pdevname()expecting it to accept a device tree phandle - Forgetting
of_node_put()afterof_get_parent()before callingsyscon_node_to_regmap() - Adding
"simple-mfd"without also adding"syscon"when subdevices need regmap access - Expecting
simple-mfdto configure per-subdevice resources — it only instantiates the device, nothing more
Best Practices
- Prefer
syscon_regmap_lookup_by_phandle()for new drivers — it is the most explicit and DT-idiomatic choice - Reach for
simple-mfdfirst for MMIO chips before writing a custom MFD core driver - Always release device_node references obtained from
of_get_parent()withof_node_put()
Chapter Summary: MFD Subsystem and Syscon API
Across this chapter you’ve built up the full picture of Linux’s multi-function-device tooling: registering MFD cells and letting the core spawn platform subdevices, attaching per-subdevice resources and IRQ domains, handling chips where a subdevice needs its own I2C client, matching device tree nodes to platform drivers with of_compatible, and finally sharing miscellaneous MMIO register blocks safely through syscon. Combined with simple-mfd, these tools cover the overwhelming majority of real-world MFD chips — from I2C PMICs with several internal blocks to MMIO system-controller regions shared across unrelated drivers.
Key Takeaways
- MFD cells connect one physical chip to several independent subdevice drivers
- Dummy I2C clients let subdevices at a different address still use a regular regmap
- Device tree compatible matching, not naming, should drive most new subdevice bindings
- Syscon turns miscellaneous MMIO blocks into a shareable regmap with almost no code
- simple-mfd removes the need for a parent driver entirely on many MMIO chips
FAQ
Do all four syscon lookup functions return the same regmap?
Yes, if pointed at the same underlying syscon node they all resolve to the identical struct regmap pointer; the choice between them is only about convenience.
Which lookup function is most commonly used in new drivers?
syscon_regmap_lookup_by_phandle() is the most common, since most device tree bindings already reference the syscon node through a phandle property.
Is syscon_regmap_lookup_by_pdevname() still relevant on modern kernels?
Barely — it is a legacy fallback used by essentially one serial driver and expects a platform device name string, not a device tree reference.
What exactly does simple-mfd add on top of syscon?
syscon provides the shared regmap; simple-mfd separately makes the OF core automatically instantiate a platform device for every child node, with no custom probe function needed.
Can simple-mfd be used without syscon?
Yes, but subdevices then have no automatic way to reach a shared regmap, which is why the two are almost always combined for MMIO-based MFD chips.
Does this close out the MFD and syscon chapter?
Yes, this lecture is the closing lecture of the MFD subsystem and syscon API chapter in this free linux device drivers course.
Continue the Free Linux Kernel Development Course
