1:我們在linux內核中都是開啟mmu的所以都是用的虛擬地址,需要建立VA到PA的映射表;
我們內核中映射表在arch/arm/mach-s5pv210/mach-smdkc110.c文件中
建立映射的函數是,smdkc110_map_io建立映射表
smdkc110_map_io 這個函數調用s5p_init_io函數真正
s5p_init_io
iotable_init
s3c24xx_init_clocks
s5pv210_gpiolib_init
s3c24xx_init_uarts
smdkc110_map_io 這個函數調用s5p_init_io函數,s5p_init_io
void __init s5p_init_io(struct map_desc *mach_desc, int size, void __iomem *cpuid_addr)
我們來看一下s5p_init_io函數的原型需要三個參數:參數1:結構體數組指針,參數2:數組的成員個數;參數三:虛擬地址基地址
函數s5p_init_io 在調用iotable_init函數建立靜態映射表,實際上我們看一下iotable_init函數中跟沒有用到之前傳的參數2、參數3;
直接把s5p_iodesc數組名當做數組首地址作為iotable_init函數的第一個參數、ARRAY_SIZE這個時自動計算的這個數組有幾個成員組成;
iotable_init(s5p_iodesc, ARRAY_SIZE(s5p_iodesc));
下面我們來分析一下這個man_desc 這個類型的結構體
struct map_desc {
unsigned long virtual; //虛擬地址
unsigned long pfn; //物理地址 .pfn = __phys_to_pfn(S5P_PA_CHIPID), 這里把物理地址放入__phys_to_pfn函數中傳給.pfn
unsigned long length; //長度
unsigned int type; //type
};
static struct map_desc s5p_iodesc為一個全局變量,實際上只需要有我們初始化好的這個全局變量數組
static struct map_desc s5p_iodesc[] __initdata = { { .virtual = (unsigned long)S5P_VA_CHIPID, //0xFD70_0000 .pfn = __phys_to_pfn(S5P_PA_CHIPID), //0xE000_0000 >> 12 .length = SZ_4K, //4k .type = MT_DEVICE, //0 }, { .virtual = (unsigned long)S3C_VA_SYS, //0xFD10_0000 .pfn = __phys_to_pfn(S5P_PA_SYSCON), //0xE010_0000 >> 12 .length = SZ_64K, //64k .type = MT_DEVICE, }, { .virtual = (unsigned long)S3C_VA_UART, //0xFE00_0000 .pfn = __phys_to_pfn(S3C_PA_UART), //0xE290_0000 >> 12 .length = SZ_4K, .type = MT_DEVICE, }, { .virtual = (unsigned long)VA_VIC0, .pfn = __phys_to_pfn(S5P_PA_VIC0), .length = SZ_16K, .type = MT_DEVICE, }, { .virtual = (unsigned long)VA_VIC1, .pfn = __phys_to_pfn(S5P_PA_VIC1), .length = SZ_16K, .type = MT_DEVICE, }, { .virtual = (unsigned long)S3C_VA_TIMER, .pfn = __phys_to_pfn(S5P_PA_TIMER), .length = SZ_16K, .type = MT_DEVICE, }, { .virtual = (unsigned long)S5P_VA_GPIO, //0xFD50_0000
.pfn = __phys_to_pfn(S5P_PA_GPIO), //0xE020_0000
.length = SZ_4K, //大小 4k
.type = MT_DEVICE, //0
}, };
我們有了這個map_desc結構體通過iotable_init函數就可以創建我們再map_desc數組中的設置好的物理地址到虛擬地址映射;
而真正建立虛擬地址到物理地址映射的函數是:create_mapping這個函數;
static void __init smdkc110_map_io(void) { s5p_init_io(NULL, 0, S5P_VA_CHIPID); s3c24xx_init_clocks(24000000); s5pv210_gpiolib_init(); s3c24xx_init_uarts(smdkc110_uartcfgs, ARRAY_SIZE(smdkc110_uartcfgs)); s5p_reserve_bootmem(smdkc110_media_devs, ARRAY_SIZE(smdkc110_media_devs)); #ifdef CONFIG_MTD_ONENAND s5pc110_device_onenand.name = "s5pc110-onenand"; #endif #ifdef CONFIG_MTD_NAND s3c_device_nand.name = "s5pv210-nand"; #endif s5p_device_rtc.name = "smdkc110-rtc"; }
void __init s5p_init_io(struct map_desc *mach_desc, int size, void __iomem *cpuid_addr) { unsigned long idcode; /* initialize the io descriptors we need for initialization */ iotable_init(s5p_iodesc, ARRAY_SIZE(s5p_iodesc)); if (mach_desc) iotable_init(mach_desc, size); idcode = __raw_readl(cpuid_addr); s3c_init_cpu(idcode, cpu_ids, ARRAY_SIZE(cpu_ids)); }
void __init iotable_init(struct map_desc *io_desc, int nr) { int i; for (i = 0; i < nr; i++) create_mapping(io_desc + i); }
關於create_maping函數如何建立映射表參考
http://blog.csdn.net/huyugv_830913/article/details/5884628
http://blog.csdn.net/longyue0917/article/details/7424536
映射表建立函數被調用
http://blog.csdn.net/tongxinv/article/details/54698188