Day74 - MMIO Register Access¶
Objective¶
Understand how Linux platform drivers access hardware registers through Memory-Mapped I/O (MMIO).
This lab follows the complete path from Device Tree resources to register access patterns commonly used in Linux drivers.
Lab Environment¶
Platform:
Driver:
Lab1 - MMIO Resource Inspection¶
Device Tree¶
demo_mmio: demo-mmio@10000000 {
compatible = "demo,mmio-resource";
reg = <0x0 0x10000000 0x1000>;
};
Resource Retrieval¶
Result¶
Verification¶
Lab2 - devm_ioremap_resource()¶
Test¶
Result¶
Observation¶
The helper performs ownership checks before mapping.
Lab3 - Real MMIO Resource Inspection¶
Device Tree Nodes¶
Device Tree Reg¶
/proc/iomem¶
Observation¶
Address translation occurs through Device Tree bus mappings.
Lab4 - Device Tree ranges Translation¶
Inspection¶
Result¶
Translation¶
Example:
Verification¶
Lab5 - __iomem¶
Test¶
Result¶
Observation¶
is an address-space annotation used by kernel tooling.
It does not change pointer size.
Lab6 - Register Offset Model¶
Register Layout¶
#define DEMO_REG_CTRL 0x00
#define DEMO_REG_STATUS 0x04
#define DEMO_REG_DATA 0x08
#define DEMO_REG_IRQ_STATUS 0x0c
Observation¶
Lab7 - Simulated Register Access¶
Register Block¶
Helper Functions¶
static u32 demo_readl(void *addr)
{
return *(u32 *)addr;
}
static void demo_writel(u32 val, void *addr)
{
*(u32 *)addr = val;
}
Result¶
Verification¶
Lab8 - Bit Operations¶
Definitions¶
#define CTRL_ENABLE BIT(0)
#define CTRL_IRQ_EN BIT(1)
#define CTRL_RESET BIT(2)
#define CTRL_DMA_EN BIT(3)
Initial Value¶
Binary:
Enable Bit¶
Result:
Disable Bit¶
Result:
Verification¶
pattern.
Lab9 - Register Field Operations¶
Field Definitions¶
#define CTRL_MODE_MASK GENMASK(1, 0)
#define CTRL_DIV_MASK GENMASK(4, 2)
#define CTRL_DRV_MASK GENMASK(7, 5)
Write Fields¶
reg |= FIELD_PREP(CTRL_MODE_MASK, 2);
reg |= FIELD_PREP(CTRL_DIV_MASK, 5);
reg |= FIELD_PREP(CTRL_DRV_MASK, 3);
Read Fields¶
Result¶
Verification¶
Key Learnings¶
Device Tree reg
↓
platform_get_resource()
↓
struct resource
↓
MMIO Resource
↓
__iomem
↓
Register Offset
↓
readl()/writel()
↓
BIT()
↓
Read-Modify-Write
↓
GENMASK()/FIELD_PREP()/FIELD_GET()
This workflow forms the foundation of most Linux platform drivers.