QT210开发板的ARM Linux静态映射分析
2014-01-14 01:32
615 查看
注:内核版本为2.6.35,cpu型号为s5pv210,内容有参考网络相关文章
内核提供了一个重要的结构体struct machine_desc ,这个结构体在内核移植中起到相当重要的作用,内核通过machine_desc结构体来控制系统体系架构相关部分的初始化。machine_desc结构体的成员包含了体系架构相关部分的几个最重要的初始化函数,包括map_io,init_irq,init_machine以及phys_io ,timer成员等。
machine_desc结构体定义如下:
structmachine_desc {
/*
*Note! The first four elements are used
*by assembler code in head-armv.S
*/
unsignedint nr; /* architecture number */
unsignedint phys_io; /* start of physicalio 用来保存UART的物理地址 */
unsignedint io_pg_offst; /* byte offset for io * page tabe entry保存UART在内核空间的虚拟地址 */
constchar *name; /* architecture name */
unsignedlong ;boot_params; /* tagged list U-boot传递给kernel的启动参数地址,一般为SDRAM物理地址+0x100 */
unsignedint video_start; /* start of videoRAM */
unsignedint video_end; /* end of video RAM */
unsignedint reserve_lp0:1; /* never has lp0 */
unsignedint reserve_lp1:1; /* never has lp1 */
unsignedint reserve_lp2 :1; /* never haslp2 */
unsignedint soft_reboot :1; /* soft reboot */
void (*fixup)(struct machine_desc *,
struct tag *, char **,
struct meminfo *);
void (*map_io)(void);/*IO mapping function IO地址从物理地址到虚拟地址映射的函数指针 */
void (*init_irq)(void);/*中断初始化函数指针*/
structsys_timer *timer; /* system tick timer */
void (*init_machine)(void);
};
machine_desc结构体通过MACHINE_START宏来初始化, s5pv210 machine_desc结构体定义如下:
/* arch/arm/mach-s5/Mach-smdkv210.c*/
MACHINE_START(SMDKV210,"SMDKV210")
/*Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
.phys_io = S3C_PA_UART & 0xfff00000,
.io_pg_offst = (((u32)S3C_VA_UART) >> 18) &0xfffc,
.boot_params = S5P_PA_SDRAM + 0x100,
.init_irq = s5pv210_init_irq,
.map_io = smdkv210_map_io,/*plat-s5p,s5p平台相关的映射*/
.init_machine = smdkv210_machine_init,
#ifdef CONFIG_S5P_HIGH_RES_TIMERS
.timer = &s5p_systimer,
#else
.timer = &s3c24xx_timer,
#endif
MACHINE_END
其中的宏MACHINE_START和MACHINE_END定义如下:
/*
* Set of macros todefine architecture features. This is built into
* a table by thelinker.
*/
#defineMACHINE_START(_type,_name) \
const struct machine_desc__mach_desc_##_type \
__attribute__((__section__(".arch.info.init")))= { \
.nr= MACH_TYPE_##_type, \
.name= _name,
#define MACHINE_END \
};
其中MACH_TYPE_##_type 为GCC扩展语法中的字符拼接标识,在预编译的时候会用真正的字符代替,比如我们这里就是MACH_TYPE_SMDKV210
MACHINE_START的使用及各个成员函数的的放置位置以及调用过程如下:
MACH_TYPE_SMDKV210这个值是目标板的类型值,定义在include/generated.h内,值为2456
/* include/generated.h*/
#define MACH_TYPE_SMDKV210 2456
由上发现,MACHINE_START主要是定义了"structmachine_desc"的类型,放在section(".arch.info.init"),是初始化数据,其所占用的内存在内核起来之后将会被释放。
这里的map_io成员即内核提供给用户的创建外设I/O资源到内核虚拟地址静态映射表的接口函数。map_io成员函数会在系统初始化过程中被调用,流程如下:
start_kernel -> setup_arch()--> paging_init()->devicemaps_init中被调用
struct machine_desc 结构体的各个成员函数在不同时期被调用:
1. .init_machine 在 arch/arm/kernel/setup.c 中被 customize_machine 调用,放在 arch_initcall( ) 段里面,会自动按顺序被调用
2. init_irq在start_kernel( ) --> init_IRQ( ) -->init_arch_irq( ) 被调用
3. map_io 在 setup_arch( ) --> paging_init( )被调用
其他主要都在 setup_arch() 中用到。
用户可以在定义machine_desc结构体时指定map_io的接口函数,我们也正是这样做的。
接下来我们继续分析smdkv210_map_io的执行过程,流程如下:
smdkv210_map_io-> s5p_init_io(NULL,0, S5P_VA_CHIPID);
下面来看一下s5p_init_io函数:
/* read cpu identification code */
void __init s5p_init_io(struct map_desc*mach_desc,
intsize, void __iomem *cpuid_addr)
{
unsignedlong 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));
}
iotable_init内核提供,定义如下:
/*
* Create the architecturespecific mappings
*/
void __init iotable_init(structmap_desc *io_desc, int nr)
{
inti;
for(i = 0; i nr; i++)
create_mapping(io_desc+ i);
}
由上知道,smdkv210_map_io最终调用iotable_init建立映射表。
iotable_init函数的参数有两个:一个是map_desc类型的结构体,另一个是该结构体的数量nr。这里最关键的就是struct map_desc。map_desc结构体定义如下:
/*include/asm-arm/mach/map.h */
struct map_desc {
unsignedlong virtual;/*虚拟地址*/
unsignedlong pfn;/*物理页框地址,通过宏__phys_to_pfn(phy_addr)实现,即物理地址右移12位的方式*/
unsignedlong length;
unsignedint type;
};
create_mapping( )函数就是通过map_desc提供的信息创建线性映射表的。
这样的话我们就知道了创建I/O映射表的大致流程为:只要定义相应I/O资源的map_desc结构体,并将该结构体传给iotable_init函数执行,就可以创建相应的I/O资源到内核虚拟地址空间的映射表了。
我们来看看s5pv210是怎么定义map_desc结构体的(即上面iotable_init()函数内的s5p_iodesc)。
[arch/arm/plat-s5p]
/* minimal IO mapping */
static structmap_desc s5p_iodesc[] __initdata = {
{
.virtual = (unsigned long)S5P_VA_CHIPID,
.pfn = __phys_to_pfn(S5P_PA_CHIPID),
.length = SZ_4K,
.type = MT_DEVICE,
},{
.virtual = (unsigned long)S3C_VA_SYS,
.pfn = __phys_to_pfn(S5P_PA_SYSCON),
.length = SZ_64K,
.type = MT_DEVICE,
},{
.virtual = (unsigned long)S3C_VA_UART,
.pfn = __phys_to_pfn(S3C_PA_UART),
.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,
.pfn = __phys_to_pfn(S5P_PA_GPIO),
.length = SZ_4K,
.type = MT_DEVICE,
},
};
在s5p_init_io()函数中,除了iotable_init()以为,还会在最后调用,s3c_init_cpu
(cpu->map_io)(mach_desc, size);
而CPU的这个map_io在arch/arm/plat-s5p/cpu.c里面定义如下:
static struct cpu_table cpu_ids[] __initdata= {
{
.idcode = 0x56440100,
.idmask = 0xffffff00,
.map_io = s5p6440_map_io,
.init_clocks = s5p6440_init_clocks,
.init_uarts = s5p6440_init_uarts,
.init = s5p6440_init,
.name = name_s5p6440,
},{
.idcode = 0x36442000,
.idmask = 0xffffff00,
.map_io = s5p6442_map_io,
.init_clocks = s5p6442_init_clocks,
.init_uarts = s5p6442_init_uarts,
.init = s5p6442_init,
.name = name_s5p6442,
},{
.idcode = 0x43100000,
.idmask = 0xfffff000,
.map_io = s5pc100_map_io,
.init_clocks = s5pc100_init_clocks,
.init_uarts = s5pc100_init_uarts,
.init = s5pc100_init,
.name = name_s5pc100,
},{
.idcode = 0x43110000,
.idmask = 0xfffff000,
.map_io = s5pv210_map_io,/*cpu相关的映射*/
.init_clocks = s5pv210_init_clocks,
.init_uarts = s5pv210_init_uarts,
.init = s5pv210_init,
.name = name_s5pv210,
},
};
再查看s5pv210_map_io (),函数代码如下:
void __init s5pv210_map_io(void)
{
#ifdef CONFIG_S3C_DEV_ADC
s3c_device_adc.name = "s3c64xx-adc";
#endif
iotable_init(s5pv210_iodesc, ARRAY_SIZE(s5pv210_iodesc));
/*initialise device information early */
s5pv210_default_sdhci0();
s5pv210_default_sdhci1();
s5pv210_default_sdhci2();
/*the i2c devices are directly compatible with s3c2440 */
s3c_i2c0_setname("s3c2440-i2c");
s3c_i2c1_setname("s3c2440-i2c");
s3c_i2c2_setname("s3c2440-i2c");
}
接下来看结构s5pv210_iodesc [arch/arm/mach-s5pv20/cpu.c],代码如下,
/* Initial IO mappings */
static struct map_desc s5pv210_iodesc[]__initdata = {
{
.virtual = (unsigned long)S5P_VA_SYSTIMER,
.pfn = __phys_to_pfn(S5PV210_PA_SYSTIMER),
.length = SZ_1M,
.type = MT_DEVICE,
},{
.virtual = (unsigned long)VA_VIC2,
.pfn = __phys_to_pfn(S5PV210_PA_VIC2),
.length = SZ_16K,
.type = MT_DEVICE,
},{
.virtual = (unsigned long)VA_VIC3,
.pfn = __phys_to_pfn(S5PV210_PA_VIC3),
.length = SZ_16K,
.type = MT_DEVICE,
},{
.virtual = (unsigned long)S5P_VA_SROMC,
.pfn = __phys_to_pfn(S5PV210_PA_SROMC),
.length = SZ_4K,
.type = MT_DEVICE,
},{
.virtual = (unsigned long)S3C_VA_WATCHDOG,
.pfn = __phys_to_pfn(S5P_PA_WDT),
.length = SZ_4K,
.type = MT_DEVICE,
},{
.virtual = (unsigned long)S3C_VA_OTG,
.pfn = __phys_to_pfn(S5PV210_PA_OTG),
.length = SZ_1M,
.type = MT_DEVICE,
},{
.virtual = (unsigned long)S3C_VA_OTGSFR,
.pfn = __phys_to_pfn(S5PV210_PA_OTGSFR),
.length = SZ_1M,
.type = MT_DEVICE,
},
#if defined(CONFIG_HRT_RTC)
{
.virtual = (unsigned long)S5P_VA_RTC,
.pfn = __phys_to_pfn(S5PV210_PA_RTC),
.length = SZ_4K,
.type = MT_DEVICE,
},
#endif
{
.virtual = (unsigned long)S5P_VA_DMC0,
.pfn = __phys_to_pfn(S5P_PA_DMC0),
.length = SZ_4K,
.type = MT_DEVICE,
},{
.virtual = (unsigned long)S5P_VA_DMC1,
.pfn = __phys_to_pfn(S5P_PA_DMC1),
.length = SZ_4K,
.type = MT_DEVICE,
},{
.virtual = (unsigned long)S5P_VA_AUDSS,
.pfn = __phys_to_pfn(S5PV210_PA_AUDSS),
.length = SZ_1M,
.type = MT_DEVICE,
},{
.virtual = (unsigned long)S5P_VA_BUS_AXI_DSYS,
.pfn =__phys_to_pfn(S5PV210_PA_BUS_AXI_DSYS),
.length = SZ_4K,
.type = MT_DEVICE,
}
};
内核提供了一个重要的结构体struct machine_desc ,这个结构体在内核移植中起到相当重要的作用,内核通过machine_desc结构体来控制系统体系架构相关部分的初始化。machine_desc结构体的成员包含了体系架构相关部分的几个最重要的初始化函数,包括map_io,init_irq,init_machine以及phys_io ,timer成员等。
machine_desc结构体定义如下:
structmachine_desc {
/*
*Note! The first four elements are used
*by assembler code in head-armv.S
*/
unsignedint nr; /* architecture number */
unsignedint phys_io; /* start of physicalio 用来保存UART的物理地址 */
unsignedint io_pg_offst; /* byte offset for io * page tabe entry保存UART在内核空间的虚拟地址 */
constchar *name; /* architecture name */
unsignedlong ;boot_params; /* tagged list U-boot传递给kernel的启动参数地址,一般为SDRAM物理地址+0x100 */
unsignedint video_start; /* start of videoRAM */
unsignedint video_end; /* end of video RAM */
unsignedint reserve_lp0:1; /* never has lp0 */
unsignedint reserve_lp1:1; /* never has lp1 */
unsignedint reserve_lp2 :1; /* never haslp2 */
unsignedint soft_reboot :1; /* soft reboot */
void (*fixup)(struct machine_desc *,
struct tag *, char **,
struct meminfo *);
void (*map_io)(void);/*IO mapping function IO地址从物理地址到虚拟地址映射的函数指针 */
void (*init_irq)(void);/*中断初始化函数指针*/
structsys_timer *timer; /* system tick timer */
void (*init_machine)(void);
};
machine_desc结构体通过MACHINE_START宏来初始化, s5pv210 machine_desc结构体定义如下:
/* arch/arm/mach-s5/Mach-smdkv210.c*/
MACHINE_START(SMDKV210,"SMDKV210")
/*Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
.phys_io = S3C_PA_UART & 0xfff00000,
.io_pg_offst = (((u32)S3C_VA_UART) >> 18) &0xfffc,
.boot_params = S5P_PA_SDRAM + 0x100,
.init_irq = s5pv210_init_irq,
.map_io = smdkv210_map_io,/*plat-s5p,s5p平台相关的映射*/
.init_machine = smdkv210_machine_init,
#ifdef CONFIG_S5P_HIGH_RES_TIMERS
.timer = &s5p_systimer,
#else
.timer = &s3c24xx_timer,
#endif
MACHINE_END
其中的宏MACHINE_START和MACHINE_END定义如下:
/*
* Set of macros todefine architecture features. This is built into
* a table by thelinker.
*/
#defineMACHINE_START(_type,_name) \
const struct machine_desc__mach_desc_##_type \
__attribute__((__section__(".arch.info.init")))= { \
.nr= MACH_TYPE_##_type, \
.name= _name,
#define MACHINE_END \
};
其中MACH_TYPE_##_type 为GCC扩展语法中的字符拼接标识,在预编译的时候会用真正的字符代替,比如我们这里就是MACH_TYPE_SMDKV210
MACHINE_START的使用及各个成员函数的的放置位置以及调用过程如下:
MACH_TYPE_SMDKV210这个值是目标板的类型值,定义在include/generated.h内,值为2456
/* include/generated.h*/
#define MACH_TYPE_SMDKV210 2456
由上发现,MACHINE_START主要是定义了"structmachine_desc"的类型,放在section(".arch.info.init"),是初始化数据,其所占用的内存在内核起来之后将会被释放。
这里的map_io成员即内核提供给用户的创建外设I/O资源到内核虚拟地址静态映射表的接口函数。map_io成员函数会在系统初始化过程中被调用,流程如下:
start_kernel -> setup_arch()--> paging_init()->devicemaps_init中被调用
struct machine_desc 结构体的各个成员函数在不同时期被调用:
1. .init_machine 在 arch/arm/kernel/setup.c 中被 customize_machine 调用,放在 arch_initcall( ) 段里面,会自动按顺序被调用
2. init_irq在start_kernel( ) --> init_IRQ( ) -->init_arch_irq( ) 被调用
3. map_io 在 setup_arch( ) --> paging_init( )被调用
其他主要都在 setup_arch() 中用到。
用户可以在定义machine_desc结构体时指定map_io的接口函数,我们也正是这样做的。
接下来我们继续分析smdkv210_map_io的执行过程,流程如下:
smdkv210_map_io-> s5p_init_io(NULL,0, S5P_VA_CHIPID);
下面来看一下s5p_init_io函数:
/* read cpu identification code */
void __init s5p_init_io(struct map_desc*mach_desc,
intsize, void __iomem *cpuid_addr)
{
unsignedlong 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));
}
iotable_init内核提供,定义如下:
/*
* Create the architecturespecific mappings
*/
void __init iotable_init(structmap_desc *io_desc, int nr)
{
inti;
for(i = 0; i nr; i++)
create_mapping(io_desc+ i);
}
由上知道,smdkv210_map_io最终调用iotable_init建立映射表。
iotable_init函数的参数有两个:一个是map_desc类型的结构体,另一个是该结构体的数量nr。这里最关键的就是struct map_desc。map_desc结构体定义如下:
/*include/asm-arm/mach/map.h */
struct map_desc {
unsignedlong virtual;/*虚拟地址*/
unsignedlong pfn;/*物理页框地址,通过宏__phys_to_pfn(phy_addr)实现,即物理地址右移12位的方式*/
unsignedlong length;
unsignedint type;
};
create_mapping( )函数就是通过map_desc提供的信息创建线性映射表的。
这样的话我们就知道了创建I/O映射表的大致流程为:只要定义相应I/O资源的map_desc结构体,并将该结构体传给iotable_init函数执行,就可以创建相应的I/O资源到内核虚拟地址空间的映射表了。
我们来看看s5pv210是怎么定义map_desc结构体的(即上面iotable_init()函数内的s5p_iodesc)。
[arch/arm/plat-s5p]
/* minimal IO mapping */
static structmap_desc s5p_iodesc[] __initdata = {
{
.virtual = (unsigned long)S5P_VA_CHIPID,
.pfn = __phys_to_pfn(S5P_PA_CHIPID),
.length = SZ_4K,
.type = MT_DEVICE,
},{
.virtual = (unsigned long)S3C_VA_SYS,
.pfn = __phys_to_pfn(S5P_PA_SYSCON),
.length = SZ_64K,
.type = MT_DEVICE,
},{
.virtual = (unsigned long)S3C_VA_UART,
.pfn = __phys_to_pfn(S3C_PA_UART),
.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,
.pfn = __phys_to_pfn(S5P_PA_GPIO),
.length = SZ_4K,
.type = MT_DEVICE,
},
};
在s5p_init_io()函数中,除了iotable_init()以为,还会在最后调用,s3c_init_cpu
(cpu->map_io)(mach_desc, size);
而CPU的这个map_io在arch/arm/plat-s5p/cpu.c里面定义如下:
static struct cpu_table cpu_ids[] __initdata= {
{
.idcode = 0x56440100,
.idmask = 0xffffff00,
.map_io = s5p6440_map_io,
.init_clocks = s5p6440_init_clocks,
.init_uarts = s5p6440_init_uarts,
.init = s5p6440_init,
.name = name_s5p6440,
},{
.idcode = 0x36442000,
.idmask = 0xffffff00,
.map_io = s5p6442_map_io,
.init_clocks = s5p6442_init_clocks,
.init_uarts = s5p6442_init_uarts,
.init = s5p6442_init,
.name = name_s5p6442,
},{
.idcode = 0x43100000,
.idmask = 0xfffff000,
.map_io = s5pc100_map_io,
.init_clocks = s5pc100_init_clocks,
.init_uarts = s5pc100_init_uarts,
.init = s5pc100_init,
.name = name_s5pc100,
},{
.idcode = 0x43110000,
.idmask = 0xfffff000,
.map_io = s5pv210_map_io,/*cpu相关的映射*/
.init_clocks = s5pv210_init_clocks,
.init_uarts = s5pv210_init_uarts,
.init = s5pv210_init,
.name = name_s5pv210,
},
};
再查看s5pv210_map_io (),函数代码如下:
void __init s5pv210_map_io(void)
{
#ifdef CONFIG_S3C_DEV_ADC
s3c_device_adc.name = "s3c64xx-adc";
#endif
iotable_init(s5pv210_iodesc, ARRAY_SIZE(s5pv210_iodesc));
/*initialise device information early */
s5pv210_default_sdhci0();
s5pv210_default_sdhci1();
s5pv210_default_sdhci2();
/*the i2c devices are directly compatible with s3c2440 */
s3c_i2c0_setname("s3c2440-i2c");
s3c_i2c1_setname("s3c2440-i2c");
s3c_i2c2_setname("s3c2440-i2c");
}
接下来看结构s5pv210_iodesc [arch/arm/mach-s5pv20/cpu.c],代码如下,
/* Initial IO mappings */
static struct map_desc s5pv210_iodesc[]__initdata = {
{
.virtual = (unsigned long)S5P_VA_SYSTIMER,
.pfn = __phys_to_pfn(S5PV210_PA_SYSTIMER),
.length = SZ_1M,
.type = MT_DEVICE,
},{
.virtual = (unsigned long)VA_VIC2,
.pfn = __phys_to_pfn(S5PV210_PA_VIC2),
.length = SZ_16K,
.type = MT_DEVICE,
},{
.virtual = (unsigned long)VA_VIC3,
.pfn = __phys_to_pfn(S5PV210_PA_VIC3),
.length = SZ_16K,
.type = MT_DEVICE,
},{
.virtual = (unsigned long)S5P_VA_SROMC,
.pfn = __phys_to_pfn(S5PV210_PA_SROMC),
.length = SZ_4K,
.type = MT_DEVICE,
},{
.virtual = (unsigned long)S3C_VA_WATCHDOG,
.pfn = __phys_to_pfn(S5P_PA_WDT),
.length = SZ_4K,
.type = MT_DEVICE,
},{
.virtual = (unsigned long)S3C_VA_OTG,
.pfn = __phys_to_pfn(S5PV210_PA_OTG),
.length = SZ_1M,
.type = MT_DEVICE,
},{
.virtual = (unsigned long)S3C_VA_OTGSFR,
.pfn = __phys_to_pfn(S5PV210_PA_OTGSFR),
.length = SZ_1M,
.type = MT_DEVICE,
},
#if defined(CONFIG_HRT_RTC)
{
.virtual = (unsigned long)S5P_VA_RTC,
.pfn = __phys_to_pfn(S5PV210_PA_RTC),
.length = SZ_4K,
.type = MT_DEVICE,
},
#endif
{
.virtual = (unsigned long)S5P_VA_DMC0,
.pfn = __phys_to_pfn(S5P_PA_DMC0),
.length = SZ_4K,
.type = MT_DEVICE,
},{
.virtual = (unsigned long)S5P_VA_DMC1,
.pfn = __phys_to_pfn(S5P_PA_DMC1),
.length = SZ_4K,
.type = MT_DEVICE,
},{
.virtual = (unsigned long)S5P_VA_AUDSS,
.pfn = __phys_to_pfn(S5PV210_PA_AUDSS),
.length = SZ_1M,
.type = MT_DEVICE,
},{
.virtual = (unsigned long)S5P_VA_BUS_AXI_DSYS,
.pfn =__phys_to_pfn(S5PV210_PA_BUS_AXI_DSYS),
.length = SZ_4K,
.type = MT_DEVICE,
}
};
相关文章推荐
- ARM Linux静态映射分析
- 基于S3C2410-ARM-Linux静态映射分析
- ARM Linux静态映射分析
- Driver: ARM Linux静态映射分析
- ARM Linux静态映射分析
- ARM Linux静态映射分析
- 转载 ARM Linux静态映射分析
- 手动修改ARM Linux的静态IP和用QT获取和修改IP
- 嵌入式Linux之我行——s3c2440的IO静态映射的分析
- arm-Linux中断处理体系结构与处理流程分析
- 通过ssh连接开发板——arm-linux下ssh的移植
- Qt-5.3.2 在友善Smart210开发板的移植记录
- arm-linux内核start_kernel之前启动分析(3)-开启MMU,走进新时代
- 【原创】车载实时路况信息接收终端移植于Smart210开发板---步骤2之win下QT的安装和配置
- ARM-Linux驱动--DM9000网卡驱动分析(一) .
- ARM-Linux驱动--DM9000网卡驱动分析(四)
- 交叉编译场景分析(arm-linux)(二)--编译tslib
- 关于real210开发板linux系统可能无法解析域名的问题解决方法
- ARM Linux 中断分析
- 一个很难很难解决的问题:在linux下编译arm嵌入式的qt时加入opengl es1 选项就会编译不过