码迷,mamicode.com
首页 > 系统相关 > 详细

设备树DTS 学习:Linux DTS文件加载过程

时间:2020-02-12 12:56:02      阅读:120      评论:0      收藏:0      [点我收藏+]

标签:bash   params   default   wget   module   creating   fir   devices   平台总线   

背景

了解机制有利于对内核有更深的认识。

wget https://mirrors.aliyun.com/linux-kernel/v3.x/linux-3.2.61.tar.xz

内核

  1. 在drivers/of/fdt.c 中有如下初始化函数 注释上:展开设备树,创建device_nodes到全局变量allnodes中

    Linux不同内核版本的 fdt.c 文件在不同的地方,使用 find | grep fdt.c 进行查找

/**
 * unflatten_device_tree - create tree of device_nodes from flat blob
 *
 * unflattens the device-tree passed by the firmware, creating the
 * tree of struct device_node. It also fills the "name" and "type"
 * pointers of the nodes so the normal device-tree walking functions
 * can be used.
 */

void __init unflatten_device_tree(void)
{
    __unflatten_device_tree(initial_boot_params, &allnodes,
                early_init_dt_alloc_memory_arch);

    /* Get pointer to "/chosen" and "/aliasas" nodes for use everywhere */
    of_alias_scan(early_init_dt_alloc_memory_arch);
}

unflatten_device_tree函数被setup_arch函数调用,因为我们使用的是arm平台所以存在arch\arm\kernel\setup.c中

void __init setup_arch(char **cmdline_p)
{
    ...
    unflatten_device_tree();
}

setup_arch函数在kernel启动是被调用,如下启动kernel存在init\main.c

asmlinkage void __init start_kernel(void)
{
    ...
    setup_arch(&command_line);
    ...
}

这些工作完成解析DTS文件。保存到全局链表allnodes中。

2、在arch/arm/boot/Makefile中有这段话来编译dts文件:

$(obj)/A20%.dtb: $(src)/dts/A20%.dts FORCE
    $(call if_changed_dep,dtc)

$(obj)/A68M%.dtb: $(src)/dts/A68M%.dts FORCE
    $(call if_changed_dep,dtc)

3、
在 board-8226.c中有初始化函数-->启动自动掉用
void __init msm8226_init(void)
{
of_platform_populate(NULL, of_default_bus_match_table, adata, NULL);
}

of_platform_populate在kernel\driver\of\platform.c中定义,回查询

root = root ? of_node_get(root) : of_find_node_by_path("/");
for_each_child_of_node(root, child)
    {
    rc = of_platform_bus_create(child, matches, lookup, parent, true);
    if (rc)
        break;
}
of_node_put(root);

在这里用到得函数of_find_node_by_path会最终调用到kernel\driver\of\base.c中得函数
struct device_node of_find_node_by_path(const char path)
{
遍历第1步中得allnodes找到根节点
}

of_platform_bus_create()函数中创建得内容存在了 adata中。

(2)使用DTS注册总线设备的过程
以高通8974平台为例,在注册i2c总线时,会调用到qup_i2c_probe()接口,该接口用于申请总线资源和添加i2c适配器。在成功添加i2c适配器后,会调用of_i2c_register_devices()接口。此接口会解析i2c总线节点的子节点(挂载在该总线上的i2c设备节点),获取i2c设备的地址、中断号等硬件信息。然后调用request_module()加载设备对应的驱动文件,调用i2c_new_device(),生成i2c设备。此时设备和驱动都已加载,于是drvier里面的probe方法将被调用。后面流程就和之前一样了。
简而言之,Linux采用DTS描述设备硬件信息后,省去了大量板文件垃圾信息。Linux在开机启动阶段,会解析DTS文件,保存到全局链表allnodes中,在掉用.init_machine时,会跟据allnodes中的信息注册平台总线和设备。值得注意的是,加载流程并不是按找从树根到树叶的方式递归注册,而是只注册根节点下的第一级子节点,第二级及之后的子节点暂不注册。Linux系统下的设备大多都是挂载在平台总线下的,因此在平台总线被注册后,会根据allnodes节点的树结构,去寻找该总线的子节点,所有的子节点将被作为设备注册到该总线上。

设备树DTS 学习:Linux DTS文件加载过程

标签:bash   params   default   wget   module   creating   fir   devices   平台总线   

原文地址:https://www.cnblogs.com/schips/p/12298318.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!