====== DTS简述 ======
参考:
* [[https://blog.csdn.net/qq_53144843/article/details/123829747|Linux DTS(Device Tree Source)]]
* [[http://kernel.meizu.com/device-tree.html|Device Tree 详解]]
===== - DTS文件 =====
DTS文件引用树:
kernel/arch/arm64/boot/dts/rockchip/
./rk3568-firefly-mplayer.dts
├─./rk3568-firefly-mplayer.dtsi
│ └─./rk3568-firefly-port.dtsi
│ ├─./rk3568-firefly-core.dtsi
│ │ └─./rk3568.dtsi
│ │ ├─./rk3568-dram-default-timing.dtsi
│ │ └─./rk3568-pinctrl.dtsi
│ │ └─./rockchip-pinconf.dtsi
│ ├─./rk356x-firefly-demo.dtsi
│ └─./rk3568-linux.dtsi
└─./rk3568-firefly-aioj-cam-8ms1m.dtsi
===== - node节点 =====
{}包围起来的结构称之为节点,dts中最开头的/ {},称为根节点。 \\
节点的标准结构是xxx@yyy{属性1;属性2;...},其中:
xxx:节点名 \\
yyy(可选):节点的地址(寄存器地址或其他地址) \\
例: \\
i2c1:i2c@021a0000 \\
rtc:pcf8523@68
==== - 一般属性 ====
=== - reg ===
reg的格式通常为
\\
例:reg = <0x021a0000 0x4000>; 0x021a0000是寄存器基地址,0x4000是长度。 \\
address 和length的个数是可变的,由父节点的属性#address-cells 和#size-cells 决定, \\
比如节点i2c@021a0000的父节点是aips-bus@02000000,其#address-cells 和#size-cells均为1,所以下面的i2c节点的reg属性就有一个address 和length, \\
而i2c节点本身#address-cells 和#size-cells 分别为1和0,所以其下的rtc: pcf8523@68 的reg属性就只有一个0x68(i2c地址)了
i2c1: i2c@021a0000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "fsl,imx6q-i2c", "fsl,imx21-i2c";
reg = <0x021a0000 0x4000>;
interrupts = <0 36 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6QDL_CLK_I2C1>;
status = "disabled";
};
配置node可以根据compatible,在kernel/Documentation/devicetree/bindings中查到说明, \\
或在 kernel/drivers/tty/serial/ 早到驱动代码。例如:
v2m_serial0: uart@090000 {
compatible = "arm,pl011", "arm,primecell";
reg = <0x090000 0x1000>;
interrupts = <5>;
clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
clock-names = "uartclk", "apb_pclk";
};
&i2c1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_hummingboard_i2c1>;
rtc: pcf8523@68 {
compatible = "nxp,pcf8523";
reg = <0x68>;
};
=== - compatible ===
如果一个节点是设备节点,那么它一定要有compatible(兼容性),因为这将作为驱动和设备(设备节点)的匹配依据, \\
compatible(兼容性)的值可以有不止一个字符串以满足不同的需求。 \\
而根节点的compatible也是非常重要的,因为系统启动后,将根据根节点的compatible来判断cpu信息,并由此进行初始化。
=== - pinctrl-names ===
pinctrl-names:定义设备不同的工作状态,一般包括下面几个: \\
default、init、sleep、idle \\
其中,sleep、idle用于系统的电源管理,以达到控制系统功耗的目的。\\
pinctrl-0:定义了一个phandles的列表,每个phandle指向一个pinctrl的节点。 \\
该配置项定义了该设备的一种工作状态,其对应于pinctrl-names中首个工作状态。
下面举例说明一下:
deviceA {
pinctrl-names = “defalut”, “idle”;
pinctrl-0 = <&state_0_node_a>;
pinctrl-1 = <&state_1_node_a &state_1_node_b>;
};
deviceA节点,定义了"default","idle"两种工作状态,随后依次定义了pinctrl-0和pinctrl-1两个pins列表,分别对应于两个状态。
=== - 属性的编写说明 ===
== - 参考SDK中第的属性说明 ==
#
cd kernel
cd Documentation/devicetree/bindings/
grep "arm,pl011" -rn *
== - 在代码中获取属性编写格式 ==
#
cd kernel/drivers/tty/serial/
grep "arm,pl011" -rn *
==== - 节点之间的联系 ====
* 节点与节点之间的关联,通常通过“标号引用”和“包含”来实现
- 标号引用,就是在节点名称前加上标号,这样设备树的其他位置就能够通过&符号来调用/访问该节点
- 包含则是最基本的方式,比如我们要在i2c1接口添加一个i2c外设,那么就必须要在i2c1下面添加一个节点
* 标号引用常常还作为节点的重写方式
* 如果一个节点是属性节点(即仅仅是作为属性被其他节点调用),可定义在任意位置
属性节点定义在哪里其实无所谓,重要的是调用的位置,比如lcd屏幕的时序, \\
其实我们完全可以把它定义在任何地方,然后在lcd节点下用&来调用它。 \\
这有点类似于函数:在哪定义不重要,重要的是在哪调用。
===== - DTS相关工具 =====
==== - devicetree(linux) ====
工具主页:https://gitee.com/yuwenhai/device-tree-tools
* 安装:
wget https://gitee.com/yuwenhai/device-tree-tools/raw/master/devicetree/dt.py;mv dt.py ~/bin/dt;chmod 755 ~/bin/dt
* 参数
usage: 从设置的根节点预览或搜索指定关键字
设备树查看器(0.9)
options:
-s SET_CONF, -set SET_CONF, --set SET_CONF
设置dtv.conf文件
-c, -config, --config
显示当前使用的dtv.conf文件路径
-r, -root, --root 显示当前的根节点路径
-z, -hp, --hidePath, -short, --short
按照最短路径显示
-f FIND_KEYWORD, -find FIND_KEYWORD, --find FIND_KEYWORD
搜索指定内容
-x {re,all}, -flag {re,all}, --flag {re,all}
re:启用正则表达式搜索 all:在所有树中显示
-d, -debug, --debug Debug模式运行
-no-color, --no-color
禁用颜色显示
-v, --version 显示当前版本
--history 显示历史变更记录
-h, --help 显示帮助页
* 设置:
dt -set ~/linux_sdk/kernel/arch/arm64/boot/dts/rockchip/rk3568-firefly-mplayer.dts
* 运行:
dt -h
dt -z
dt -z -find pinctrl