转自:https://blog.csdn.net/qq_30145093/article/details/78053823?locationNum=10&fps=1

转自http://www.cnblogs.com/pengdonglin137/p/5252348.html

在设备树中有一个叫做aliases的节点:

   1: / {
   2:     ... ...
   3:  
   4:     chosen {
   5:         stdout-path = "/serial@13800000";
   6:         bootargs = "root=/dev/ram0 rw rootfstype=ext4 console=ttySAC0,115200 ethmac=1C:6F:65:34:51:7E init=/linuxrc";
   7:     };
   8:  
   9:     aliases {
  10:         spi0 = "/spi@13920000";
  11:         spi1 = "/spi@13930000";
  12:         spi2 = "/spi@13940000";
  13:         i2c0 = "/i2c@13860000";
  14:         i2c1 = "/i2c@13870000";
  15:         i2c2 = "/i2c@13880000";
  16:         i2c3 = "/i2c@13890000";
  17:         ... ...
  18:     };
  19: ... ...
  20: };

在Linux内核启动的时候会解析这个节点:

start_kernel
    ---> setup_arch
            ---> unflatten_device_tree
                    ---> of_alias_scan

在of_alias_scan中会扫描这个节点:

of_alias_scan:

   1: void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align))
   2: {
   3:     struct property *pp;
   4:  
   5:     of_aliases = of_find_node_by_path("/aliases"); // 找到/aliases节点对应的device_node
   6:     of_chosen = of_find_node_by_path("/chosen"); // 找到/chosen节点对应的device_node
   7:     if (of_chosen == NULL) // 如果没有/chosen的话,就找/chosen@0节点
   8:         of_chosen = of_find_node_by_path("/chosen@0");
   9:  
  10:     if (of_chosen) {
  11:         /* linux,stdout-path and /aliases/stdout are for legacy compatibility */
  12:         const char *name = of_get_property(of_chosen, "stdout-path", NULL);
  13:         if (!name)
  14:             name = of_get_property(of_chosen, "linux,stdout-path", NULL);
  15:         if (IS_ENABLED(CONFIG_PPC) && !name)
  16:             name = of_get_property(of_aliases, "stdout", NULL);
  17:         if (name)
  18:             of_stdout = of_find_node_opts_by_path(name, &of_stdout_options);
  19:     }
  20:  
  21:     if (!of_aliases)
  22:         return;
  23:  
  24:     for_each_property_of_node(of_aliases, pp) { // 遍历/aliases节点的属性,以属性i2c2 = "/i2c@13880000";为例
  25:         const char *start = pp->name; // 属性的名字,如"i2c2"
  26:         const char *end = start + strlen(start); // 名字的结尾,*end是'\0'
  27:         struct device_node *np;
  28:         struct alias_prop *ap;
  29:         int id, len;
  30:  
  31:         /* 不处理名字是name、phandle、linux,phandle的属性 */
  32:         if (!strcmp(pp->name, "name") || 
  33:             !strcmp(pp->name, "phandle") ||
  34:             !strcmp(pp->name, "linux,phandle"))
  35:             continue;
  36:  
  37:         np = of_find_node_by_path(pp->value); 
  38:         /*
  39:             根据属性的值(如"/i2c@13880000")获得这个值对应的节点
  40:             i2c@13880000 {
  41:                 #address-cells = <0x1>;
  42:                 #size-cells = <0x0>;
  43:                 compatible = "samsung,s3c2440-i2c";
  44:                 reg = <0x13880000 0x100>;
  45:                 interrupts = <0x0 0x3c 0x0>;
  46:                 clocks = <0x7 0x13f>;
  47:                 clock-names = "i2c";
  48:                 pinctrl-names = "default";
  49:                 pinctrl-0 = <0x22>;
  50:                 status = "disabled";
  51:             };        
  52:         */
  53:         if (!np)
  54:             continue;
  55:  
  56:         /* walk the alias backwards to extract the id and work out
  57:          * the 'stem' string */
  58:         while (isdigit(*(end-1)) && end > start) //对于"i2c2",end最终会指向字符'2'的地址
  59:             end--;
  60:         len = end - start; // 获得"i2c"的长度(不包含结尾的数字2),就是3
  61:  
  62:         if (kstrtoint(end, 10, &id) < 0) // 将end指向的字符'2'转化为数字2,赋值给id
  63:             continue;
  64:  
  65:         /* Allocate an alias_prop with enough space for the stem */
  66:         ap = dt_alloc(sizeof(*ap) + len + 1, 4); // 分配内存,多分配的"len+1"用于存放stem的名字
  67:         if (!ap)
  68:             continue;
  69:         memset(ap, 0, sizeof(*ap) + len + 1);
  70:         ap->alias = start; // ap->alias指向字符串"i2c2"
  71:         of_alias_add(ap, np, id, start, len);
  72:     }
  73: }

