zoukankan      html  css  js  c++  java
  • 设备树DTS 学习:Linux DTS文件加载过程

    背景

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

    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平台所以存在archarmkernelsetup.c中

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

    setup_arch函数在kernel启动是被调用,如下启动kernel存在initmain.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在kerneldriverofplatform.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会最终调用到kerneldriverofase.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节点的树结构,去寻找该总线的子节点,所有的子节点将被作为设备注册到该总线上。

  • 相关阅读:
    easy ui 表单ajax和from两种提交数据方法
    easy ui 下拉级联效果 ,下拉框绑定数据select控件
    easy ui 下拉框绑定数据select控件
    easy ui 异步上传文件,跨域
    easy ui 菜单和按钮(Menu and Button)
    HTTP 错误 404.3
    EXTJS4.2 后台管理菜单栏
    HTML 背景图片自适应
    easy ui 表单元素input控件后面加说明(红色)
    EXTJS 4.2 添加滚动条
  • 原文地址:https://www.cnblogs.com/schips/p/12298318.html
Copyright © 2011-2022 走看看