Platform Device Resources In Linux
Free Linux Kernel Development Course — Platform Drivers, Part 2
In the previous lecture of this free Linux kernel development course you learned how a platform driver registers itself with module_platform_driver() and how the kernel matches a driver to a device by name. But matching a driver to a device is only half the story. Once matched, the driver needs to know where the hardware actually lives — which memory address it responds to, which IRQ line it fires on, and any private configuration data the board needs to pass down. That information is called a platform device resource, and it is the subject of this lecture.
Understanding platform device resources in Linux kernel programming is one of the most practical skills you can pick up in this free embedded Linux course, because almost every real driver — I2C controllers, UART blocks, GPIO banks, DMA engines — is written on top of this exact mechanism.
Focus Keywords
struct resource linux
IORESOURCE_MEM IORESOURCE_IRQ
free linux device drivers course
free embedded systems course
What You Will Learn
struct resource fields
the six IORESOURCE types
how resources reach the driver
device tree vs legacy board files
common resource-definition mistakes
Prerequisites
You should be comfortable with the platform bus concept, struct platform_driver, and the probe()/remove() callbacks covered in the previous lecture of this series. Basic C structures and pointers are assumed.
What Is a Platform Device Resource
A pseudo platform bus has no automatic discovery mechanism the way PCI or USB does. Nothing “enumerates” a UART controller soldered onto a board — the kernel has to be told it exists, where its registers sit in memory, and which interrupt line it uses. That description is packaged inside struct platform_device, specifically in an array of struct resource entries.
Think of a resource as a labelled sticky note the board description attaches to a device: “my registers start here and end here”, or “I will raise interrupt number 47 when I need attention”. The driver never guesses these values — it always asks the kernel for them at probe time.
For example, a device named ep_res_demo with num_resources = 3 would carry a resource array shaped like this:
| Index | Type | Meaning |
|---|---|---|
| resource[0] | IORESOURCE_MEM | First register block |
| resource[1] | IORESOURCE_MEM | Second register block |
| resource[2] | IORESOURCE_IRQ | Interrupt line |
struct resource Fields Explained
Every resource, no matter its type, is represented by the same small structure defined in include/linux/ioport.h:
struct resource {
resource_size_t start;
resource_size_t end;
const char *name;
unsigned long flags;
};
- start / end — for a memory or I/O resource these mark the beginning and end address of the region. For an IRQ or a DMA channel,
startandendhold the same number. - name — a human readable label, useful when a device exposes more than one resource of the same type and you want to fetch a specific one by name.
- flags — a bitmask that tells the kernel what kind of resource this is: memory, IRQ, DMA channel, and so on.
The Six IORESOURCE Types
Kernel 6.x still defines six resource flags in include/linux/ioport.h. Knowing what each one is for prevents a very common beginner mistake: asking for IORESOURCE_MEM when the board description actually supplied IORESOURCE_IO.
| Flag | Used For | Typical Driver |
|---|---|---|
| IORESOURCE_IO | Legacy PCI/ISA I/O ports | Old x86 peripherals |
| IORESOURCE_MEM | Memory-mapped register regions | UART, I2C, SPI controllers |
| IORESOURCE_REG | Register offsets within a shared block | Multi-function PMIC devices |
| IORESOURCE_IRQ | Interrupt line number | Almost every hardware block |
| IORESOURCE_DMA | DMA channel number | Audio codecs, storage controllers |
| IORESOURCE_BUS | Bus number range | Bridge / bus controller drivers |
How The Kernel Learns About Devices
There are two very different eras of platform resource description, and it helps to know both because you will still meet the old one in legacy code.
The Old, Deprecated Way — Board Files
Before Device Tree existed, every board had a C source file that hand-built an array of struct resource and called platform_device_register(). The driver stayed generic; the board file did all the wiring. This approach does not scale — every new board needs a kernel recompile — and mainline Linux has moved almost entirely away from it.
The Modern Way — Device Tree And ACPI
On kernel 6.x, the overwhelming majority of platform devices are created automatically. A Device Tree node with a reg property and an interrupts property is walked by the of_platform layer, which builds the struct platform_device and its resource array for you before your driver’s probe() is ever called. On ACPI-based systems the equivalent job is done by the ACPI core. Either way, your driver code stays identical — it still calls the same resource-fetching functions you will learn in the next lecture.
The path from firmware description to your driver code follows four steps:
- A Device Tree node declares its
regandinterruptsproperties. - The
of_platformbus layer walks that node during boot. - It builds a
struct platform_deviceand populates itsresource[]array. - Your driver’s
probe()function is called with that fully populated device.
Common Mistakes With Platform Device Resources
| Mistake | Why It Breaks |
|---|---|
| Assuming resource index 0 is always memory | Order depends entirely on how the device tree or board file listed resources |
| Not checking the return value of a resource lookup | A missing or mistyped device tree property returns NULL, and dereferencing it crashes the kernel |
| Hard-coding physical addresses in the driver | Defeats the whole purpose of the resource abstraction and breaks portability |
Forgetting the resource name field when several resources share a type |
Makes name-based lookup impossible and index-based lookup fragile |
Summary And Key Takeaways
- A platform device resource describes memory regions, IRQ lines, DMA channels or bus numbers that a driver needs.
struct resourcestores a start/end pair, a name, and a type flag.- There are six IORESOURCE flags;
IORESOURCE_MEMandIORESOURCE_IRQare the two you will use constantly. - Modern kernel 6.x systems build the resource array automatically from Device Tree or ACPI — you rarely hand-write it yourself anymore.
In the next lecture you will extract these resources inside probe() using platform_get_resource() and platform_get_irq(), and build an original demo driver, ep_res_demo, that reads them out and prints them to the kernel log.
Frequently Asked Questions
What is the difference between a platform device and a platform device resource?
The platform device is the object representing the hardware block itself; a resource is one piece of information attached to that device, such as a memory range or an interrupt number.
Do I still need to write struct resource arrays by hand on kernel 6.x?
Almost never for real hardware. Device Tree or ACPI supplies them automatically. You would still hand-build one for a purely virtual or test platform device.
Can a single platform device have more than one memory resource?
Yes. Many controllers expose more than one register block, so you will commonly see two or three IORESOURCE_MEM entries on the same device.
What happens if I request a resource type that the device does not have?
The lookup function returns NULL, and your probe function must check for that and fail gracefully instead of dereferencing a null pointer.
Is IORESOURCE_IO still relevant on modern ARM or RISC-V boards?
Rarely. IORESOURCE_IO exists mainly for legacy x86 I/O port peripherals; almost all embedded platform drivers use IORESOURCE_MEM instead.
Where can I see the resources the kernel assigned to a device at runtime?
Boot with a verbose log level and check dmesg, or read the device’s entry under /sys/devices, which exposes the matched resource ranges.
Continue The Free Linux Kernel Development Course
Next up: extracting these resources inside probe() with an original hands-on driver example.
