ioremap
/ EYE-oh-ree-map /
A device's registers live at a physical address — say the hardware datasheet says 'control register at 0xFED00000.' But the kernel runs in virtual memory and cannot just dereference a raw physical address; it needs a virtual address that the MMU maps to that physical spot. ioremap is the function that builds that mapping: you hand it a physical address range, and it returns a kernel virtual pointer you can use to reach the device's registers.
Concretely you call base = ioremap(phys_addr, size), and the kernel sets up page-table entries so that the returned pointer base points at the device's MMIO region — and, importantly, it maps that region as device memory (uncached, with the right access rules), not as ordinary cacheable RAM. You then access registers as base + offset, using the writel/readl family of accessors rather than a plain dereference. When you are done (in your driver's cleanup or remove path), you call iounmap(base) to tear the mapping down. A common pattern is devm_ioremap_resource, the device-managed version, which automatically unmaps when the driver detaches, removing a whole class of leak.
ioremap matters because it is the bridge from a physical hardware address on a datasheet to a usable pointer in driver code — practically every MMIO driver starts by ioremapping its register block. Two honest cautions: the pointer ioremap returns is only valid for the I/O accessor functions and for the kernel, not for userspace and not for memcpy as if it were RAM; treating it like normal memory (caching it, letting the compiler reorder around it) is exactly the bug the MMIO barrier discipline guards against. And you must ioremap only memory that is real device space your driver owns — mapping the wrong range is undefined at the hardware level.
void __iomem *base; base = ioremap(0xFED00000, 0x1000); // map 4 KiB of regs if (!base) return -ENOMEM; writel(1, base + 0x00); // start the device ... iounmap(base); // in cleanup/remove // or use devm_ioremap_resource() for auto-unmap
ioremap turns a physical register address into a kernel virtual pointer mapped as device memory; iounmap releases it.
The returned pointer is for I/O accessors (writel/readl) only — not userspace, not memcpy, not a cacheable RAM pointer. Pair every ioremap with iounmap, or use devm_ioremap_resource for automatic cleanup.