设备树知识小全(五):根节点兼容性

简介: 设备树知识小全(五):根节点兼容性

上面简要的了解一丢丢的属性,其实也最常用的三个属性。

但是还是应该系统的学学啦。开整。

参考资料:《Linux设备驱动开发详解》

1、根节点兼容性

上述.dts文件中,第2行根节点"/"的兼容属性compatible=“acme,coyotes-revenge”;定义了整个系统(设备级别)的名称,它的组织形式为:,。

Linux内核通过根节点"/"的兼容属性即可判断它启动的是什么设备。

在真实项目中,这个顶层设备的兼容属性一般包括两个或者两个以上的兼容性字符串,首个兼容性字符串是板子级别的名字,后面一个兼容性是芯片级别(或者芯片系列级别)的名字。

譬如板子arch/arm/boot/dts/vexpress-v2p-ca9.dts兼容于arm,vexpress,v2p-ca9和“arm,vexpress”:

compatible = "arm,vexpress,v2p-ca9", "arm,vexpress";

板子arch/arm/boot/dts/vexpress-v2p-ca5s.dts的兼容性则为:

compatible = "arm,vexpress,v2p-ca5s", "arm,vexpress";

板子arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts的兼容性为:

compatible = "arm,vexpress,v2p-ca15_a7", "arm,vexpress";

可以看出,上述各个电路板的共性是兼容于arm,vexpress,而特性是分别兼容于arm,vexpress,v2p-ca9、arm,vexpress,v2p-ca5s和arm,vexpress,v2p-ca15_a7。

进一步地看,arch/arm/boot/dts/exynos4210-origen.dts的兼容性字段如下:

compatible = "insignal,origen", "samsung,exynos4210", "samsung,exynos4";

第一个字符串是板子名字(很特定),第2个字符

串是芯片名字(比较特定),第3个字段是芯片系列的名字(比较通用)。

作为类比,arch/arm/boot/dts/exynos4210-universal_c210.dts的兼容性字段则如下:

compatible = "samsung,universal_c210", "samsung,exynos4210", "samsung,exynos4";

由此可见,它与exynos4210-origen.dts的区别只在于第1个字符串(特定的板子名字)不一样,后面芯片名和芯片系列的名字都一样。

在Linux 2.6内核中,ARM Linux针对不同的电路板会建立由MACHINE_START和MACHINE_END包围起来的针对这个设备的一系列回调函数,如代码清单18.3所示。

1 MACHINE_START(VEXPRESS, "ARM-Versatile Express")
 2         .atag_offset    = 0x100,
 3         .smp            = smp_ops(vexpress_smp_ops),
 4         .map_io         = v2m_map_io,
 5         .init_early     = v2m_init_early,
 6         .init_irq       = v2m_init_irq,
 7         .timer          = &v2m_timer,
 8         .handle_irq     = gic_handle_irq,
 9         .init_machine   = v2m_init,
10         .restart        = vexpress_restart,
11 MACHINE_END

这些不同的设备会有不同的MACHINE ID,Uboot在启动Linux内核时会将MACHINE ID存放在r1寄存器,Linux启动时会匹配Bootloader传递的MACHINE ID和MACHINE_START声明的MACHINE ID,然后执行相应设备的一系列初始化函数。

ARM Linux 3.x在引入设备树之后,MACHINE_START变更为DT_MACHINE_START,其中含有一个.dt_compat成员,用于表明相关的设备与.dts中根节点的兼容属性兼容关系。

如果Bootloader传递给内核的设备树中根节点的兼容属性出现在某设备的.dt_compat表中,相关的设备就与对应的兼容匹配,从而引发这一设备的一系列初始化函数被执行。一个典型的DT_MACHINE如代码清单18.4所示。

1 static const char * const v2m_dt_match[] __initconst = {
 2         "arm,vexpress",
 3         "xen,xenvm",
 4         NULL,
 5 };
 6 DT_MACHINE_START(VEXPRESS_DT, "ARM-Versatile Express")
 7         .dt_compat      = v2m_dt_match,
 8         .smp            = smp_ops(vexpress_smp_ops),
 9         .map_io         = v2m_dt_map_io,
10         .init_early     = v2m_dt_init_early,
11         .init_irq       = v2m_dt_init_irq,
12         .timer          = &v2m_dt_timer,
13         .init_machine   = v2m_dt_init,
14         .handle_irq     = gic_handle_irq,
15         .restart        = vexpress_restart,
16 MACHINE_END

Linux倡导针对多个SoC、多个电路板的通用DT设备,即一个DT设备的.dt_compat包含多个电路板.dts文件的根节点兼容属性字符串。 (举个栗子就是这个流程 这个那个板子都可以用)

之后,如果这多个电路板的初始化序列不一样,可以通过int of_machine_is_compatible(const char*compat)API判断具体的电路板是什么。在Linux内核中,常常使用如下API来判断根节点的兼容性:

