Mastering of_device_id and of_device_get_match_data in Linux Kernel Drivers
This guide explains how the of_device_id structure and of_device_get_match_data() function enable flexible device matching in ARM‑based SoCs, covering their definitions, usage patterns, code examples, troubleshooting tips, and how to expose device tables to user space.
Introduction
ARM‑based SoCs use device tree files to describe hardware and match drivers, enabling a single kernel image to support multiple devices. The of_device_id table in driver code allows the same IP core to be configured differently across SoCs.
of_device_id Data Structure
Defined in include/linux/mod_devicetable.h:
struct of_device_id {
char name[32];
char type[32];
char compatible[128];
const void *data;
};The structure first appeared around Linux‑2.6.13‑rc2 and was originally used for PCI and USB matching via scripts such as scripts/table2alias.c.
of_device_get_match_data() Function
Located in drivers/of/device.c, it returns the data field of the matched of_device_id entry:
const void *of_device_get_match_data(const struct device *dev)
{
const struct of_device_id *match;
match = of_match_device(...);
if (!match)
return NULL;
return match->data;
}
EXPORT_SYMBOL(of_device_get_match_data);The returned pointer can be cast to any driver‑specific type, allowing per‑device initialization data.
Typical Usage in a Probe Function
Define an of_device_id table with entries for each supported SoC or configuration, populating the data field with init functions or parameter structures.
In the driver’s probe(), call of_device_get_match_data(dev) to obtain the appropriate data and invoke the corresponding initialization routine.
Common Pitfalls
The device tree node is not created after parsing the DTB.
The driver does not provide an of_device_id table.
Mismatch between the compatible, name, or type fields in the table and those in the device tree.
When any of these conditions occur, the driver cannot retrieve match data, which can be diagnosed by inspecting exported device tables.
Exporting Device Tables to User Space
Register the table with MODULE_DEVICE_TABLE (defined in include/linux/module.h) using the appropriate type (e.g., of, usb, pci). The kernel script scripts/mod/file2alias.c converts these tables into modules.alias, which can be examined directly or via modinfo.
Other Device Tables
Similar tables exist for USB ( struct usb_device_id) and PCI ( struct pci_device_id), each with its own fields and export mechanisms. Example definitions:
struct usb_device_id {
__u16 match_flags;
__u16 idVendor;
__u16 idProduct;
__u16 bcdDevice_lo;
__u16 bcdDevice_hi;
__u8 bDeviceClass;
__u8 bDeviceSubClass;
__u8 bDeviceProtocol;
__u8 bInterfaceClass;
__u8 bInterfaceSubClass;
__u8 bInterfaceProtocol;
__u8 bInterfaceNumber;
kernel_ulong_t driver_info;
};
struct pci_device_id {
__u32 vendor, device;
__u32 subvendor, subdevice;
__u32 class, class_mask;
kernel_ulong_t driver_data;
};Reference
Commit log for mod_devicetable.h can be viewed at
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/log/include/linux/mod_devicetable.h.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Liangxu Linux
Liangxu, a self‑taught IT professional now working as a Linux development engineer at a Fortune 500 multinational, shares extensive Linux knowledge—fundamentals, applications, tools, plus Git, databases, Raspberry Pi, etc. (Reply “Linux” to receive essential resources.)
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
