Skip to content

Memory

Physical

Requesting

Prior to using a region of memory, the driver should request the region.

With a device tree node node and resource res:

if (!request_mem_region(res.start, resource_size(&res), "my-device"))
{
    pr_err("failed to request memory region\n");
    of_node_put(node);
    return -EBUSY;
}

This does not "do" anything with the memory, just ensures that nothing else is using it and locks the memory as being used by your driver until you release it.

Releasing

release_mem_region(res.start, resource_size(&res));

Mapping to virtual memory

Source

To allow physical memory to be used by userspace, it must be mapped to virtual memory with ioremap:

void __iomem *ioremap(unsigned long offset, unsigned long size);

With a device tree node node and resource res:

virt_mem_base = ioremap(res.start, get_total_memory());
if (!virt_mem_base) {
    pr_err("failed to ioremap physical memory region\n");
    release_mem_region(res.start, resource_size(&res));
    of_node_put(node);
    return -ENOMEM;
}

The output of ioremap is the address that you must use to access this memory.

Once you are done, you must unmap the memory.

Using this memory

You have to use functions to dereference this pointer:

unsigned char  readb(const volatile void __iomem *addr);  /* read 8 bits */
unsigned short readw(const volatile void __iomem *addr);  /* read 16 bits */
unsigned int   readl(const volatile void __iomem *addr);  /* read 32 bits */
unsigned long  readq(const volatile void __iomem *addr);  /* read 64 bits */

void writeb (unsigned char  value, volatile void __iomem *addr);  /* write 8 bits */
void writew (unsigned short value, volatile void __iomem *addr);  /* write 16 bits */
void writel (unsigned int   value, volatile void __iomem *addr);  /* write 32 bits */
void writeq (unsigned long  value, volatile void __iomem *addr);  /* write 64 bits */

Note

Function names here are due to legacy reasons (byte, word, long, quad).

Getting from virtual memory

If you have already mapped to virtual memory, you can get the address you mapped to:

phys_to_virt(res.start)

Virtual

Unmapping

if (virt_mem_base) {
    iounmap(virt_mem_base);
    pr_info("iounmapped virtual memory region");
}