of_alias_add:

   1: static void of_alias_add(struct alias_prop *ap, struct device_node *np,
   2:              int id, const char *stem, int stem_len)
   3: {
   4:     ap->np = np; // np是"/i2c@13880000"对应的节点device_node
   5:     ap->id = id; // id的值是2
   6:     strncpy(ap->stem, stem, stem_len); // 由于stem_len是3,所以ap->stem被赋值为"i2c"
   7:     ap->stem[stem_len] = 0;
   8:     list_add_tail(&ap->link, &aliases_lookup); // 将这个ap加入到全局aliases_lookup链表中
   9:     pr_debug("adding DT alias:%s: stem=%s id=%i node=%s\n",
  10:          ap->alias, ap->stem, ap->id, of_node_full_name(np));
  11: }

使用:

在drivers/i2c/i2c-core.c中:

   1: int i2c_add_adapter(struct i2c_adapter *adapter)
   2: {
   3:     struct device *dev = &adapter->dev;
   4:     int id;
   5:  
   6:     if (dev->of_node) {
   7:         id = of_alias_get_id(dev->of_node, "i2c");
   8:         if (id >= 0) {
   9:             adapter->nr = id;
  10:             return __i2c_add_numbered_adapter(adapter);
  11:         }
  12:     }
  13:     ... ...
  14: }

第7行调用of_alias_get_id获得与这个device_node(即/i2c@13880000节点)对应的alias_prop的id,如果以/i2c@13880000节点为例,这里得到的id就是2。

of_alias_get_id:

   1: int of_alias_get_id(struct device_node *np, const char *stem)
   2: {
   3:     struct alias_prop *app;
   4:     int id = -ENODEV;
   5:  
   6:     mutex_lock(&of_mutex);
   7:     list_for_each_entry(app, &aliases_lookup, link) { // 遍历全局链表aliases_lookup
   8:         if (strcmp(app->stem, stem) != 0) // 找到 stem 是 "i2c" 的alias_prop
   9:             continue;
  10:  
  11:         if (np == app->np) { // 判断这个alias_prop指向的device_node是不是跟传入的匹配
  12:             id = app->id;  // 获得 id,2
  13:             break;
  14:         }
  15:     }
  16:     mutex_unlock(&of_mutex);
  17:  
  18:     return id;
  19: }

從上面的分析就可以知道alias節點的作用了:

比如SoC上有如果多個i2c控制器,alias的相當於給每個i2c控制器分配一個唯一的編號,如上面的i2c@13880000對應的alias是i2c2,那麼這個編號就是2,將來就可以在/dev下看到名爲i2c-2的設備節點。

在內核中可以看到很多地方都會調用of_alias_get_id,他的作用就是根據傳入的device node,在alias中找到對應的唯一編號,如:

of_alias_get_id(pdev->dev.of_node, "spi")

of_alias_get_id(node, "fimc")

of_alias_get_id(pdev->dev.of_node, "serial")

of_alias_get_id(pdev->dev.of_node, "uart")

of_alias_get_id(dev->of_node, "gpio")

... ...

