首页 > 其他分享 >设备树 aliases

设备树 aliases

时间:2023-04-08 21:57:36浏览次数:28  
标签:node i2c ap stem alias aliases id 设备

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

 / {
    #address-cells = <1>;
    #size-cells = <1>;
 
    aliases {
        fimc0 = &fimc0;
        fimc1 = &fimc1;
        fimc2 = &fimc2;     
        i2c0 = &i2c0;
        i2c1 = &i2c1;
        i2c2 = &i2c2;
           ······
    };
    
    ......
};

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

start_kernel
    setup_arch
        unflatten_device_tree
            of_alias_scan
void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align))
{
    struct property *pp;
 
    /* 找到/aliases节点对应的device_node */
    of_aliases = of_find_node_by_path("/aliases");
 
    /*  找到/chosen节点对应的device_node */
    of_chosen = of_find_node_by_path("/chosen");
 
    /* 如果没有/chosen的话,就找/chosen@0节点 */
    if (of_chosen == NULL)
        of_chosen = of_find_node_by_path("/chosen@0");
 
    /* 遍历/aliases节点的属性 */
    for_each_property_of_node(of_aliases, pp) {
        const char *start = pp->name;            // 属性的名字
        const char *end = start + strlen(start); // 名字的结尾,*end是'\0'
        struct device_node *np;
        struct alias_prop *ap;
        int id, len;
 
        /* Skip those we do not want to proceed */
        /* 忽略名字是name、phandle、linux,phandle的属性 */
        if (!strcmp(pp->name, "name") ||
            !strcmp(pp->name, "phandle") ||
            !strcmp(pp->name, "linux,phandle"))
            continue;
 
        /* 根据属性的值获得这个值对应的节点 */
        /* 比如这个这个属性,fimc2 = "/soc/camera/fimc@fb400000"通过路径来找到节点 */
        np = of_find_node_by_path(pp->value);
        if (!np)
            continue;
 
        /* 正常一个属性名字是fimc1,i2c0,这样,这里是把end指针指向数字前面那一个位置,
         * 比如fimc2的c字符的地址 */
        while (isdigit(*(end-1)) && end > start)
            end--;
        len = end - start;    /* 这个len就是名字除去数字的长度 */
 
        /* 把end字符串后面的数字,由字符串转换成数字复制给id,比如fimc2的,数子2 */
        if (kstrtoint(end, 10, &id) < 0)        
            continue;
 
        /* Allocate an alias_prop with enough space for the stem */
        /* 分配内存,多分配的"len+1"用于存放stem的名字 */
        ap = dt_alloc(sizeof(*ap) + len + 1, __alignof__(*ap));
        if (!ap)
            continue;
        memset(ap, 0, sizeof(*ap) + len + 1);
        ap->alias = start;        /*  ap->alias指向字符串"fimc2 */
        of_alias_add(ap, np, id, start, len);
    }
}
 
static void of_alias_add(struct alias_prop *ap, struct device_node *np,
             int id, const char *stem, int stem_len)
{
    ap->np = np;        // np是"/soc/camera/fimc@fb400000";"对应的节点device_node
    ap->id = id;        // id的值是2,代表设备序号,使用的时候要用到
 
    //由于stem_len是名字除去数字的长度,所以ap->stem被赋值为"fimc"
    strncpy(ap->stem, stem, stem_len);    
    ap->stem[stem_len] = 0;
    list_add_tail(&ap->link, &aliases_lookup);    //将这个ap加入到全局aliases_lookup链表中
    pr_debug("adding DT alias:%s: stem=%s id=%i node=%pOF\n",
         ap->alias, ap->stem, ap->id, np);
}

在注册i2c控制器时:

int i2c_add_adapter(struct i2c_adapter *adapter)
{
    struct device *dev = &adapter->dev;
    int id;
 
    if (dev->of_node) {
//获取与这个device_node对应的alias_prop的id。如果以 i2c2 = &i2c2;节点为例,这里得到的id就是2
        id = of_alias_get_id(dev->of_node, "i2c");
        if (id >= 0) {
            adapter->nr = id;
            return __i2c_add_numbered_adapter(adapter);
        }
    }
 
    id = idr_alloc(&i2c_adapter_idr, adapter,
               __i2c_first_dynamic_bus_num, 0, GFP_KERNEL);
 
    adapter->nr = id;
    return i2c_register_adapter(adapter);
}
 
