(三)从解析DTS到创建device_从device_node到并入设备驱动模型(结合源码)

从device_node到并入设备驱动模型

此篇博客有很多参考其他文章的内容,由于参考内容繁杂,不一一标注角标了,在末尾会贴上所有参考博客的link,如有侵权,请联系本人处理,谢谢。

深入,并且广泛
					 -沉默犀牛

上一篇文章已经详细的分析了两个问题:
1.如何根据Device Tree的信息,找到最适合的machine_desc
2.如何将DTB转换成节点是device_node的树状结构

那么为什么要做这两件事情呢?

我们现在要做的事情是把DTS中描述的节点(status = okay的)注册到kernel中,DTS的信息我们的kernel没法直接识别啊,就得通过上述的2把DTS中描述的每一个节点,转换成device_node结构体,我们可以认为DTS中写的每一个节点在这里都被解析为一个device_node。(该结构体中有parent、child、sibling成员,通过这些成员把device_node给连接成了树状结构)好,现在我们有了完全代表了DTS信息,又能被kernel识别的device_node,现在就要把这些device_node一个个的创建起来(比如有的device_node要注册到platform总线上,有的要注册到i2c总线…),这个创建的过程,就需要我们上述1中的machine_desc了!在定义machine_desc结构体的时候,会定义一个回调函数:xxxx_init(大部分情况)就是这个xxxx_init把device_node都注册起来。

再补充上面一段话的三个点
1.xxxx_init函数只是注册了platform总线上的device_node,那其他的呢?比如i2c上的device呢?在注册i2c总线时,调用qup_i2c_probe(),这个接口会添加i2c适配器,适配器添加完成后会调用of_i2c_register_devices()接口来i2c总线节点的子节点,然后调用i2c_new_device(),生成i2c设备。

2.我在定义回调函数后面写了个大部分情况,也就代表有的时候不会定义这个回调函数,那么kernel怎么注册device_node呢?事实上kernel会检测machine_desc有没有init函数,如果有,则调用;如果没有,则调用of提供的接口直接注册所有platform的device,这里就有一个问题了:这个machine_desc如果没有定义init函数,那我还要它干嘛呢?我去看(根据DTS选择最适配的machine_desc)那一段代码时发现,如果没有找到合适的machine_desc的话,有一行注释:does not return! 这似乎意味着,找不到合适的machine_desc也没啥关系,kernel还是会继续运行下去,platform上的device还是可以注册上。如果这一点的理解有误,请留言纠正,大恩不言谢!

3.DTS中的节点都转换成了device_node,但是DTS中描述的节点并不都是device啊,比如cpus node,memory node,choose node等。对于这些节点的处理,我会在下一篇文章中说明。

经过前面的介绍和解释,我们明确了这一篇文章的主题:
那些platform总线下的device_node如何注册到platform总线上的?

执行流程

进入kernel的入口后,会按照如下的调用流程start_kernel->rest_init->kernel_init->kernel_init_freeable->
do_basic_setup->do_initcallsdo_initcalls函数中,在do_initcalls函数中,kernel会依次执行各个initcall函数。

代码验证

在上述的调用流程中,会调用到调用customize_machine,也正是这个函数,检测了machine_desc是否有xxxx_init函数,代码如下:

static int __init customize_machine(void)
{
   

    if (machine_desc->init_machine)  //如果有init_machine()函数,则执行
        machine_desc->init_machine();
    else  //否则直接调用of提供的接口来注册device
        of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);

    return 0;
}
arch_initcall(customize_machine); 

以高通msm8953为例,看看它有没有定义init_machine函数:

DT_MACHINE_START(MSM8953_DT,
	"Qualcomm Technologies, Inc. MSM8953 (Flattened Device Tree)")
	.init_machine		= msm8953_init,    //这里定义了init函数
	.dt_compat		= msm8953_dt_match,    //这个参数就是之前匹配machine_desc用的
						       //这个参数将于DTS中的compatible属性值来比较
MACHINE_END

再看看这个函数的内容:

static void __init msm8953_init(void
  • 5
    点赞
  • 44
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值