2012/10/03

Linux IO mapped memory access

APIs

For a device driver, the hardware registers access usually involves following kernel API.

  • request_mem_region: Tell kernel that the specific range of physical memory are to be used.
  • ioremap: Maps the physical memory to kernel virtual memory that can be accessed by kernel.
  • ioreadX, iowriteX: X could be 8, 16, 32, parameter is the kernel virtual memory.
  • release_mem_region: tell kernel the range of physical memory is not to be used anymore


ioread & iowirte

There are some drivers for ARM device are using "writel" and  "iowrite32" function to access IO mapped memory.
writeX read X are deprecated functions,  should use ioreadX iowriteX functions.

There is some interesting story about memory barriers of io mapped memory access.
Seems in 2006, writel and iowrite32 is no-barrier.  It is nowadays.

http://lwn.net/Articles/198988/

request_mem_region

About why some code, there is no calling of request_mem_region.
http://stackoverflow.com/questions/7682422/what-does-request-mem-region-actually-do-and-when-it-is-needed

Examples

Some source examples shows how to use io read/write related functions.
//-------------------------------------------------------------------------
// mini s3c24xx I2S driver
/* IIS controller */
#define S3C2410_PA_IIS (0x55000000)
s3c24xx_i2s.regs = ioremap(S3C2410_PA_IIS, 0x100);
reg = readl(s3c24xx_i2s.regs + S3C2410_IISMOD) & ~S3C2410_IISMOD_FS_MASK;
writel(reg | div, s3c24xx_i2s.regs + S3C2410_IISMOD);
#define ioremap(cookie,size) __arm_ioremap(cookie, size, MT_DEVICE)
__arm_ioremap(unsigned long phys_addr, size_t size, unsigned int mtype)
{
unsigned long last_addr;
unsigned long offset = phys_addr & ~PAGE_MASK;
unsigned long pfn = __phys_to_pfn(phys_addr);
/*
* Don't allow wraparound or zero size
*/
last_addr = phys_addr + size - 1;
if (!size || last_addr < phys_addr)
return NULL;
return __arm_ioremap_pfn(pfn, offset, size, mtype);
}
//-------------------------------------------------------------------------
//mini s3c24xx framebuffer driver
info->mem = request_mem_region(res->start, size, pdev->name);
info->io = ioremap(res->start, size);
lcdcon1 = readl(info->io + S3C2410_LCDCON1);
writel(lcdcon1 & ~S3C2410_LCDCON1_ENVID, info->io + S3C2410_LCDCON1);
view raw gistfile1.txt hosted with ❤ by GitHub

No comments:

Post a Comment

Post Code on Blogger

Simplest way to post code to blogger for me: <pre style="background: #f0f0f0; border: 1px dashed #CCCCCC; color: black;overflow-x:...