新旧内核的device设备注册对比

Posted aaronGao

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了新旧内核的device设备注册对比相关的知识,希望对你有一定的参考价值。

转自:http://blog.chinaunix.net/uid-7332782-id-3268801.html

 

1. Version2.6内核启动过程

    start_kernel( )  //板子上电启动后进入start_kernel( ),相当于程序的main入口

        -->setup_arch(&command_line)  //command_line由内核传入

            -->mdesc = setup_machine(machine_arch_type);

                -->list = lookup_machine_type(nr); //汇编实现查找机器码所定义的平台,找到后返回mdesc结构               

            -->init_machine = mdesc->init_machine;  //struct machine_desc *mdesc;machine_desc结构很重要,

        -->rest_init()

            -->kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND); //定义进程kernel_init,pid=1,在kthreadd进程创建好后调度运行          

                -->kernel_init()

                    -->do_basic_setup()

                        -->driver_init()

                            -->devices_init()

                            -->buses_init()

                            -->classes_init()

                            -->platform_bus_init()

                        -->do_initcalls()  //此函数很重要,执行了initcall表中所有的函数,包含了init_machine(saar_init())函数                       

                            -->saar_init()

                    -->init_post()    //调度用户空间程序,比如bash,在用户空间死循环执行程序                   

            -->pid = kernel_thread(kthreadd, NULL, CLONE_FS | CLONE_FILES);  //定义进程kthreadd

2. Version3.x内核启动过程和2.6版本在init_machine加载设备资源的差异对比

  • 在2.6内核中, 在setup_arch()中,举个例子imx5,

-->init_machine=mdesc->init_machine;  //init/main.c->start_kernel()->setup_arch()

  -->.init_machine=mxc_board_init;    //arch/arm/mach-mx5/mx50_arm2.c->MACHINE_START() ,宏即时初始化machine_desc结构体        

    -->mxc_register_device(&mxc_dma_device);  //arch/arm/mach-mx5/mx50_arm2.c->mxc_board_init()

    -->mxc_register_device(&mxc_wdt_device);  //mxc_wdt_device这些设备资源也都申明在mach-mx50下面

    -->mxc_register_device(&mxci2c_devices[0]);

    -->..........

当然在setup_arch()中对init_machine进行初始化,这个时候并没有调用init_machine函数,而是将init_machine属性定义为arch_initcall,然后在do_initcalls()中进行遍历调用,具体见上述的启动过程。

由上述可以看出,在系统启动时,device设备就已经register到总线上了,而3.x以后已经不在mach-**中申明设备资源了,那启动流程如何呢,见下一节。

  •  在3.x内核中,在setup_arch()是这么处理的, 首先解析dtb

-->setup_arch()  //init/main.c->start_kernel()->setup_arch()

  -->mdesc=setup_machine_fdt();

  -->unflatten_device_tree()

     -->__unflatten_device_tree()

        -->unflatten_dt_node()  //到此基本完成dts中node到链表的操作

节点中的设备注册(这儿也是在init_machine中完成,但是还没找到依据,并不像2.6中,init_machine有arch_initcall属性--解决:其实和2.6一样,在./arch/arm/kernel/setup.c中也是对init_machine添加arch_initcall属性。)

-->DT_MACHINE_START  //machine_desc结构体赋值

  -->.init_machine=imx6sx_init_machine

     -->of_platform_populate();   //imx6sx_init_machine()调用

        -->of_platform_bus_create();   //由for_each_child_of_node()调用,遍历device tree中每个节点

           -->of_platform_device_create_pdata()

              -->of_device_alloc()    //为每个device申请空间

              -->platform_device_put()

           -->of_platform_bus_create()

到此完成设备的注册。

在3.x的setup.c中关于init_machine的调用是这么定义的

 1 static int __init customize_machine(void)
 2 {
 3     /*
 4      * customizes platform devices, or adds new ones
 5      * On DT based machines, we fall back to populating the
 6      * machine from the device tree, if no callback is provided,
 7      * otherwise we would always need an init_machine callback.
 8      */
 9     if (machine_desc->init_machine)
10         machine_desc->init_machine();
11 #ifdef CONFIG_OF
12     else
13         of_platform_populate(NULL, of_default_bus_match_table,
14                     NULL, NULL);
15 #endif
16     return 0;
17 }

 

关于init_machine到底会不会被执行,在Documentation/Devicetree/usage-model.txt中有这么一段话

The most interesting hook in the DT context is .init_machine() which
is primarily responsible for populating the Linux device model with
data about the platform.  Historically this has been implemented on
embedded platforms by defining a set of static clock structures,
platform_devices, and other data in the board support .c file, and
registering it en-masse in .init_machine().  When DT is used, then
instead of hard coding static devices for each platform, the list of
devices can be obtained by parsing the DT, and allocating device
structures dynamically.

The simplest case is when .init_machine() is only responsible for
registering a block of platform_devices.  A platform_device is a concept
used by Linux for memory or I/O mapped devices which cannot be detected
by hardware, and for composite or virtual devices (more on those
later).  While there is no platform device terminology for the DT,
platform devices roughly correspond to device nodes at the root of the
tree and children of simple memory mapped bus nodes.

 

以上是关于新旧内核的device设备注册对比的主要内容,如果未能解决你的问题,请参考以下文章

linux platform device/driver--Platform Device和Platform_driver注册过程之代码对比

Platform device/driver注册过程 (转)

16 内核中注册设备

RK3399平台开发系列讲解(内核设备树篇)3.6device_node与device绑定流程

RK3399平台开发系列讲解(内核设备树篇)3.6device_node与device绑定流程

Embeded linux之probe