of_alias_get_id 函数与设备树中aliases节点的关系【转】的更多相关文章

  1. linux 设备树中 dwc3 节点的phys参数含义

    找了好久今天找到了,记录一下: &dwc3_0 { ... phys = <&lane3 PHY_TYPE_USB3 1 2 26000000>; ... } Requir ...

  2. linux 设备树及节点引用【转】

    本文转载自:http://blog.csdn.net/KjfureOne/article/details/51972854 1.ARM Linux社区为什么要引入设备树 Linux之父Linus To ...

  3. 基于tiny4412的Linux内核移植 --- aliases节点解析

    作者信息 作者: 彭东林 邮箱:pengdonglin137@163.com QQ:405728433 平台简介 开发板:tiny4412ADK + S700 + 4GB Flash 要移植的内核版本 ...

  4. 基于tiny4412的Linux内核移植 --- aliases节点解析【转】

    转自:https://www.cnblogs.com/pengdonglin137/p/5252348.html 阅读目录(Content) 作者信息 平台简介 正文 回到顶部(go to top) ...

  5. 设备树中ranges属性分析(1)

    作者 彭东林 pengdonglin137@163.com   软件环境 Linux-4.10.17 Qemu+vexpress   概述 在设备树中有时会看到ranges属性,这个ranges属性可 ...

  6. 【u-boot】u-boot对设备树的节点解析(转)

    1,设备树的引入2,uboot本身对设备树的支持3,对uboot中设备树节点解析代码的分析 (1)上一篇文章中提到函数 dm_init_and_scan(bool pre_reloc_only) 中有 ...

  7. 利用函数来得到所有子节点号& 利用函数来取得最高级的节点号

    在Oracle 中我们知道有一个 Hierarchical Queries 通过CONNECT BY 我们可以方便的查了所有当前节点下的所有子节点.但很遗憾,在MySQL的目前版本中还没有对应的功能. ...

  8. C语言:根据形参c中指定的英文字母,按顺序打印出若干后继相邻字母,-主函数中放入一个带头节点的链表结构中,h指向链表的头节点。fun函数找出学生的最高分-使用插入排序法对字符串中的字符进行升序排序。-从文件中找到指定学号的学生数据,读入次学生数据,

    //根据形参c中指定的英文字母,按顺序打印出若干后继相邻字母,输出字母的大小与形参c一致,数量由形参d指定.例如:输入c为Y,d为4,则输出ZABC. #include <stdio.h> ...

  9. Java实现 LeetCode 450 删除二叉搜索树中的节点

    450. 删除二叉搜索树中的节点 给定一个二叉搜索树的根节点 root 和一个值 key,删除二叉搜索树中的 key 对应的节点,并保证二叉搜索树的性质不变.返回二叉搜索树(有可能被更新)的根节点的引 ...

随机推荐

  1. 分布式系统之消息中间件rabbitmq

    分布式系统之消息中间件rabbitmq 博客分类: 感谢:  一般php 用rabbitmq  java 用activemq  http://spartan1.iteye.com/blog/11802 ...

  2. Spring邮件发送2

    前言:上一篇博文讲解了邮件发送的基础用法(数据是写死的),然而在实际开发中,大多数情况下邮件内容都是根据业务来动态生成的.所以在此篇博文中,我们将讲解邮件发送携带数据的几种方案. 一.解析自定义占位符 ...

  3. 记一次oracle crs无法重启事故

    今天在修改了数据库参数后,关闭数据库及crs,然后重新启动了服务器,服务器启动完成之后,发现数据库无法启动,过程如下: step1:重启数据库 $ su - grid $ srvctl stop da ...

  4. "双非"应届生校招如何获得大厂青睐?(内附技术岗超全求职攻略)

    写在前面的话 笔者从17年的2月份开始准备春招,其中遇到不少坑,也意识到自己走过的弯路.故写了这篇文章总结一番,本文适合主动学习的,对自己要学的课程不明确的,对面试有恐惧症的...等将来打算从事技术岗 ...

  5. Error creating document instance. Cause: org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 1; 前言中不允许有内容。

    Error creating document instance. Cause: org.xml.sax.SAXParseException;  lineNumber: 1; columnNumber ...

  6. Linux后台运行命令 nohup command > myout.file 2>&1

    Linux命令后台运行 转自北国的雨,谢谢:http://www.cnblogs.com/lwm-1988/archive/2011/08/20/2147299.html 有两种方式:1. comma ...

  7. JavaScript利用数组原型,添加方法实现遍历多维数组每一个元素

    原型就是提供给我们为了让我们扩展更多功能的. 今天学习了用js模拟底层代码,实现数组多维的遍历.思想是在数组原型上添加一个方法. // js中的数组forEach方法,传入回掉函数 能够帮助我们遍历数 ...

  8. java Servlet文件拷贝的模板代码

    //通过response对象获得一个输出流对象 ServletOutputStream os = response.getOutputStream(); //获得要拷贝文件的绝对路径 String r ...

  9. @OnetoOne @OnetoMany @ManyToOne(2)

    在班主任(id,name,bjid) 班级(id name) 学生(id name bjid)的 关系中 班主任一对一关联班级 班级一对多关联学生 @OnetoOne @joinColumn(bjid ...

  10. 0312-css样式(选择器、文本text、字体fonts、背景background)

    问题: 1.css中table{border:1px:}是定义table的样式,只有表格的外边框,不能实现<table border="1"></table> ...