【linux】具体芯片MACHINE_START处理

时间:2021-07-05 09:11:19

欢迎转载,转载时需保留作者信息,谢谢。

邮箱:tangzhongp@163.com

博客园地址:http://www.cnblogs.com/embedded-tzp

Csdn博客地址:http://blog.csdn.net/xiayulewa

 

MACHINE_START定义了一个具体机器。Linux已经定义好了调用接口,只需要实现MACHINE_START中的成员即可。

 

Mach-mini2440.c (src\arch\arm\mach-s3c24xx)  中定义:

 

MACHINE_START(MINI2440, "MINI2440")

    /* Maintainer: Michel Pollet <buserror@gmail.com> */

    .atag_offset    = 0x100,

    .map_io     = mini2440_map_io,

    .init_machine   = mini2440_init,

    .init_irq   = s3c2440_init_irq,

    .init_time  = samsung_timer_init,

    .restart    = s3c244x_restart,

MACHINE_END

 

#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             \

};

可见编译后放置在段.arch.info.init中。

 

struct machine_desc成员的处理流程

 

Ø  init_machine:

start_kernel→rest_init→kernel_init→kernel_init_freeable→do_basic_setup→do_initcalls

 

static initcall_t *initcall_levels[] __initdata = {

    __initcall0_start,  /* 在src\arch\arm\kernel\vmlinux.lds中定义__initcall0_start = .; *(.initcall0.init) *(.initcall0s.init) */

    __initcall1_start, /* 在src\arch\arm\kernel\vmlinux.lds中定义*/

    __initcall2_start, /* 同上*/

    __initcall3_start, /* 同上*/

    __initcall4_start, /* 同上*/

    __initcall5_start, /* 同上*/

    __initcall6_start, /* 同上*/

    __initcall7_start, /* 同上*/

    __initcall_end, /* 同上*/

};

 

static void __init do_initcalls(void)

{

    int level;

 

    for (level = 0; level < ARRAY_SIZE(initcall_levels) - 1; level++)

        do_initcall_level(level);

}

 

因此do_initcalls函数会执行所有的在src\arch\arm\kernel\vmlinux.lds中定义的__initcall0_start与_initcall_end之间的段。

 

Setup.c (src\arch\arm\kernel)中有:

 

static int __init customize_machine(void)

{

    /*

     * customizes platform devices, or adds new ones

     * On DT based machines, we fall back to populating the

     * machine from the device tree, if no callback is provided,

     * otherwise we would always need an init_machine callback.

     */

    if (machine_desc->init_machine)

        machine_desc->init_machine();

#ifdef CONFIG_OF

    else

        of_platform_populate(NULL, of_default_bus_match_table,

                    NULL, NULL);

#endif

    return 0;

}

arch_initcall(customize_machine);

 

而Init.h (src\include\linux)中有:

#define arch_initcall(fn)       __define_initcall(fn, 3)

 

#define __define_initcall(fn, id) \

    static initcall_t __initcall_##fn##id __used \

__attribute__((__section__(".initcall" #id ".init"))) = fn

 

最后得到函数customize_machine被分配到了__initcall0_start与_initcall_end之间的段.initcall3.init.

 

总结:整个流程为: start_kernel→rest_init→kernel_init→kernel_init_freeable→do_basic_setup→do_initcalls→

customize_machine→machine_desc->init_machine()MACHINE_START宏定义的.init_machine   = mini2440_init

 

Ø  map_io:

setup_arch→paging_init→devicemaps_init→ mdesc->map_io();MACHINE_START宏定义的.map_io     = mini2440_map_io;

 

Ø  init_irq:

 

start_kernel→init_IRQ→init_irq→machine_desc->init_irq()即

MACHINE_START宏定义的.init_irq   = s3c2440_init_irq;

 

Ø  init_time:

start_kernel→time_init→machine_desc->init_time()即

MACHINE_START宏定义的.init_time  = samsung_timer_init;