转自: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 {
   7:     };
   8:  
   9:     aliases {
  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:  
if (!of_aliases)
return;
  23:  
// 名字的结尾,*end是'\0'
struct device_node *np;
struct alias_prop *ap;
int id, len;
  30:  
/* 不处理名字是name、phandle、linux,phandle的属性 */
continue;
  36:  
value); 
/*
            i2c@13880000 {
                #address-cells = <0x1>;
                #size-cells = <0x0>;
                reg = <0x13880000 0x100>;
                interrupts = <0x0 0x3c 0x0>;
                clocks = <0x7 0x13f>;
                pinctrl-0 = <0x22>;
            };        
        */
if (!np)
continue;
  55:  
/* walk the alias backwards to extract the id and work out
         * the 'stem' string */
  59:             end--;
  61:  
// 将end指向的字符'2'转化为数字2,赋值给id
continue;
  64:  
/* Allocate an alias_prop with enough space for the stem */
if (!ap)
continue;
sizeof(*ap) + len + 1);
  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")

... ...

相关文章:

  • 2022-12-23
  • 2022-02-14
  • 2022-12-23
  • 2022-01-24
  • 2021-10-30
  • 2021-12-29
  • 2022-01-02
  • 2021-11-18
猜你喜欢
  • 2022-02-11
  • 2022-12-23
  • 2022-12-23
  • 2021-05-18
  • 2022-12-23
  • 2021-10-21
  • 2022-12-23
相关资源
相似解决方案