GPIO 控制器节点基础

GPIO(General Purpose Input/Output)控制器是嵌入式系统中最基础、最常用的外设之一。在设备树中,GPIO 控制器节点必须按照标准规范进行描述,以便内核能够正确识别、初始化并管理这些引脚资源。本节将详细解析 GPIO 控制器节点的标准定义、核心属性及其语义。

2.1 标准节点结构

一个完整的 GPIO 控制器节点通常包含以下核心属性:

属性名 类型 是否必需 描述
compatible 字符串列表 必需 指定驱动兼容性,格式为 "厂商,型号"
reg 地址/长度对 必需 描述控制器寄存器基地址和地址范围
gpio-controller 空属性 必需 标记该节点为 GPIO 控制器
#gpio-cells 整数 必需 指定 GPIO 描述符所需的单元数
interrupt-parent phandle 可选 指定中断控制器父节点
interrupts 中断描述符 可选 描述 GPIO 控制器的中断线
ngpios 整数 可选 指定该控制器管理的 GPIO 引脚总数
关键概念: gpio-controller 是一个布尔属性,只要存在即表示该节点是 GPIO 控制器;#gpio-cells 则定义了引用该控制器时每个 GPIO 描述符需要几个 32 位整数单元。

2.2 典型节点定义示例

以下是一个基于 ARM 平台(如 i.MX6ULL)的 GPIO 控制器节点定义:

gpio1: gpio@0209c000 {
    compatible = "fsl,imx6ul-gpio", "fsl,imx35-gpio";
    reg = <0x0209c000 0x4000>;
    interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>,
                 <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>;
    gpio-controller;
    #gpio-cells = <2>;
    interrupt-controller;
    #interrupt-cells = <2>;
    ngpios = <32>;
};

该示例中:

  • compatible:使用 fallback 机制,优先匹配 "fsl,imx6ul-gpio",若不匹配则回退到 "fsl,imx35-gpio"。
  • reg:寄存器基地址为 0x0209c000,地址范围为 0x4000(16KB)。
  • interrupts:该控制器支持两路中断(通常对应低 16 位和高 16 位引脚)。
  • #gpio-cells = <2>:每个 GPIO 描述符由两个单元组成——第一个单元为引脚号,第二个单元为标志位。
  • ngpios:明确声明该控制器管理 32 个 GPIO 引脚。

2.3 #gpio-cells 的语义解析

#gpio-cells 的值决定了其他设备节点如何引用该 GPIO 控制器的引脚。最常见的值为 2,其单元含义如下:

单元索引 名称 描述 示例值
0 引脚号 从 0 开始的 GPIO 引脚索引 15
1 标志位 GPIO 配置标志(低电平有效、上拉等) 0x0000(默认)

标志位(flags)的常用定义(Linux 内核 gpio.h):

  • 0x0000:默认,高电平有效,无特殊配置。
  • GPIO_ACTIVE_LOW (0x0001):低电平有效。
  • GPIO_OPEN_DRAIN (0x0010):开漏输出。
  • GPIO_OPEN_SOURCE (0x0020):开源输出。
  • GPIO_PULL_UP (0x0040):内部上拉使能。
  • GPIO_PULL_DOWN (0x0080):内部下拉使能。
实践建议: 当 #gpio-cells = <1> 时,引用方只需提供引脚号,标志位默认为 0。这种简化适用于不需要特殊配置的简单 GPIO 使用场景。

2.4 GPIO 控制器节点结构图

下图展示了 GPIO 控制器节点在设备树中的位置及其与周边节点的关系:

GPIO 控制器节点结构图 / (根节点) soc@0 aips-bus@02000000 gpio1: gpio@0209c000 compatible / reg / gpio-controller / #gpio-cells 标识属性 • compatible • reg • ngpios • status GPIO 功能属性 • gpio-controller • #gpio-cells • gpio-ranges • line-names 中断相关属性 • interrupt-controller • #interrupt-cells • interrupts • interrupt-parent 说明:GPIO 控制器节点通过 gpio-controller 和 #gpio-cells 两个核心属性向系统声明其 GPIO 资源管理能力

2.5 属性详解与常见陷阱

2.5.1 compatible 属性

该属性是驱动匹配的关键。推荐使用"厂商,型号"格式,并保留 fallback 兼容字符串:

compatible = "vendor,soc-gpio", "vendor,family-gpio";

内核驱动匹配时,会按照字符串顺序依次尝试,直到找到匹配的驱动。

2.5.2 reg 属性

描述 GPIO 控制器的寄存器地址空间。对于 32 位 ARM 平台,格式为 <基地址 地址长度>:

reg = <0x0209c000 0x4000>;  // 基地址 0x0209c000,长度 16KB
常见错误: 地址长度设置过小会导致内核无法完整访问寄存器空间,引发驱动初始化失败。务必参考芯片手册确认 GPIO 模块的寄存器地址范围。

2.5.3 gpio-controller 与 #gpio-cells

这两个属性必须成对出现。缺少 gpio-controller 会导致其他节点无法引用该控制器的 GPIO;#gpio-cells 值错误会导致 GPIO 描述符解析异常。

2.6 多控制器实例对比

控制器 compatible #gpio-cells ngpios 中断支持
GPIO1 fsl,imx6ul-gpio 2 32 是(2 路)
GPIO2 fsl,imx6ul-gpio 2 32 是(2 路)
GPIO5 fsl,imx6ul-gpio 2 8 是(1 路)

从表中可以看出,同一 SoC 的不同 GPIO 控制器可能具有不同的引脚数量和中断能力,这些差异都需要在设备树中准确描述。

2.7 引用 GPIO 控制器的标准方式

其他设备节点通过 gpios 或 xxx-gpios 属性引用 GPIO 引脚:

leds {
    compatible = "gpio-leds";
    led-red {
        label = "red-led";
        gpios = <&gpio1 15 GPIO_ACTIVE_LOW>;
        linux,default-trigger = "heartbeat";
    };
};

button {
    compatible = "gpio-keys";
    power-key {
        label = "power";
        gpios = <&gpio2 3 GPIO_ACTIVE_LOW>;
        linux,code = <KEY_POWER>;
    };
};

引用格式解析:&gpio1 指向 GPIO 控制器节点,15 为引脚号,GPIO_ACTIVE_LOW 为标志位。这三个值正好对应 #gpio-cells = <2> 的规格。

2.8 本章小结

  • GPIO 控制器节点必须包含 compatible、reg、gpio-controller 和 #gpio-cells 四个核心属性。
  • #gpio-cells 决定了 GPIO 描述符的格式,最常见的值为 2(引脚号 + 标志位)。
  • 标志位用于配置 GPIO 的电气特性,如电平有效极性、上下拉、开漏等。
  • 其他设备通过 gpios 属性引用 GPIO 引脚,格式必须与目标控制器的 #gpio-cells 一致。
  • 准确的节点定义是 GPIO 子系统正常工作的基础,任何属性缺失或错误都可能导致驱动加载失败或引脚操作异常。