【linux】具體芯片MACHINE_START處理

歡迎轉載,轉載時需保留做者信息,謝謝。linux

郵箱:tangzhongp@163.comide

博客園地址:http://www.cnblogs.com/embedded-tzp函數

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

 

MACHINE_START定義了一個具體機器。Linux已經定義好了調用接口,只須要實現MACHINE_START中的成員便可。.net

 

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

 

MACHINE_START(MINI2440, "MINI2440")orm

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

    .atag_offset    = 0x100,接口

    .map_io     = mini2440_map_io,ci

    .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_machinemachine_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_irqmachine_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

相關文章
相關標籤/搜索