3. DRM 设备树节点结构:display-controller 核心属性
在 DRM 显示驱动框架中,display-controller 节点是设备树中描述显示控制器的核心节点。该节点向内核报告硬件控制器的寄存器基址、中断资源、总线连接关系以及兼容性信息。本节详细解析 display-controller 节点的规范定义、compatible、reg 和 interrupts 属性的标准写法与解析流程。
3.1 display-controller 节点规范与标准结构
设备树规范(ePAPR / Devicetree Specification)并未强制要求节点名称必须为 "display-controller",但 DRM 子系统及主流 SoC 厂商(如 NXP、Rockchip、Allwinner、Mediatek)均采用 display-controller 作为标准节点名,以便于驱动通过 of_device_is_compatible() 或节点名称进行快速识别。
一个典型的 display-controller 节点结构如下:
display-controller@1e60000 {
compatible = "vendor,display-controller-version", "vendor,display-controller";
reg = <0x01e60000 0x10000>;
interrupts = <0 45 4>;
interrupt-parent = <&gic>;
clocks = <&ccu CLK_DISPLAY>;
resets = <&ccu RST_DISPLAY>;
status = "okay";
};
节点名称中的 @1e60000 表示该控制器的第一个寄存器基地址,用于辅助地址匹配。节点内部属性按功能可分为三类:
| 属性类别 | 属性名 | 作用 | 是否必须 |
|---|---|---|---|
| 标识属性 | compatible | 驱动匹配与硬件版本识别 | 必须 |
| 资源属性 | reg | 寄存器地址空间描述 | 必须 |
| 资源属性 | interrupts | 中断号与触发类型 | 必须 |
| 辅助属性 | clocks / resets | 时钟与复位控制 | 按需 |
| 状态属性 | status | 设备启用/禁用 | 推荐 |
3.2 compatible 属性:驱动匹配与硬件版本识别
compatible 属性是设备树中最重要的标识属性,DRM 驱动通过 of_match_table 与 compatible 字符串进行匹配。display-controller 节点的 compatible 通常采用 “厂商,设备型号” 的命名规范,并支持向后兼容的 fallback 字符串。
标准格式:
compatible = "vendor,soc-display-ctrl-v2", "vendor,soc-display-ctrl";
匹配优先级:内核优先使用第一个字符串进行精确匹配;若失败,则依次尝试后续字符串。这种设计允许同一驱动支持多个硬件版本。
| 厂商前缀 | 示例 compatible | 对应 DRM 驱动 |
|---|---|---|
| rockchip | "rockchip,rk3399-vop" | rockchip_drm_vop |
| allwinner | "allwinner,sun8i-de2" | sun4i_drm |
| fsl | "fsl,imx6q-ipu" | imx_drm |
| mediatek | "mediatek,mt8173-disp-ovl" | mediatek_drm |
| amlogic | "amlogic,meson-gxbb-dw-hdmi" | meson_drm |
3.3 reg 属性:寄存器地址空间描述
reg 属性用于描述 display-controller 占用的寄存器地址空间。每个 reg 条目由 地址 和 长度 组成,格式由父节点的 #address-cells 和 #size-cells 决定。
标准格式:
reg = <0x01e60000 0x10000>;
其中:
- 0x01e60000:寄存器基地址(物理地址)
- 0x10000:寄存器地址空间长度(64KB)
对于包含多个独立寄存器区域的复杂控制器,reg 可以包含多个条目:
reg = <0x01e60000 0x10000>,
<0x01e70000 0x1000>,
<0x01e80000 0x2000>;
内核通过 platform_get_resource(pdev, IORESOURCE_MEM, index) 按索引依次获取每个 reg 区域,index 从 0 开始。
| #address-cells | #size-cells | reg 条目格式 | 示例 |
|---|---|---|---|
| 1 | 1 | <addr len> | <0x1e60000 0x10000> |
| 2 | 1 | <high_addr low_addr len> | <0x0 0x1e60000 0x10000> |
| 1 | 2 | <addr high_len low_len> | <0x1e60000 0x0 0x10000> |
3.4 interrupts 属性:中断资源描述
interrupts 属性定义 display-controller 使用的中断线。中断描述格式由中断控制器(如 GIC)的 #interrupt-cells 属性决定。ARM 平台最常用的中断控制器是 GIC(Generic Interrupt Controller),其 #interrupt-cells 通常为 3。
标准格式(GIC v2/v3):
interrupts = <0 45 4>;
三个字段的含义:
- 字段 1(中断类型):0 = SPI(共享外设中断),1 = PPI(私有外设中断)
- 字段 2(中断号):对于 SPI,中断号范围为 32 ~ 1019;对于 PPI,范围为 16 ~ 31
- 字段 3(触发类型与极性):1 = 上升沿触发,2 = 下降沿触发,4 = 高电平触发,8 = 低电平触发
对于包含多个中断的 display-controller(如帧完成中断、错误中断、DMA 中断),可以定义多个中断:
interrupts = <0 45 4>, /* 帧同步中断 */
<0 46 4>, /* 错误中断 */
<0 47 4>; /* DMA 完成中断 */
内核通过 platform_get_irq(pdev, index) 按索引获取每个中断号,index 从 0 开始。
| 中断类型 | 类型值 | 中断号范围 | 说明 |
|---|---|---|---|
| SPI | 0 | 32 ~ 1019 | 共享外设中断,多个 CPU 均可接收 |
| PPI | 1 | 16 ~ 31 | 私有外设中断,仅绑定到特定 CPU |
3.5 完整 display-controller 节点示例
以下是一个完整的 display-controller 节点示例,综合了上述三个核心属性及常用辅助属性:
display-controller@1e60000 {
compatible = "vendor,display-ctrl-v2", "vendor,display-ctrl";
reg = <0x01e60000 0x10000>,
<0x01e70000 0x1000>;
interrupts = <0 45 4>,
<0 46 4>;
interrupt-parent = <&gic>;
clocks = <&clkc DISPLAY_CLK>,
<&clkc DISPLAY_AXI_CLK>;
clock-names = "pclk", "axi";
resets = <&rstc DISPLAY_RST>;
status = "okay";
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
display_out: endpoint {
remote-endpoint = <&hdmi_in>;
};
};
};
};
/sys/firmware/devicetree/base/ 下对应节点的属性值是否与设备树源文件一致。使用 dtc -I dtb -O dts 反编译 DTB 文件,验证 compatible、reg、interrupts 是否被正确编译。
通过本节的学习,你应该能够:
- 理解 display-controller 节点的标准结构和命名规范
- 正确编写 compatible 属性,支持多版本硬件匹配
- 准确配置 reg 属性,描述寄存器地址空间
- 合理设置 interrupts 属性,定义中断资源
- 将三个核心属性组合成完整的 display-controller 节点