基于tiny4412的Linux内核移植 --- aliases节点解析
作者信息
作者: 彭东林
QQ:405728433
平台简介
开发板:tiny4412ADK + S700 + 4GB Flash
要移植的内核版本:Linux-4.4.0 (支持device tree)
u-boot版本:友善之臂自带的 U-Boot 2010.12 (为支持uImage启动,做了少许改动)
busybox版本:busybox 1.25
交叉编译工具链: arm-none-linux-gnueabi-gcc
(gcc version 4.8.3 20140320 (prerelease) (Sourcery CodeBench Lite 2014.05-29))
正文
在设备树中有一个叫做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是i2c,那麼這個編號就是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")
... ...
完。
基于tiny4412的Linux内核移植 --- aliases节点解析的更多相关文章
- 基于tiny4412的Linux内核移植 --- aliases节点解析【转】
转自:https://www.cnblogs.com/pengdonglin137/p/5252348.html 阅读目录(Content) 作者信息 平台简介 正文 回到顶部(go to top) ...
- 基于tiny4412的Linux内核移植 -- 设备树的展开
作者信息 作者: 彭东林 邮箱:pengdonglin137@163.com QQ:405728433 平台简介 开发板:tiny4412ADK + S700 + 4GB Flash 要移植的内核版本 ...
- 基于tiny4412的Linux内核移植 -- 设备树的展开【转】
转自:https://www.cnblogs.com/pengdonglin137/p/5248114.html#_lab2_3_1 阅读目录(Content) 作者信息 平台简介 摘要 正文 一.根 ...
- 基于tiny4412的Linux内核移植(支持device tree)(三)
作者信息 作者: 彭东林 邮箱:pengdonglin137@163.com QQ:405728433 平台简介 开发板:tiny4412ADK + S700 + 4GB Flash 要移植的内核版本 ...
- 基于tiny4412的Linux内核移植 -- MMA7660驱动移植(九-2)
作者信息 作者: 彭东林 邮箱:pengdonglin137@163.com QQ:405728433 平台简介 开发板:tiny4412ADK + S700 + 4GB Flash 要移植的内核版本 ...
- 基于tiny4412的Linux内核移植 -- MMA7660驱动移植(九)
作者信息 作者: 彭东林 邮箱:pengdonglin137@163.com QQ:405728433 平台简介 开发板:tiny4412ADK + S700 + 4GB Flash 要移植的内核版本 ...
- 基于tiny4412的Linux内核移植(支持device tree)(一)
作者信息 作者: 彭东林 邮箱:pengdonglin137@163.com QQ:405728433 平台简介 开发板:tiny4412ADK + S700 + 4GB Flash 要移植的内核版本 ...
- 基于tiny4412的Linux内核移植 -- PWM子系统学习(八)
作者信息 作者: 彭东林 邮箱:pengdonglin137@163.com QQ:405728433 平台简介 开发板:tiny4412ADK + S700 + 4GB Flash 要移植的内核版本 ...
- 基于tiny4412的Linux内核移植 -- SD卡驱动移植(五)
作者信息 作者: 彭东林 邮箱:pengdonglin137@163.com QQ:405728433 平台简介 开发板:tiny4412ADK + S700 + 4GB Flash 要移植的内核版本 ...
随机推荐
- [原创]推荐一款强大的.NET程序内存分析工具.NET Memory Profiler
[原创]推荐一款强大的.NET程序内存分析工具.NET Memory Profiler 1 官方网站:http://memprofiler.com/2 下载地址:http://memprofiler. ...
- 解决 Android Studio 乱码问题
http://www.eoeandroid.com/thread-275485-1-1.html 很多同学都安装了Android Studio,但是发现中文是乱码,其实这个很好解决的.在IDE里点击F ...
- MAC电脑操作快捷键
注:command即苹果键,也有人称为花键.ctrl即control键.escape即键盘左上角的esc键.space空格键. 屏幕捕捉快捷键 动作:保存到-快捷键 全屏捕捉-桌面(.pdf文件):c ...
- MySQL查询及删除重复记录的方法
查询及删除重复记录的方法(一)1.查找表中多余的重复记录,重复记录是根据单个字段(peopleId)来判断select * from peoplewhere peopleId in (select p ...
- ie8下jquery改变PNG的opacity出现黑边,ie6下png透明解决办法
目前互联网对于网页效果要求越来越高,不可避免的用到PNG图片,PNG分为几种格 式,PNG8 PNG24 PNG32,其中最常用的,也是显示效果和大小比较适中的则是PNG24,支持半透明,透明,颜色也 ...
- [Aaronyang] 写给自己的WPF4.5 笔记21 [3d课 2/4]
1. 当然复杂的3d模型我们是可以通过更专业的工具做出来,然后导入项目中,我们只是方便演示,选择简单的图形. Tip: 关于摄像机的NearPlaneDistance和FarPlaneDistance ...
- ISO/IEC 9899 C语言标准(非官方翻译)
本系列博文将以ISO/IEC 9899最新的官方手册为准,然后再添加GCC以及Clang编译器对标准的扩展. 本系列博文将不仅仅是针对C编程语言(C Programming Language)标准的翻 ...
- js中“==”与"==="的区别
首先,== equality 等同,=== identity 恒等. ==, 两边值类型不同的时候,要先进行类型转换,再比较. ===,不做类型转换,类型不同的一定不等. 一言以蔽之:==先转换类型再 ...
- Android Studio 中关于NDK编译及jni header生成的问题
之前由于工作原因使用grails这个基于groovy的框架做项目,对groovy感觉很好. 基于groovy的gradle构建系统对我而言自然也是好的没得说. Android Studio 正式版出来 ...
- ecshop利用.htaccess实现301重定向的方法
实现方法如下(空间必须支持对目录中的.htaccess文件解析) 打开 .htaccess 找到 RewriteEngine on 它的下方添加 RewriteCond %{HTTP_HOST} ^需 ...