int of_machine_is_compatible(const char *compat);

此API判断目前运行的板子或者SoC的兼容性,它匹配的是设备树根节点下的兼容属性。

例如drivers/cpufreq/exynos-cpufreq.c中就有判断运行的CPU类型是exynos4210、exynos4212、exynos4412还是exynos5250的代码,进而分别处理,如代码清单18.5所示。

1 static int exynos_cpufreq_probe(struct platform_device *pdev)
 2 {
 3         int ret = -EINVAL;
 4
 5         exynos_info = kzalloc(sizeof(*exynos_info), GFP_KERNEL);
 6         if (!exynos_info)
 7                 return -ENOMEM;
 8
 9         exynos_info->dev = &pdev->dev;
10
11         if (of_machine_is_compatible("samsung,exynos4210")) {
12                 exynos_info->type = EXYNOS_SOC_4210;
13                 ret = exynos4210_cpufreq_init(exynos_info);
14         } else if (of_machine_is_compatible("samsung,exynos4212")) {
15                 exynos_info->type = EXYNOS_SOC_4212;
16                 ret = exynos4x12_cpufreq_init(exynos_info);
17         } else if (of_machine_is_compatible("samsung,exynos4412")) {
18                 exynos_info->type = EXYNOS_SOC_4412;
19                 ret = exynos4x12_cpufreq_init(exynos_info);
20         } else if (of_machine_is_compatible("samsung,exynos5250")) {
21                 exynos_info->type = EXYNOS_SOC_5250;
22                 ret = exynos5250_cpufreq_init(exynos_info);
23         } else {
24                 pr_err("%s: Unknown SoC type\n", __func__);
25                 return -ENODEV;
26         }
27         ...
28 }

如果一个兼容包含多个字符串,譬如对于前面介绍的根节点兼容compatible=“samsung,universal_c210”,“samsung,exynos4210”,"samsung,exynos4"的情况,如下3个表达式都是成立的。

of_machine_is_compatible("samsung,universal_c210")
of_machine_is_compatible("samsung,exynos4210")
of_machine_is_compatible("samsung,exynos4")

这个的复用吧,我觉得是利用一套去适应多条的必然,但是如果相对于本身,顺序或者自定义过多,那么其实也没有必要复用这个DT吧。具体的当然我现在的理解都是纯靠猜想,具体等到设计到的时候,再做详细展开,正如我所说,学习读书,联接很重要。

目录
相关文章
|
6月前
|
Linux API SoC
设备树知识小全(十一):OF是什么?
设备树知识小全(十一):OF是什么?
143 0
|
6月前
|
Linux API C语言
设备树知识小全(十):由设备树引发的BSP和驱动变更
设备树知识小全(十):由设备树引发的BSP和驱动变更
89 0
|
网络性能优化 网络协议 网络虚拟化
|
5月前
|
前端开发 Java 数据库连接
项目API借口的根路径怎样设置
项目API借口的根路径怎样设置
|
6月前
|
缓存 Linux API
设备树知识小全(六):设备节点兼容性
设备树知识小全(六):设备节点兼容性
90 0
MM管理器(叶子修改版)V3.0
MM管理器(叶子修改版)
1456 0
CATIA二次开发—遍历结构树
CATIA二次开发—遍历结构树
CATIA二次开发—遍历结构树
|
Java API 数据库
【编译原理+句柄+入栈顺序从右至左+系统调用+win api+程序安排+acm ieee usenix信息】答疑
【编译原理+句柄+入栈顺序从右至左+系统调用+win api+程序安排+acm ieee usenix信息】答疑
110 0
【编译原理+句柄+入栈顺序从右至左+系统调用+win api+程序安排+acm ieee usenix信息】答疑
|
自然语言处理 算法 安全
【算法】1379. 找出克隆二叉树中的相同节点(多语言实现)
给你两棵二叉树,原始树 original 和克隆树 cloned,以及一个位于原始树 original 中的目标节点 target。 其中,克隆树 cloned 是原始树 original 的一个 副本 。 请找出在树 cloned 中,与 target 相同 的节点,并返回对该节点的引用(在 C/C++ 等有指针的语言中返回 节点指针,其他语言返回节点本身)。
【算法】1379. 找出克隆二叉树中的相同节点(多语言实现)
|
关系型数据库 MySQL 网络安全
【技术贴】安装MYSQL最后一步出现错误,提示"终结点映射器中没有更多的终结点可用的解决"!
【技术贴】安装MYSQL最后一步出现错误,提示"终结点映射器中没有更多的终结点可用的解决"!   能看到这句话证明你的mYSQL已经ok了。   问题分析 这是因为你在安装MySQL的某一步中勾选了“Add firewall exception for this port”(为防火墙添加例外),但是你的Windows的防火墙或者防火墙服务被你优化关闭了(比如我 就没有开过windows防火墙),所以会有这个提示。
1823 0