分类: 嵌入式
2009-11-16 10:44:26
从物理地址到内核虚拟地址的映射
—分析AT91SAM9261EK板子上9261芯片自带的LCD控制器的驱动程序
本文分析了AT91SAM9261EK板子上9261芯片自带的LCD控制器的驱动程序中是如何实现从物理地址到内核虚拟地址的映射。
当系统执行/drivers/video/atmel_lcdfb.c中的atmel_lcdfb_init()时,调用 platform_driver_probe(&atmel_lcdfb_driver, atmel_lcdfb_probe)函数,首先以atmel_lcdfb_driver中()的name "atmel_lcdfb"为依据来搜索系统注册的device中有没有这个platform_device,如果有这个设备,则向系统注册该设备的驱动。
static struct platform_driver atmel_lcdfb_driver = {
.remove = __exit_p(atmel_lcdfb_remove),
.driver = {
.name = "atmel_lcdfb",
.owner = THIS_MODULE,
},
};
由于在/arch/arm/mach-at91/at91sam9261_devices.c中有下面的platform_device at91_lcdc_device,
static struct platform_device at91_lcdc_device = {
.name = "atmel_lcdfb",
.id = 0,
.dev = {
.dma_mask = &lcdc_dmamask,
.coherent_dma_mask = 0xffffffff,
.platform_data = &lcdc_data,
},
.resource = lcdc_resources,
.num_resources = ARRAY_SIZE(lcdc_resources),
};
它的name也为"atmel_lcdfb",并且在at91_add_device_lcdc()函数中已经向系统注册了该设备,所以当执行 atmel_lcdfb_probe()函数中的map = platform_get_resource(pdev, IORESOURCE_MEM, 1)时,即可得到下面定义的lcdc_resources参数,其中AT91SAM9261_LCDC_BASE即为 LCD User Interface 的起始地址0x600000,也即物理地址;AT91SAM9261_LCDC_BASE + SZ_4K - 1为结束地址。
static struct resource lcdc_resources[] = {
[0] = {
.start = AT91SAM9261_LCDC_BASE,
.end = AT91SAM9261_LCDC_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = AT91SAM9261_ID_LCDC,
.end = AT91SAM9261_ID_LCDC,
.flags = IORESOURCE_IRQ,
},
#if defined(CONFIG_FB_INTSRAM)
[2] = {
.start = AT91SAM9261_SRAM_BASE,
.end = AT91SAM9261_SRAM_BASE + AT91SAM9261_SRAM_SIZE - 1,
.flags = IORESOURCE_MEM,
},
#endif
};
然后通过ioremap()函数实现从物理地址到内核虚拟地址的映射,也即sinfo->mmio = ioremap(info->fix.mmio_start, info->fix.mmio_len);其中的
info->fix.mmio_start = regs->start(即AT91SAM9261_LCDC_BASE);
info->fix.mmio_len = regs->end(即AT91SAM9261_LCDC_BASE + SZ_4K - 1) - regs->start + 1;