3. Linux 内核 I2C 子系统:I2C 核心层、总线驱动、设备驱动模型、设备树绑定

在嵌入式 Linux 系统中,FT5x06 与 GT911 等触控芯片均通过 I2C 总线与主控通信。理解 Linux I2C 子系统的分层架构,是驱动开发和性能调优的基础。本章将深入剖析 I2C 核心层、总线驱动、设备驱动模型以及设备树绑定的工作机制。

3.1 I2C 子系统整体架构

Linux I2C 子系统采用标准的分层设计,从上到下依次为:设备驱动层、核心层、总线驱动层。这种分层使得触控驱动开发者只需关注设备驱动层,而无需关心底层硬件差异。

关键概念: I2C 核心层是连接设备驱动与总线驱动的桥梁,提供统一的 API 接口、设备注册/注销机制以及总线访问方法。
Linux I2C 子系统分层架构 设备驱动层 (Device Driver) ft5x06_ts.c / gt9xx_ts.c 等触控驱动 I2C 核心层 (I2C Core) i2c-core.c / i2c-dev.c / 设备模型管理 总线驱动层 (Bus Adapter Driver) i2c-imx.c / i2c-s3c2410.c / i2c-omap.c 等 触控驱动通过 i2c_transfer() 等核心 API 与底层硬件隔离,实现跨平台兼容

3.2 I2C 核心层 (I2C Core)

I2C 核心层是子系统的中枢,主要职责包括:

  • 设备与驱动管理: 维护 i2c_client 和 i2c_driver 的注册、匹配、移除生命周期。
  • 总线访问抽象: 提供 i2c_transfer()、i2c_smbus_read_byte_data() 等统一 API。
  • 设备模型集成: 将 I2C 设备挂载到 Linux 设备模型 (device/driver/bus) 中。
  • 用户态接口: 通过 /dev/i2c-N 字符设备提供用户空间访问能力。
调优提示: 在触控驱动中,高频使用 i2c_transfer() 时,建议使用 struct i2c_msg 消息数组实现批量读写,减少总线锁定开销。

3.2.1 核心数据结构

数据结构 作用 触控驱动中的典型用法
struct i2c_client 描述一个 I2C 从设备(如触控芯片) 在 probe() 中通过 dev_get_drvdata() 获取
struct i2c_driver 描述 I2C 设备驱动 定义 probe/remove/id_table 回调
struct i2c_adapter 描述 I2C 总线控制器 通过 client->adapter 访问
struct i2c_msg 描述一次 I2C 传输事务 构造读/写消息数组,调用 i2c_transfer()

3.3 I2C 总线驱动 (Bus Adapter Driver)

总线驱动层直接操作硬件寄存器,实现 I2C 总线的时序控制。不同 SoC 平台需要不同的总线驱动,例如:

  • i2c-imx.c: NXP i.MX 系列
  • i2c-s3c2410.c: Samsung S3C/S5P 系列
  • i2c-omap.c: TI OMAP 系列
  • i2c-designware.c: Synopsys DesignWare I2C 控制器

总线驱动需要实现 struct i2c_algorithm 中的 master_xfer() 函数,该函数最终被核心层的 i2c_transfer() 调用。

/* i2c_algorithm 结构体核心成员 */
struct i2c_algorithm {
    int (*master_xfer)(struct i2c_adapter *adap,
                       struct i2c_msg *msgs, int num);
    int (*smbus_xfer)(struct i2c_adapter *adap, u16 addr,
                      unsigned short flags, char read_write,
                      u8 command, int size, union i2c_smbus_data *data);
    u32 (*functionality)(struct i2c_adapter *adap);
};
性能瓶颈: 总线驱动的 master_xfer() 实现质量直接影响触控报点率。低效的实现可能引入额外延迟,导致触摸响应滞后。调优时需关注总线时钟频率 (如 400kHz) 和传输合并策略。

3.4 I2C 设备驱动模型

Linux 设备驱动模型为 I2C 子系统提供了统一的设备-驱动匹配框架。触控驱动作为 I2C 设备驱动,遵循标准的 probe/remove 生命周期。

I2C 设备驱动模型匹配流程 设备树解析 of_i2c_register_devices() 创建 i2c_client i2c_new_client_device() 总线匹配 i2c_device_match() 调用 probe() 触控驱动初始化 注册输入设备 / 中断处理 input_register_device() / request_irq() 匹配依据:设备树 compatible 属性与 i2c_driver.id_table 中的 compatible 字符串

3.4.1 驱动注册示例

/* FT5x06 I2C 驱动结构体定义 */
static const struct i2c_device_id ft5x06_id[] = {
    { "ft5x06", 0 },
    { }
};
MODULE_DEVICE_TABLE(i2c, ft5x06_id);

static const struct of_device_id ft5x06_of_match[] = {
    { .compatible = "focaltech,ft5x06" },
    { }
};
MODULE_DEVICE_TABLE(of, ft5x06_of_match);

static struct i2c_driver ft5x06_driver = {
    .driver = {
        .name   = "ft5x06",
        .of_match_table = ft5x06_of_match,
    },
    .probe    = ft5x06_probe,
    .remove   = ft5x06_remove,
    .id_table = ft5x06_id,
};

module_i2c_driver(ft5x06_driver);

3.5 设备树绑定 (Device Tree Binding)

设备树 (Device Tree) 是描述硬件拓扑的扁平数据结构,用于在系统启动时向内核传递硬件配置信息。对于 I2C 触控设备,设备树节点需要描述:

  • compatible: 与驱动匹配的字符串
  • reg: I2C 从设备地址 (7位或10位)
  • interrupts: 触控中断引脚配置
  • reset-gpios / irq-gpios: 复位和中断 GPIO (可选)

3.5.1 FT5x06 设备树节点示例

&i2c1 {
    status = "okay";
    clock-frequency = <400000>;  /* 400kHz 高速模式 */

    ft5x06: touchscreen@38 {
        compatible = "focaltech,ft5x06";
        reg = <0x38>;
        interrupt-parent = <&gpio1>;
        interrupts = <13 IRQ_TYPE_EDGE_FALLING>;
        reset-gpios = <&gpio1 12 GPIO_ACTIVE_LOW>;
        touchscreen-size-x = <800>;
        touchscreen-size-y = <480>;
    };
};

3.5.2 GT911 设备树节点示例

&i2c2 {
    status = "okay";
    clock-frequency = <400000>;

    gt911: touchscreen@5d {
        compatible = "goodix,gt911";
        reg = <0x5d>;
        interrupt-parent = <&gpio3>;
        interrupts = <7 IRQ_TYPE_EDGE_RISING>;
        irq-gpios = <&gpio3 7 GPIO_ACTIVE_HIGH>;
        reset-gpios = <&gpio3 6 GPIO_ACTIVE_LOW>;
        touchscreen-size-x = <1024>;
        touchscreen-size-y = <600>;
    };
};
调优要点: 设备树中的 clock-frequency 直接影响触控数据读取速度。FT5x06 和 GT911 均支持 400kHz 快速模式,部分芯片可尝试 1MHz 高速模式,但需验证总线信号完整性。

3.6 本章小结

层级 核心文件/结构 触控调优关注点
I2C 核心层 i2c-core.c, struct i2c_msg 批量传输减少总线锁定
总线驱动层 master_xfer() 实现 时钟频率、传输合并策略
设备驱动模型 probe/remove 回调 中断注册时机、资源分配
设备树绑定 compatible, reg, interrupts 地址冲突、中断类型、GPIO 配置