[DTS]设备树实践

简介: [DTS]设备树实践

以下内容以RK3288作为讲解

kernel\arch\arm\boot\dts\rk3288.dts

(1) 头文件

#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/pinctrl/rockchip.h>
#include <dt-bindings/clock/rk3288-cru.h>
#include <dt-bindings/power/rk3288-power.h>
#include <dt-bindings/thermal/thermal.h>
#include <dt-bindings/power/rk3288-power.h>
#include <dt-bindings/soc/rockchip,boot-mode.h>

头文件里面定义了dts文件中使用的宏,比如下面:

interrupts = <GIC_SPI 151 IRQ_TYPE_LEVEL_HIGH>,
            <GIC_SPI 152 IRQ_TYPE_LEVEL_HIGH>,
            <GIC_SPI 153 IRQ_TYPE_LEVEL_HIGH>,
            <GIC_SPI 154 IRQ_TYPE_LEVEL_HIGH>;

GIC_SPIIRQ_TYPE_LEVEL_HIGH都是定义在头文件中的。

(2) 根节点

/ {
    #address-cells = <2>;
    #size-cells = <2>;
    compatible = "rockchip,rk3288";
    interrupt-parent = <&gic>;
    
    ........
}
  • address-cells和#size-cells决定子节点的reg属性值为

    < address1 length1 address2 length2>

  • compatible用来匹配machine_desc
  • interrupt-parent表示根节点所使用的中断控制器,如果子节点没有该属性,这和父节点共用。

(3) aliases(别名)

    aliases {
        ethernet0 = &gmac;
        i2c0 = &i2c0;
        i2c1 = &i2c1;
        i2c2 = &i2c2;
        i2c3 = &i2c3;
        i2c4 = &i2c4;
        i2c5 = &i2c5;
        mshc0 = &emmc;
        mshc1 = &sdmmc;
        mshc2 = &sdio0;
        mshc3 = &sdio1;
        serial0 = &uart0;
        serial1 = &uart1;
        serial2 = &uart2;
        serial3 = &uart3;
        serial4 = &uart4;
        spi0 = &spi0;
        spi1 = &spi1;
        spi2 = &spi2;
    };

定义节点别名

(4) arm-pmu(电源管理单元)

arm-pmu {
    compatible = "arm,cortex-a12-pmu";
    interrupts = <GIC_SPI 151 IRQ_TYPE_LEVEL_HIGH>,
        <GIC_SPI 152 IRQ_TYPE_LEVEL_HIGH>,
        <GIC_SPI 153 IRQ_TYPE_LEVEL_HIGH>,
        <GIC_SPI 154 IRQ_TYPE_LEVEL_HIGH>;
    interrupt-affinity = <&cpu0>, <&cpu1>, <&cpu2>, <&cpu3>;
};

这个节点的属性和属性值该如何定义?
1) 到kernel\Documentation\devicetree\bindings\arm\pmu.txt查看文档说明,文档中给出了该节点的属性及说明。
2) compatible属性,文档中给出了选项

"apm,potenza-pmu"
"arm,armv8-pmuv3"
"arm,cortex-a73-pmu"
"arm,cortex-a72-pmu"
"arm,cortex-a57-pmu"
"arm,cortex-a53-pmu"
"arm,cortex-a35-pmu"
"arm,cortex-a17-pmu"
"arm,cortex-a15-pmu"
"arm,cortex-a12-pmu"
"arm,cortex-a9-pmu"
"arm,cortex-a8-pmu"
"arm,cortex-a7-pmu"
"arm,cortex-a5-pmu"
"arm,arm11mpcore-pmu"
"arm,arm1176-pmu"
"arm,arm1136-pmu"
"brcm,vulcan-pmu"
"cavium,thunder-pmu"
"qcom,scorpion-pmu"
"qcom,scorpion-mp-pmu"
"qcom,krait-pmu"

然后根据cpu使用的arm核心版本来决定值,比如RK3288使用cortex-a12,所以选择"arm,cortex-a12-pmu"

3) interrupts属性,文档中给出的解释是(1 combined interrupt or 1 per core)一个组合中断或一个核心一个中断。因为RK3288是4核的,所以interrupts组合了四个中断。然后每个中断对应的三个值。

为什么是三个值,每个值对应的含义是什么?

4) 为什么是三个值,这跟中断控制器有关。上面说过子节点没有指定interrupt-parent属性,则和父节点共用,所以我们可以找到对应的中断控制器的定义。并找到它的compatible属性。

compatible = "arm,gic-400";

