What is Syscon Regmap Lookup Simple-MFD in Linux Kernel

Syscon Regmap Lookup Simple-MFD-Free Linux Device Drivers Course
Free Linux Device Drivers Course — MFD Subsystem, Lecture 8 (Chapter Closing)
Lecture 8
Kernel 6.x
~16 min read

free linux device drivers course
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-mfd compatible string spawns subdevices automatically
  • How simple-mfd and syscon combine to remove the need for a custom MFD driver
  • A chapter-wide summary tying MFD, device tree binding, and syscon together

Prerequisites

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.

Four Paths, One Regmap
by node
by compatible
by phandle
by pdevname
↓↓↓↓
same struct regmap *

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() after of_get_parent() before calling syscon_node_to_regmap()
  • Adding "simple-mfd" without also adding "syscon" when subdevices need regmap access
  • Expecting simple-mfd to 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-mfd first for MMIO chips before writing a custom MFD core driver
  • Always release device_node references obtained from of_get_parent() with of_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

Leave a Reply

Your email address will not be published. Required fields are marked *