MMIO Access APIs¶
Overview¶
After a device's physical registers are mapped into the kernel virtual address space using ioremap(), Linux drivers access the registers through dedicated MMIO access APIs.
These APIs provide a portable and architecture-independent interface for accessing memory-mapped I/O (MMIO) registers.
The most commonly used APIs are:
readb()readw()readl()writeb()writew()writel()
Why Not Dereference Pointers Directly?¶
Although MMIO registers appear as memory addresses after ioremap(), they are not normal RAM.
Instead of writing:
Linux drivers use:
Likewise, instead of:
drivers use:
Using the MMIO access APIs allows the kernel to provide the correct implementation for different CPU architectures and I/O memory models.
MMIO Access Workflow¶
A typical Linux driver accesses device registers as follows:
Physical Register Address
│
▼
ioremap()
│
▼
Virtual MMIO Address
│
▼
readb()/readw()/readl()
writeb()/writew()/writel()
│
▼
Hardware Registers
The MMIO access APIs are used after the register region has been mapped by ioremap().
Register Access Using Offsets¶
Device registers are usually defined as offsets from a base address.
Example:
void __iomem *base;
base = ioremap(PHYS_BASE, SIZE);
writel(CTRL_ENABLE, base + REG_CTRL);
status = readl(base + REG_STATUS);
data = readl(base + REG_DATA);
This is the programming model used by most Linux platform drivers.
Register Width¶
Different devices expose registers with different widths.
| API | Register Width |
|---|---|
readb() / writeb() |
8-bit |
readw() / writew() |
16-bit |
readl() / writel() |
32-bit |
The register width must match the hardware specification.
Endianness¶
On Little Endian systems such as Raspberry Pi, ARM64, and x86, a 32-bit register value is stored as:
The MMIO access APIs handle register accesses according to the architecture's I/O memory model.
Relationship with ioremap()¶
ioremap() and the MMIO access APIs serve different purposes.
| API | Purpose |
|---|---|
ioremap() |
Map a physical register region into the kernel virtual address space |
iounmap() |
Remove the mapping |
readb() / readw() / readl() |
Read MMIO registers |
writeb() / writew() / writel() |
Write MMIO registers |
Both are required for accessing memory-mapped hardware devices.
Summary¶
Linux drivers access memory-mapped device registers through dedicated MMIO access APIs rather than directly dereferencing pointers.
The complete workflow is:
Physical Address
│
▼
ioremap()
│
▼
Virtual MMIO Address
│
▼
readb()/readw()/readl()
writeb()/writew()/writel()
│
▼
Hardware Registers
Understanding this workflow is fundamental to writing Linux platform drivers and other MMIO-based kernel drivers.