热度 16
2013-9-8 16:30
1871 次阅读|
0 个评论
linux从协处理器P15的C0寄存器读出CPU ID 给r9,然后在proc_info_list这个段中查找(proc_info_list这个结构体在arch/arm/include/asm/procinfo.h中定义),看是否有对应的CPUid,这个段里面包含了所有支持的cpu的proc_info结构体。比如s3c2410对应的结构体在arch/arm/mm/proc_arm920.s,这个文件定义了一个__arm920_proc_info。结构体第一个数据位cpu_val,第二个为cpu_mask,如果cpu_val=cpu_maskr9,则说明支持这个cpu。 struct proc_info_list { unsigned int cpu_val; unsigned int cpu_mask; unsigned long __cpu_mm_mmu_flags; /* used by head.S */ unsigned long __cpu_io_mmu_flags; /* used by head.S */ unsigned long __cpu_flush; /* used by head.S */ const char *arch_name; const char *elf_name; unsigned int elf_hwcap; const char *cpu_name; struct processor *proc; struct cpu_tlb_fns *tlb; struct cpu_user_fns *user; struct cpu_cache_fns *cache; }; 每个cpu也会定义一个和他一样的结构体,并且给他赋值。这些结构体都被存放在proc_info_list这个段,比如在arch/arm/mm/proc_arm920.s里面有如下结构体: __arm920_proc_info: .long 0x41009200 .long 0xff00fff0 .long PMD_TYPE_SECT | \ PMD_SECT_BUFFERABLE | \ PMD_SECT_CACHEABLE | \ PMD_BIT4 | \ PMD_SECT_AP_WRITE | \ PMD_SECT_AP_READ .long PMD_TYPE_SECT | \ PMD_BIT4 | \ PMD_SECT_AP_WRITE | \ PMD_SECT_AP_READ b __arm920_setup .long cpu_arch_name .long cpu_elf_name .long HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB .long cpu_arm920_name .long arm920_processor_functions .long v4wbi_tlb_fns .long v4wb_user_fns cpu_arch_name这些东西在同一个文件里有如下定义,就是他们的初值。 cpu_arch_name: .asciz "armv4t"//初值 .size cpu_arch_name, . - cpu_arch_name//还不知道size的用法??? .type cpu_elf_name, #object//说明这是一个对象 cpu_elf_name: .asciz "v4" .size cpu_elf_name, . - cpu_elf_name .type cpu_arm920_name, #object cpu_arm920_name: .asciz "ARM920T" .size cpu_arm920_name, . - cpu_arm920_name .align .section ".proc.info.init", #alloc, #execinstr .type __arm920_proc_info,#object /***********************************************************************************/ 在arch/arm/include/asm/mach/arch.h下有machine_desc结构体,这个结构体保存了board的一些信息,linux程序会从这个段中查找对应的板子ID, struct machine_desc { unsigned int nr; /* architecture number */ const char *name; /* architecture name */ unsigned long boot_params; /* tagged list */ const char **dt_compat; /* array of device tree * 'compatible' strings */ unsigned int nr_irqs; /* number of IRQs */ unsigned int video_start; /* start of video RAM */ unsigned int video_end; /* end of video RAM */ unsigned int reserve_lp0 :1; /* never has lp0 */ unsigned int reserve_lp1 :1; /* never has lp1 */ unsigned int reserve_lp2 :1; /* never has lp2 */ unsigned int soft_reboot :1; /* soft reboot */ void (*fixup)(struct machine_desc *, struct tag *, char **, struct meminfo *); void (*reserve)(void);/* reserve mem blocks */ void (*map_io)(void);/* IO mapping function */ void (*init_early)(void); void (*init_irq)(void); struct sys_timer *timer; /* system tick timer */ void (*init_machine)(void); #ifdef CONFIG_MULTI_IRQ_HANDLER void (*handle_irq)(struct pt_regs *); #endif }; 在arch/arm/mach-s3c64XX中定义了一个结构体: MACHINE_START(SMDK6410, "SMDK6410") /* Maintainer: Ben Dooks ben-linux@fluff.org */ //.phys_io = S3C_PA_UART 0xfff00000, //.io_pg_offst = (((u32)S3C_VA_UART) 18) 0xfffc, .boot_params = S3C64XX_PA_SDRAM + 0x100, .init_irq = s3c6410_init_irq, .map_io = smdk6410_map_io, .init_machine = smdk6410_machine_init, .timer = s3c24xx_timer, MACHINE_END 然后在arch/arm/include/asm/mach/arch.h中有machine_start的宏定义, #define MACHINE_START(_type,_name) \ static const struct machine_desc __mach_desc_##_type \ __used \ __attribute__((__section__(".arch.info.init"))) = { \ .nr = MACH_TYPE_##_type, \ .name = _name, #define MACHINE_END \ }; 两个程序解释开就是定义了一个machine_desc类型的变量mach_desc_smdk6410,并且赋值。最后指定这个结构体添加到.arch.info.init中去(大体上就是这个样子)。下面这些是移植linux很重要的东西,它指定了linux到板子的映射函数。根据具体的情况,可能要修改函数里面一些信息。 machine_desc mach_desc_smdk6410{ .nr = MACH_TYPE_SMDK6410,//板子ID号,这个宏在其他地方定义 .name = _name,//板子名字 //.phys_io = S3C_PA_UART 0xfff00000, //.io_pg_offst = (((u32)S3C_VA_UART) 18) 0xfffc, .boot_params = S3C64XX_PA_SDRAM + 0x100, .init_irq = s3c6410_init_irq, .map_io = smdk6410_map_io, .init_machine = smdk6410_machine_init, .timer = s3c24xx_timer, }