int of_alias_get_id(struct device_node *np, const char *stem)
{
    struct alias_prop *app;
    int id = -ENODEV;
 
    mutex_lock(&of_mutex);
    /* 遍历全局链表aliases_lookup */
    list_for_each_entry(app, &aliases_lookup, link) {
        /* 找到 stem 是 "i2c" 的alias_prop */
        if (strcmp(app->stem, stem) != 0)
            continue;
        /* 所有的i2c控制的stem都叫"i2c",所以要保证设备节点一致 */
        if (np == app->np) {
            id = app->id;        /* 最终返回找到的编号名字 */
            break;
        }
    }
    mutex_unlock(&of_mutex);
 
    return id;
}

 从上面的分析可知alias节点的作用:

        比如SoC上有多个i2c控制器,alias相当于给每个i2c控制器分配一个唯一的编号,如上面的i2c2对应的alias是i2c2,那么这个编号就是2,将来就可以在/dev下看到名为i2c-2的设备节点。

 

标签:node,i2c,ap,stem,alias,aliases,id,设备
From: https://www.cnblogs.com/god-of-death/p/17299316.html

相关文章

  • Linux内核设备驱动设备树概念与使用
    一、设备树概念以及作用1.1设备树概念设备树(DeviceTree),将这个词分开就是“设备”和“树”,描述设备树的文件叫做DTS(DeviceTreeSource),这个DTS文件采用树形结构描述板级设备,也就是开发板上的设备信息,比如CPU数量、内存基地址、IIC接口上接了哪些设备、SPI接口上接了......
  • 移动端技术:如何优化网站以适应不同设备?
    ​ 随着移动设备的普及,越来越多的用户使用手机和平板电脑来访问网站。因此,网站的移动端优化变得越来越重要。本文将介绍如何优化网站以适应不同设备。一、响应式设计响应式设计是一种能够自适应不同设备的网站设计方式。它可以根据用户的设备大小和屏幕分辨率来自动调整网站的......
  • 主机和IO设备的交互
    系统总线的结构与I/O系统主机和IO设备的交互通过IO接口实现什么是IO接口IO接口就是负责协调主机和外部设备的数据传输的部件,又叫做IO控制器。如下:IO接口主机侧连接到主机,设备侧连接IO设备。这里我们着重看到主机侧的这边,主机侧连接到系统总线,而系统总线的结构也会对IO的控......
  • linux 磁盘设备
       查看Linux系统的I/O调度器查看Linux系统的I/O调度器一般分成两个部分,一个是查看Linux系统整体使用的I/O调度器,另一个是查看某磁盘使用的I/O调度器。查看当前系统支持的I/O调度器,使用如下命令 [[email protected]]#dmesg|grep-ischeduler[4.8......
  • win101909播放设备无法正常工作解决方法
    我们在使用win10操作系统的时候,如果在升级了1909版本之后,可能会有部分小伙伴遇到win101909播放设备无法正常工作这样的问题。那么对于这种情况小编觉得可能是因为我们的系统在更新版本的时候丢失了一些系统文件导致的,可以尝试回退系统即可。详细步骤就来看下小编是怎么做的吧~win......
  • 迪进国际推出8/16/32端口选项,增强Digi Connect EZ系列设备服务器的功能
    全球领先的物联网(IoT)连接产品和服务供应商迪进国际(DigiInternational,NASDAQ:DGII, www.digi.com)今日宣布推出DigiConnect® EZ8/16/32。该解决方案是迪进新一代设备服务器系列的最新产品,为企业、商业和工业自动化应用提供安全、可扩展的连接。此次产品扩展强调了迪进为......
  • 如何获取 Android 设备的CPU核数、时钟频率以及内存大小
    DeviceYearClass的主要功能是根据CPU核数、时钟频率以及内存大小对设备进行分级。下表是Facebook公司提供的分级标准,其中Year栏表示分级结果。以下类就是从Facebook的开源项目DeviceYearClass中拿出来的packagecom.yirui.youbao.util;importandroid.annotati......
  • 今日总结 Android与硬件设备通信(一)
    今天看了看Android与硬件通信的原理1、建立连接的原理在实现软件与硬件交互的时候,首先需要了解该硬件的构造,运行流程等相关操作,熟读相关的文档,知道硬件开发商那边给出了哪些接口,分别对应我们项目中的那些模块等等就拿我这个项目的硬件来说,供应商给出的连接流程如下图:  我......
  • AI视频融合平台EasyCVR播放器快照优化:快照名称增加设备与通道名
    EasyCVR视频融合平台基于云边端协同架构,能支持海量视频的轻量化接入与汇聚管理,可提供视频监控直播、云端录像、云存储、录像检索与回看、智能告警、平台级联、智能分析等视频服务。近期我们对EasyCVR平台的播放器快照功能进行了优化。此前,点击快照截图后,生成文件名称没有包含设备和......
  • VM安装虚拟机时各分区,设备类型,文件系统简介
    各分区简介:/boot:存放开机文件,一般为100M左右(50M~200M)。swap:swap是交换分区、可以看成一种虚拟的内存扩展,内存不够是,可以将内存程序移入,需要时再取出,会比从硬盘读取快。/:linux根目录的分区。各设备类型简介:标准分区:标准分区可以包含文件系统或交换空间,也能提供一个容器,用于......