从上面的属性值可以找到中断控制器的类型为GIC (Generic Interrupt Controller),所以可以找到对应的说明文档kernel\Documentation\devicetree\bindings\interrupt-controller\arm,gic.txt

文档中说明GIC的#interrupt-cells属性值应为3,所以每个中断源对应三个值。
然后三个值对应的含义是什么,文档中也有解释。
1st cell:中断类型,0表示SPI中断,1表示PPI中断
2nd cell:该中断类型中的中断号,SPI中断的范围是[0-987], PPI中断范围是[0-15]
3rd cell : 标识, bit3:0 4:高电平触发 8:低电平触发(SPI无效) ) ; bit[15:8] (PPI中断掩码)

5) <GIC_SPI 151 IRQ_TYPE_LEVEL_HIGH>含义
中断类型: SPI(GIC_SPI定义在arm-gic.h中),SPI表示该中断是所有cpu core共享的
中断号: 151, RK3288 datasheet中给出的值是从0~159,该值具体如何定义还不清楚。
标识: 高电平,RK3288 datasheet中说“Input interrupt level is fixed , only high-level sensitive”(输入中断仅高电平有效)

6) interrupt-affinity属性用来关联中断和cpu core, 这个属性是和interrupts中的值一一对应的。即:
<GIC_SPI 151 IRQ_TYPE_LEVEL_HIGH> --------> cpu0
<GIC_SPI 152 IRQ_TYPE_LEVEL_HIGH> --------> cpu1
<GIC_SPI 153 IRQ_TYPE_LEVEL_HIGH> --------> cpu2
<GIC_SPI 154 IRQ_TYPE_LEVEL_HIGH> --------> cpu3

当超过一个SPI时interrupt-affinity属性必须出现

(5) sdmmc(SDIO)

sdmmc: dwmmc@ff0c0000 {
    compatible = "rockchip,rk3288-dw-mshc";
    max-frequency = <150000000>;
    clocks = <&cru HCLK_SDMMC>, <&cru SCLK_SDMMC>,
    <&cru SCLK_SDMMC_DRV>, <&cru SCLK_SDMMC_SAMPLE>;
    clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
    fifo-depth = <0x100>;
    interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
    reg = <0x0 0xff0c0000 0x0 0x4000>;
    resets = <&cru SRST_MMC0>;
    reset-names = "reset";
    status = "disabled";
};

1) 文档说明
kernel\Documentation\devicetree\bindings\mmc\rockchip-dw-mshc.txt
kernel\Documentation\devicetree\bindings\mmc\synopsy-dw-mshc.txt
kernel\Documentation\devicetree\bindings\mmc\mmc.txt
上面的文档对该节点中的属性都做了说明。

2) max-frequency: 最大时钟频率,查看datasheet
在这里插入图片描述
3) clocks: 指定时钟单元和时钟阀门,这个要和clock-name一一对应的。这里指定了4个属性值,对应到clock-name也是四个属性值。

**biu: bus interface unit(总线接口单元)
ciu: card interface unit(卡接口单元)
cru: clock reset unit(时钟复位单元)**

4) clock-names: 时钟名,和clocks一一对应
5) fifo-depth: 输入输出(rx/tx)缓存的大小
6) interrupts: 中断
7) reg: 基地址和最大偏移量,为什么要用四个值(cell)呢?
因为父节点#address-cells = <2> #size-cells = <2>, 主要是为了适配所有子节点,所以父节点多定义了一些cell。
8)resets: 指定复位单元和复位说明符(指示哪个外设复位)。RK3288时钟单元和复位单元集成在同一个模块上(cru)。
9) reset-names: 使用resets属性必须要有该属性,属性值必须是"reset"。
10) status: 外设状态,两个取值: disabled和okay 。

(6) spi

spi0: spi@ff110000 {
    compatible = "rockchip,rk3288-spi", "rockchip,rk3066-spi";
    clocks = <&cru SCLK_SPI0>, <&cru PCLK_SPI0>;
    clock-names = "spiclk", "apb_pclk";
    dmas = <&dmac_peri 11>, <&dmac_peri 12>;
    dma-names = "tx", "rx";
    interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
    pinctrl-names = "default";
    pinctrl-0 = <&spi0_clk &spi0_tx &spi0_rx &spi0_cs0>;
    reg = <0x0 0xff110000 0x0 0x1000>;
    #address-cells = <1>;
    #size-cells = <0>;
    status = "disabled";
};

