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_mask&r9,则说明支持这个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,
}
文章评论(0条评论)
登录后参与讨论