一. 简介
每个节点都有 compatible 属性,根节点 “ /” 也不例外。 imx6ull-alientek-emmc.dts 设备树 文件中的根 节点下也有一个 compatible 属性。
本文继续学习设备树文件的语法。具体学习根节点 "/" 下的 compatile属性的作用。
二. 设备树根节点下的compatile属性的作用
下面以 imx6ull-alientek-emmc.dts设备树文件为例,imx6ull-alientek-emmc.dts 文件中根 节点的 compatible 属性内容如下所示:
/ {model = "Freescale i.MX6 ULL 14x14 EVK Board";compatible = "fsl,imx6ull-14x14-evk", "fsl,imx6ull";chosen {stdout-path = &uart1;};
........................................
};
可以看出, compatible 有两个值:“ fsl,imx6ull-14x14-evk ” 和 “ fsl,imx6ull ”。
前面我们说了, 设备节点的 compatible 属性值是为了匹配 Linux 内核中的驱动程序,那么根节点中的 compatible 属性是为了做什么工作的?
通过根节点的 compatible 属性可以知道我们所使用的设备,一般第 一个值描述了所使用的硬件设备名字,例如,这里使用的是“ imx6ull-14x14-evk ”这个设备,第二 个值描述了设备所使用的 SOC (即芯片),例如,这里使用的是 “ imx6ull ” 这颗 SOC 。
Linux 内核会通过根 节点的 compoatible 属性查看是否支持此设备,如果支持的话设备就会启动 Linux 内核。
接下来 我们就来学习一下 Linux 内核在使用设备树前后是如何判断是否支持某款设备的。
1. 使用设备树之前设备匹配方法
在没有使用设备树以前, uboot 会向 Linux 内核传递一个叫做 machine id 的值, machine id 也就是设备 ID ,告诉 Linux 内核自己是个什么设备,看看 Linux 内核是否支持。
Linux 内核是支持很多设备的,针对每一个设备 ( 板子 ) , Linux 内核都用 MACHINE_START 和 MACHINE_END 来定义一个 machine_desc 结构体来描述这个设备,例如,在文 件 arch/arm/mach-imx/mach- mx35_3ds.c 中有如下定义:
MACHINE_START(MX35_3DS, "Freescale MX35PDK")/* Maintainer: Freescale Semiconductor, Inc */.atag_offset = 0x100,.map_io = mx35_map_io,.init_early = imx35_init_early,.init_irq = mx35_init_irq,.init_time = mx35pdk_timer_init,.init_machine = mx35_3ds_init,.reserve = mx35_3ds_reserve,.restart = mxc_restart,
MACHINE_END
上述代码就是定义了 “ Freescale MX35PDK ” 这个设备,其中 MACHINE_START 和MACHINE_END 定义在文件 arch/arm/include/asm/mach/arch.h 中,内容如下:
#define MACHINE_START(_type,_name) \
static const struct machine_desc __mach_desc_##_type \__used \__attribute__((__section__(".arch.info.init"))) = { \.nr = MACH_TYPE_##_type, \.name = _name,#define MACHINE_END \
};
根据 MACHINE_START 和 MACHINE_END 的宏定义,展开后如下:
static const struct machine_desc __mach_desc_MX35_3DS__used __attribute__((__section__(".arch.info.init"))) = { .nr = MACH_TYPE_MX35_3DS, //机器ID .name = "Freescale MX35PDK",.atag_offset = 0x100,.map_io = mx35_map_io,.init_early = imx35_init_early,.init_irq = mx35_init_irq,.init_time = mx35pdk_timer_init,.init_machine = mx35_3ds_init,.reserve = mx35_3ds_reserve,.restart = mxc_restart,
};
可以看出,这里定义了一个 machine_desc 类型的结构体变量 __mach_desc_MX35_3DS , 这 个 变 量 存 储 在 “ .arch.info.init ” 段 中 。
第 4 行 的 MACH_TYPE_MX35_3DS 就 是 “ Freescale MX35PDK ” 这 个 板 子 的 machine id 。
MACH_TYPE_MX35_3DS 定义在文件 include/generated/mach-types.h 中,此文件定义了大量的
machine id ,内容如下所示:
#define MACH_TYPE_EBSA110 0
..........
#define MACH_TYPE_WRT350N_V2 1633
#define MACH_TYPE_OMAP_LDP 1639
#define MACH_TYPE_MX35_3DS 1645
...............
前面说了, uboot 会给 Linux 内核传递 machine id 这个参数, Linux 内核会检查这个 machine id ,其实就是将 machine id 与 上面的这些 MACH_TYPE_XXX 宏进行对比,看 看有没有相等的,如果相等,就表示 Linux 内核支持这个设备,如果不支持,那么这个设 备就没法启动 Linux 内核。
2. 使用设备树以后的设备匹配方法
当 Linux 内 核 引 入 设 备 树 以 后 就 不 再 使 用 MACHINE_START 了 , 而 是 换 用了
DT_MACHINE_START 。 DT_MACHINE_START 也定义在文件 arch/arm/include/asm/mach/arch.h 里面,定义如下:
#define DT_MACHINE_START(_name, _namestr) \
static const struct machine_desc __mach_desc_##_name \__used \__attribute__((__section__(".arch.info.init"))) = { \.nr = ~0, \.name = _namestr,#endif
可以看出, DT_MACHINE_START 和 MACHINE_START 基本相同,只是 .nr 的设置不同,在 DT_MACHINE_START 里面,直接将 .nr 设置为 ~0 。说明引入设备树以后,不会再根据 machine
id 来检查 Linux 内核是否支持某个设备了。
打开文件 arch/arm/mach-imx/mach-imx6ul.c ,有如下所示内容:
static const char *imx6ul_dt_compat[] __initconst = {"fsl,imx6ul","fsl,imx6ull",NULL,
};DT_MACHINE_START(IMX6UL, "Freescale i.MX6 Ultralite (Device Tree)").map_io = imx6ul_map_io,.init_irq = imx6ul_init_irq,.init_machine = imx6ul_init_machine,.init_late = imx6ul_init_late,.dt_compat = imx6ul_dt_compat,
MACHINE_END
可以看出,machine_desc 结构体中有个 .dt_compat 成员变量,此成员变量保存着本设备兼容属性。
上面的 mach-imx6ul.c 文件中的结构体设置 .dt_compat = imx6ul_dt_compat , imx6ul_dt_compat 表里面有 "fsl,imx6ul" 和 "fsl,imx6ull" 这两个兼容值。 只要某个设备 ( 板子 ) 的设备树文件的根节点 “ / ” 的 compatible 属性值与 imx6ul_dt_compat 表中的任何一个值相等,那么就表示 Linux 内核支持此设备。
imx6ull-alientek-emmc.dts 中根节点的 compatible 属性值如下:
compatible = "fsl,imx6ull-14x14-evk", "fsl,imx6ull";
可以看出,mach-imx6ul.c 文件 中 “fsl,imx6ull” 与 imx6ul_dt_compat 中的 “ fsl,imx6ull ” 匹配,因此 I.MX6U-ALPHA 开发板可以正常启动 Linux 内核。
如果将 imx6ull-alientek-emmc.dts 根节点的 compatible 属性改为其他的值,比如:
compatible = "fsl,imx6ull-14x14-evk", "fsl,imx6ullll"
重新编译 .dts 设备树文件,并用新的 DTS 启动 Linux 内核,开发板重启后,结果如下 :
当我们修改了根节点 compatible 属性内容以后,因为 Linux 内核找不到对应的设备,因此,Linux 内核无法启动。在 uboot 输出 Starting kernel… 以后就再也没有其他信息输出了。