1) dmas: 指定spi总线中MISO, MOSI所使用的DMA通道。
在这里插入图片描述
2) pinctrl-names: 引脚配置名称(引脚默认状态),属性值可以为"default"或"sleep"。
3) pinctrl-0: 引脚引用列表,这里主要是spi的引脚。每个引用点都必须是引脚控制器下的子节点。
4) #address-cells和#size-cells主要是为了挂接在spi上的设备准备的。

总结:
(1) 上面的讲解主要是语法实践和如何来查找说明文档来进行配置。对于做二次开发的人来说主要是看芯片原厂给的文档和查看Documention\devicetree下的文档。当然也可以看datasheet, 只是没太大必要,而且很多芯片厂家不会提供完整的datasheet.
(2) 如果是芯片原厂工程师,主要是根据datasheet和Documention\devicetree下的文档来配置。有时候还要自定义属性。
(3) 属性值得配置一定要和驱动匹配。

相关文章
|
4月前
|
Linux SoC
Linux设备树(DTS)介绍
**设备树(DTS)是Linux中用于描述硬件信息的文本文件,旨在减少内核与平台相关代码的耦合。DTS文件包含静态硬件配置,不支持动态变更。它被编译成DTB二进制文件,供内核在启动时解析以了解硬件布局。设备树解决了ARM体系结构代码维护的复杂性问题,通过解耦实现vendor修改的独立和共二进制目标。设备树overlay允许对配置进行增量修改,遵循特定规则,如dts覆盖dtsi,先引用后修改。调试时,可使用内置工具反编译dtb或dtbo映像为dts文本以检查内容。**
204 7
|
3月前
|
Linux SoC
Linux设备树(DTS)
Dts:DTS即Device Tree Source,是一个文本形式的文件,用于描述硬件信息。一般都是固定信息,无法变更,无法overlay。 设备树由来 linux内核源码中,之前充斥着大量的平台相关(platform Device)配置,而这些代码大多是杂乱且重复的,这使得ARM体系结构的代码维护者和内核维护者在发布一个新的版本的时候有大量的工作要做,以至于LinusTorvalds 在2011年3月17日的ARM Linux邮件列表中宣称“Gaah.Guys,this whole ARM thing is a f*cking pain in the ass”这使得整个ARM社区不得不
|
6月前
|
XML Ubuntu 物联网
Linux系统中驱动入门设备树DTS(经典)
Linux系统中驱动入门设备树DTS(经典)
360 0
|
Linux SoC
Linux设备树(DTS)介绍
Dts:DTS即Device Tree Source,是一个文本形式的文件,用于描述硬件信息。一般都是固定信息,无法变更,无法overlay。 设备树由来 linux内核源码中,之前充斥着大量的平台相关(platform Device)配置,而这些代码大多是杂乱且重复的,这使得ARM体系结构的代码维护者和内核维护者在发布一个新的版本的时候有大量的工作要做,以至于LinusTorvalds 在2011年3月17日的ARM Linux邮件列表中宣称“Gaah.Guys,this whole ARM thing is a f*cking pain in the ass”这使得整个ARM社区不得不
241 0
|
编译器
[DTS]设备树语法
[DTS]设备树语法
[DTS]设备树基本概念
在Linux3.x之前的内核源码中,存在大量对板级细节信息描述的代码。这些代码充斥在/arch/arm/plat-xxx和/arch/arm/mach-xxx目录。为了解决这个问题而引入设备树。
DTS设备树(todo)
http://blog.csdn.net/21cnbao/article/details/8457546 https://my.oschina.net/hanshubo/blog/615199   http://blog.
1245 0
|
6月前
|
关系型数据库 MySQL 数据挖掘
阿里云 SelectDB 携手 DTS ,一键实现 TP 数据实时入仓
DTS 作为阿里云核心的数据交互引擎,以其高效的实时数据流处理能力和广泛的数据源兼容性,为用户构建了一个安全可靠、可扩展、高可用的数据架构桥梁。阿里云数据库 SelectDB 通过与 DTS 联合,为用户提供了简单、实时、极速且低成本的事务数据分析方案。用户可以通过 DTS 数据传输服务,一键将自建 MySQL / RDS MySQL / PolarDB for MySQL 数据库,迁移或同步至阿里云数据库 SelectDB 的实例中,帮助企业在短时间内完成数据迁移或同步,并即时获得深度洞察。
阿里云 SelectDB 携手 DTS ,一键实现 TP 数据实时入仓
|
6月前
|
SQL 分布式计算 监控
在数据传输服务(DTS)中,要查看每个小时源端产生了多少条数据
【2月更文挑战第32天】在数据传输服务(DTS)中,要查看每个小时源端产生了多少条数据
66 6