提示:完善设备IIC设备节点和驱动
文章目录
- 前言
- 一、参考资料
- 二、设备树-设备节点描述
-
- [MIPI屏-FT5X06 原理图](#MIPI屏-FT5X06 原理图)
- AI-参考根据原理图自动生成相关配置
-
- 原理图引脚对应关系(先锁定硬件)
-
- [1. 触摸中断引脚 TP_INT_L_GPIO3_A5](#1. 触摸中断引脚 TP_INT_L_GPIO3_A5)
- [2. 触摸复位引脚 TP_RST_L_GPIO0_B6](#2. 触摸复位引脚 TP_RST_L_GPIO0_B6)
- [3、补充 I2C 总线复用引脚(配套参考)](#3、补充 I2C 总线复用引脚(配套参考))
- [GPIO 基础配置(设备树 dts 语法)](#GPIO 基础配置(设备树 dts 语法))
-
- [1. 中断引脚 TP_INT_L_GPIO3_A5](#1. 中断引脚 TP_INT_L_GPIO3_A5)
-
- [设备树触摸节点属性(对应你的 my-ft5x06@38)](#设备树触摸节点属性(对应你的 my-ft5x06@38))
- 参数拆解
- [2. 复位引脚 TP_RST_L_GPIO0_B6](#2. 复位引脚 TP_RST_L_GPIO0_B6)
- [Pinctrl 引脚复用核心规则(RK 平台重点)](#Pinctrl 引脚复用核心规则(RK 平台重点))
- 设备树配置复位和终端硬件连接信息
-
- 配置复位脚
- 配置中断脚
- 配置pinctrl复用
-
- [疑难解惑 myft5x06_pins:myft5x06-pins 配置符号](#疑难解惑 myft5x06_pins:myft5x06-pins 配置符号)
-
- [① 冒号前 myft5x06_pins:节点 Label(标签)](#① 冒号前 myft5x06_pins:节点 Label(标签))
- [② 冒号后 myft5x06-pins:节点名称 name](#② 冒号后 myft5x06-pins:节点名称 name)
- 一句话解释两者横线区别
- 设备树中复位和中断完整配置
- 三、驱动编写-完善FT5X06驱动
- 总结
前言
如前面Linux驱动-i2c 驱动框架编写,自定了节点,描述自定义的IIC 设备树来描述硬件实验。 这里我们完善设备节点并写驱动。
一、参考资料
最基本的一定要了解gpio 基本知识点和pinctrl基本知识点:配置和相关API
GPIO 控制和操作-使用命令通过sysfs文件系统控制GPIO
二、设备树-设备节点描述
MIPI屏-FT5X06 原理图

如图,mipi 对应的地板原理图描述,我们要做的就是根据地板原理图来进行设备树修改,也就是进行硬件描述,最终目的是给驱动调用。
AI-参考根据原理图自动生成相关配置
最初,我是根据经验和以前总结知识点进行配AI-置,后来发现AI 能完成大部分工作,至少帮助理解特别有用。
原理图引脚对应关系(先锁定硬件)
1. 触摸中断引脚 TP_INT_L_GPIO3_A5
- 板上信号名:TP_INT_L_GPIO3_A5
- RK3568 GPIO 编号:GPIO3_A5
- FPC 座引脚:J8 Pin25 TP_INT
- 电平特性:后缀_L = 低电平有效,触摸按下时拉低触发中断
2. 触摸复位引脚 TP_RST_L_GPIO0_B6
- 板上信号名:TP_RST_L_GPIO0_B6
- RK3568 GPIO 编号:GPIO0_B6
- FPC 座引脚:J8 Pin26 TP_RST
- 电平特性:后缀_L = 低电平复位,正常工作拉高
3、补充 I2C 总线复用引脚(配套参考)
- I2C1_SCL_TP → GPIO0_B4(硬件 I2C 复用功能)
- I2C1_SDA_TP → GPIO0_B5(硬件 I2C 复用功能)
GPIO 基础配置(设备树 dts 语法)
1. 中断引脚 TP_INT_L_GPIO3_A5
设备树触摸节点属性(对应你的 my-ft5x06@38)
java
my-ft5x06: my-ft5x06@38 {
compatible = "my-ft5x06";
reg = <0x38>;
// 中断配置:父控制器是gpio3
interrupt-parent = <&gpio3>;
// RK_PA5 = GPIO3_A5,低电平触发
interrupts = <RK_PA5 IRQ_TYPE_LEVEL_LOW>;
// 触摸驱动标准属性,传递中断gpio
touch-gpio = <&gpio3 RK_PA5 IRQ_TYPE_EDGE_RISING>;
// 复位引脚配置
reset-gpio = <&gpio0 RK_PB6 GPIO_ACTIVE_LOW>;
};
参数拆解
- interrupt-parent = <&gpio3>:中断控制器挂载在 GPIO3 组;
- RK_PA5:GPIO3_A5 宏定义;
- IRQ_TYPE_LEVEL_LOW:低电平触发中断(匹配原理图TP_INT_L);
- touch-gpio:ft5x06 驱动专用属性,读取中断引脚;
- reset-gpio = <&gpio0 RK_PB6 GPIO_ACTIVE_LOW>:
java
&gpio0:复位引脚属于 GPIO0 组;
RK_PB6:GPIO0_B6;
GPIO_ACTIVE_LOW:低电平有效复位。
2. 复位引脚 TP_RST_L_GPIO0_B6
驱动内部逻辑:
上电 probe 时,内核驱动自动拉低该 GPIO 一段时间,拉高释放复位,完成 FT5x06 初始化。
Pinctrl 引脚复用核心规则(RK 平台重点)
java
gpio3_int_tp: gpio3-int-tp {
gpios = <&gpio3 RK_PA5 GPIO_INPUT>;
status = "okay";
};
gpio0_rst_tp: gpio0-rst-tp {
gpios = <&gpio0 RK_PB6 GPIO_OUTPUT_HIGH>;
status = "okay";
};
设备树配置复位和终端硬件连接信息
配置复位脚
java
reset-gpio =<&gpio0 RK_PB6 GPIO_ACTIVE_LOW>;
- 复位引脚的属性reset-gpio 是可以随便写的,这个最终是驱动里面自己去匹配的。
- 原理图上面是:GPIO0_B6
配置中断脚
java
# 描述中断的属性名称可不能随便写
# 描述中断类型
interrupt-parent= <&gpio3> 描述中断控制器用的是哪一个类型 TP_INT_L_GPIO3_A5
# 描述中断gpio 信息
interrupts-gpio = <&gpio3 RK_PA5 GPIO_ACTIVE_LOW> 描述gpio io 口,设置低电平有效
# 描述中断方式
interrupts = <RK_PA5 IRO_TYPE_LEVEL_LOW>
- 其实这里有三个必备属性:中断类型、中断信息、中断方式
- 宏定义:RK_PA5 这个是宏定义,不要问为什么。
配置pinctrl复用
配置pinctrl 复用,就是配置这个GPIO 口就是给我用的,实际还需要检查一下系统里面有没有默认给其它功能用。
java
就需要pin-ctrl 子系统
pinctrl-names = "default";
pinctrl-0 = <&myft5x06_pins>
然后在pinctrl 里面配置好复用功能:
java
myft5x06{
myft5x06_pins:myft5x06-pins{
// 在这里写复用功能
rockchip,pins = <0 RK_PB6 RK_FUNC_GPIO &pcfg_pull_up>, <3 RK_PA5 R K_FUNC_GPIO &pcfg_pull_up>
}
}
疑难解惑 myft5x06_pins:myft5x06-pins 配置符号
① 冒号前 myft5x06_pins:节点 Label(标签)
- 规则:只能用字母、数字、下划线 _,不能用横杠 -;
- 作用:全局唯一别名,别处用 &myft5x06_pins 引用这个 pinctrl 配置。
② 冒号后 myft5x06-pins:节点名称 name
- 规则:设备树节点名允许下划线、横杠 -,只是语义标识,无引用作用;
- 行业习惯:pinctrl 节点名字统一用 - 分隔,可读性更好。
一句话解释两者横线区别
- Label(标签):只能 _ 下划线,不能 -;
- Node Name(节点名):可用 - 横杠,仅做标识;
所以标准写法:
java
myft5x06_pins: myft5x06-pins {
...
};
设备树中复位和中断完整配置
基于以上基本知识点,配置如下:
路径:
java
&i2c1 {
status = "okay";
myft5x06: my-ft5x06@38 {
compatible = "my-ft5x06";
reg = <0x38>;
reset-gpios = <&gpio0 RK_PB6 GPIO_ACTIVE_LOW>;
interrupt-parent = <&gpio3>;
interrupts-gpio = <&gpio3 RK_PA5 GPIO_ACTIVE_LOW>;
interrupts = <RK_PA5 IRQ_TYPE_LEVEL_LOW>;
pinctrl-names = "default";
pinctrl-0 = <&myft5x06_pins>;
};
};
&pinctrl {
myft5x06 {
myft5x06_pins: myft5x06-pins {
rockchip,pins =
<0 RK_PB6 RK_FUNC_GPIO &pcfg_pull_none>,
<3 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>;
};
};
};
三、驱动编写-完善FT5X06驱动
基本API 参考: Linux驱动-GPIO基本函数api
我们目标就是通过驱动程序去获取、操作 gpio 硬件,然后看中断是否触发
驱动程序编写
java
#include <linux/init.h>
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/of_device.h>
#include <linux/gpio/consumer.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
struct gpio_desc *reset_gpio;
struct gpio_desc *irq_gpio;
irqreturn_t ft5x06_handler(int irq,void *args){
printk("==========ft5x06_handler==========\n");
return IRQ_RETVAL(IRQ_HANDLED);
}
int ft5x06_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
int ret=0;
printk(KERN_INFO "###### This is ft5x06 probe ######\n");
// 获取复位GPIO描述符
reset_gpio = gpiod_get_optional(&client->dev, "reset", 0); // 第二个参数是属性(reset-gpios)前缀reset
if (reset_gpio == NULL)
{
printk("gpiod_get_optional reset_gpio error\n");
return -1;
}
// 获取中断GPIO描述符
irq_gpio = gpiod_get_optional(&client->dev, "interrupts", 0); // 第二个参数是属性(interrupts-gpio)前缀interrupts
if (irq_gpio == NULL)
{
printk("gpiod_get_optional irq_gpio error\n");
return -1;
}
gpiod_direction_output(reset_gpio, 0);
ssleep(5);
gpiod_direction_output(reset_gpio, 1);
ret = request_irq(client->irq,ft5x06_handler,IRQF_TRIGGER_FALLING | IRQF_ONESHOT,"ft5x06_irq",NULL);
if (ret < 0)
{
printk("request_irq request error\n");
return -1;
}
return 0;
}
int ft5x06_remove(struct i2c_client *client)
{
printk(KERN_INFO "###### This is ft5x06_remove ######\n");
return 0;
}
static const struct of_device_id ft5x06_id[] = {
{ .compatible = "my-ft5x06" },
{ /* Sentinel */ },
};
// 关键补充
MODULE_DEVICE_TABLE(of, ft5x06_id);
static struct i2c_driver ft5x06_driver = {
.driver = {
.owner = THIS_MODULE,
.name = "my-ft5x06",
.of_match_table = ft5x06_id,
},
.probe = ft5x06_probe,
.remove = ft5x06_remove,
};
static int __init ft5x06_driver_init(void)
{
int ret;
ret = i2c_add_driver(&ft5x06_driver);
if (ret < 0) {
printk(KERN_ERR "i2c_add_driver failed ret=%d\n", ret);
return ret;
}
printk(KERN_INFO "###### ft5x06 driver register success ######\n");
return 0;
}
static void __exit ft5x06_driver_exit(void)
{
i2c_del_driver(&ft5x06_driver);
printk(KERN_INFO "###### ft5x06 driver unregister ######\n");
}
module_init(ft5x06_driver_init);
module_exit(ft5x06_driver_exit);
MODULE_LICENSE("GPL");
驱动程序实验
编译驱动文件,然后push 到目录下,加载驱动并触摸屏幕看打印日志:
编译驱动
java
#!/bin/bash
export ARCH=arm64
export CROSS_COMPILE=aarch64-linux-gnu-
obj-m += ft5x06_driver.o
KDIR :=/home/topeet/wfc/RK3568Linux/rk356x_linux/kernel
PWD ?= $(shell pwd)
all:
make -C $(KDIR) M=$(PWD) modules
clean:
make -C $(KDIR) M=$(PWD) clean
生成 ft5x06_driver.ko 驱动文件
执行驱动-看日志打印
加载驱动 insmod ft5x06_driver.ko ,看内核日志
日志如下,说明中断配置和驱动代码没有问题的。

总结
- 这里在i2c 基础框架上加了复位和终端,并实际操作验证。
- 框架方法,里面用到了基本都是之前的gpio、pinctrl 复用、中断、平台总线思想等基础知识,需要融汇贯通,涉及到的知识点需要了解并掌握。