瑞芯微RK3568芯片是一款定位中高端的通用型SOC,采用22nm制程工艺,搭载一颗四核Cortex-A55处理器和Mali G52 2EE 图形处理器。RK3568 支持4K 解码和 1080P 编码,支持SATA/PCIE/USB3.0 外围接口。RK3568内置独立NPU,可用于轻量级人工智能应用。RK3568 支持安卓 11 和 linux 系统,主要面向物联网网关、NVR 存储、工控平板、工业检测、工控盒、卡拉 OK、云终端、车载中控等行业。
【公众号】迅为电子
【粉丝群】824412014(加群获取驱动文档+例程)
【视频观看】嵌入式学习之Linux驱动(第七期_设备树_全新升级)_基于RK3568
【购买链接】迅为RK3568开发板瑞芯微Linux安卓鸿蒙ARM核心板人工智能AI主板
第60章 实例分析:GPIO
60.1 GPIO相关属性
60.1.1 RK ft5x06设备树节点
下面展示的是iTOP-RK3568开发板SDK源码中的ft5x06设备树,其中蓝色字体部分就是关于gpio相关的描述,包括了interrupts、 interrupt-controller、#interrupt-cells、interrupt-parent四种常见属性:
gpio0: gpio@fdd60000 {
compatible = "rockchip,gpio-bank";
reg = <0x0 0xfdd60000 0x0 0x100>;
interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&pmucru PCLK_GPI00>, <&pmucru DBCLK_GPI00>;
gpio-controller;
#gpio-cells = <2>;
gpio-ranges = <&pinctrl 0 0 32>;
interrupt-controller;
#interrupt-cells = <2>;
};
ft5x06: ft5x06@38 {
status = "disabled";
compatible = "edt,edt-ft5306";
reg = <0x38>;
touch-gpio = <&gpio0 RK_PB5 IRQ_TYPE_EDGE_RISING>;
interrupt-parent = <&gpio0>;
interrupts = <RK_PB5 IRQ_TYPE_LEVEL_LOW>;
reset-gpios = <&gpio0 RK_PB6 GPIO_ACTIVE_LOW>;
touchscreen-size-x = <800>;
touchscreen-size-y = <1280>;
touch_type = <1>;
};
其中gpio0节点是在内核源码的“/arch/arm64/boot/dts/rockchip/rk3568.dtsi”设备树的3549-3560行定义的,而ft5x06: ft5x06@38触摸芯片节点是在内核源码的“/arch/arm64/boot/dts/rockchip/topeet_rk3568_lcds.dtsi”设备树的301-313行定义的。接下来将会对设备树常见的四个gpio属性进行介绍。
60.1.2 gpio-controller
gpio-controller属性用于标识一个设备节点作为GPIO控制器。GPIO控制器是负责管理和控制GPIO引脚的硬件模块或驱动程序。
gpio-controller属性通常作为设备节点的一个属性出现,位于设备节点的属性列表中。
当一个设备节点被标识为GPIO控制器时,它通常会定义一组GPIO引脚,并提供相关的GPIO控制和配置功能。其他设备节点可以使用该GPIO控制器来控制和管理其GPIO引脚。
通过使用gpio-controller属性,设备树可以明确标识出GPIO控制器设备节点,使系统可以正确识别和管理GPIO引脚的配置和控制。
60.1.3 #gpio-cells
#gpio-cells属性用于指定GPIO引脚描述符的编码方式。GPIO引脚描述符是用于标识和配置GPIO引脚的一组值,例如引脚编号、引脚属性等。
#gpio-cells属性的属性值是一个整数,表示用于编码GPIO引脚描述符的单元数。通常,这个值为2。
在第一小节的示例中有1个gpio引脚描述属性,由于#gpio-cells属性被设置为了2,所以每个引脚描述属性中会有两个整数,具体内容如下所示:
ft5x06: ft5x06@38 {
.....
reset-gpios = <&gpio0 RK_PB6 GPIO_ACTIVE_LOW>;
.....
};
RK_PB6、GPIO_ACTIVE_LOW都属于恒定义,会在下面的小节进行讲解。
通过使用#gpio-cells属性,设备树可以指定GPIO引脚描述符的编码方式,使系统能够正确识别和解析GPIO引脚的配置和控制。
60.1.4 gpio-ranges
gpio-ranges属性是设备树中一个用于描述GPIO范围映射的属性。它通常用于描述具有大量GPIO引脚的GPIO控制器,以简化GPIO引脚的编码和访问。
在设备树中,GPIO控制器的每个引脚都有一个本地编号,用于在控制器内部进行引脚寻址。然而,这些本地编号并不一定与外部引脚的物理编号或其他系统中使用的编号一致。为了解决这个问题,可以使用gpio-ranges属性将本地编号映射到实际的引脚编号。
gpio-ranges属性是一个包含一系列整数值的列表,每个整数值对应于设备树中的一个GPIO控制器。列表中的每个整数值按照特定的顺序提供以下信息:
(1)外部引脚编号的起始值。
(2)GPIO控制器内部本地编号的起始值。
(3)引脚范围的大小(引脚数量)。
在第一小节的示例中gpio-ranges属性的值为<&pinctrl 0 0 32>,其中<&pinctrl>表示引用了名为pinctrl的引脚控制器节点,0 0 32表示外部引脚从0开始,控制器本地编号从0开始,共映射了32个引脚。
这样,gpio-ranges属性将GPIO控制器的本地编号直接映射到外部引脚编号,使得GPIO引脚的编码和访问更加简洁和直观。
60.1.5 gpio引脚描述属性
第一小节的设备树中关于gpio引脚描述属性相关内容如下所示:
ft5x06: ft5x06@38 {
.....
reset-gpios = <&gpio0 RK_PB6 GPIO_ACTIVE_LOW>;
.....
};
gpio引脚描述属性个数由#gpio-cells所决定,因为gpio0节点中的#gpio-cells属性设置为了2,所以上面设备树gpio引脚描述属性个数也为2。
其中RK_PB6 定义在内核源码目录下的“include/dt-bindings/pinctrl/rockchip.h”头文件中,定义了RK引脚名和gpio编号的宏定义,如下图(图 60-1)所示:
图 60-1
GPIO_ACTIVE_LOW定义在源码目录下的“include/dt-bindings/gpio/gpio.h”中,表示设置为低电平,同理GPIO_ACTIVE_HIGH就表示将这个GPIO设置为高电平,但这里只是对设备的描述,具体的设置还是要跟驱动相匹配。
60.1.6其他属性
本小节将根据下面的设备树示例讲解一下gpio的其他重要属性,设备树具体内容如下所示:
gpio-controller@00000000 {
compatible = "foo";
reg = <0x00000000 0x1000>;
gpio-controller;
#gpio-cells = <2>;
ngpios = <18>;
gpio-reserved-ranges = <0 4>, <12 2>;
gpio-line-names = "MMC-CD", "MMC-WP",
"voD eth", "RST eth", "LED R",
"LED G", "LED B", "col A",
"col B", "col C", "col D",
"NMI button", "Row A", "Row B",
"Row C", "Row D", "poweroff",
"reset";
};
第6行的ngpios 属性指定了 GPIO 控制器所支持的 GPIO 引脚数量。它表示该设备上可用的 GPIO 引脚的总数。在这个例子中,ngpios` 的值为 18,意味着该 GPIO 控制器支持 18 个 GPIO 引脚。
第7行的gpio-reserved-ranges属性定义了保留的GPIO范围。每个范围由两个整数值表示,用尖括号括起来。保留的GPIO范围意味着这些GPIO引脚不可用或已被其他设备或功能保留。在这个例子中,有两个保留范围:<0 4>和<12 2>。<0 4>表示从第0个引脚开始的连续4个引脚被保留,而<12 2>表示从第12个引脚开始的连续2个引脚被保留。
第8行的gpio-line-names 属性定义了GPIO引脚的名称,以逗号分隔。每个名称对应一个 GPIO 引脚。这些名称用于标识和识别每个GPIO引脚的作用或连接的设备。在这个例子中,gpio-line-names属性列出了多个GPIO引脚的名称,如 "MMC-CD"、"MMC-WP"、"voD eth" 等等。通过这些名称,可以清楚地了解每个GPIO引脚的功能或用途。
60.2 中断实例编写
在上一个小节中对设备树中断要用到的属性进行了讲解,而在本小节将会编写一个在RK3568上LED灯的中断设备树。
首先确定LED的引脚编号,LED原理图如下图(图 60-2)所示:
图 60-2
从上面的原理图可以得到LED灯的引脚网络标号为Working_LEDEN_H_GPIO0_B7,对应的引脚为GPIO0_B7。
然后来查看内核源码目录下的“drivers/drivers/leds/leds-gpio.c”文件,这是led的驱动文件,然后找到compatible匹配值相关的部分,如下(图 60-3)所示:
图 60-3
可以看到compatible匹配值为gpio-leds。
最后在内核源码目录下的“include/dt-bindings/pinctrl/rockchip.h”头文件中,定义了RK引脚名和gpio编号的宏定义,如下图(图 60-4)所示:
图 60-4
在源码目录下的“include/dt-bindings/gpio/gpio.h”文件中定义了引脚极性设置宏定义,如下图(图 60-5)所示:
图 60-5
其中GPIO_ACTIVE_HIGH表示将该引脚设置为高电平,GPIO_ACTIVE_LOW表示将该引脚设置为低电平。
至此,我们关于编写LED设备树的前置内容就查找完成了,接下来进行设备树的编写。
编写完成的设备树如下所示:
/dts-v1/;
#include "dt-bindings/pinctrl/rockchip.h"
#include "dt-bindings/gpio/gpio.h"
/{
model = "This is my devicetree!";
led led@1 {
compatible = "gpio-leds";
gpios = <&gpio0 RK_PB7 GPIO_ACTIVE_HIGH>
};
};
第1行: 设备树文件的头部,指定了使用的设备树语法版本。
第3行:用于定义 Rockchip 平台的引脚控制器相关的绑定。
第4行:用于定义中断控制器相关的绑定。
第5行:表示设备树的根节点开始。
第6行:指定了设备树的模型名称,描述为 "This is my devicetree!"。
第9行:指定了设备节点的兼容性字符串,表示该设备与 "gpio-leds" 兼容。
第10行:指定了该 LED 设备所使用的 GPIO 引脚。&gpio0 是引脚控制器的引用,RK_PB7 是引脚的编号或标识,GPIO_ACTIVE_HIGH 表示该 GPIO 引脚的活动电平是高电平。
至此,关于led的设备树就讲解完成了。
60.3 其他SOC设备树对比
而无论使用的是瑞芯微SOC还是恩智浦、三星的SOC,在设备树关于gpio相关的描述都是类似的,关于在恩智浦和三星源码中的ft5x06设备树如下所示(关于gpio相关的属性已经标记为了蓝色):
恩智浦
gpio1: gpio@0209c000 {
compatible = "fsl,inx6ul-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>;
edt-ft5x06@38 {
compatible = "edt,edt-ft5306", "edt,edt-ft5x06", "edt,edt-ft5406";
pinctrl-names = "default";
pinctrl-0 = <&ts_int_pin &ts_reset_pin>;
reg = <0x38>;
interrupt-parent = <&gpio1>;
interrupts = <9 0>;
reset-gpios = <&gpio5 9 GPIO_ACTIVE_LOW>;
irq-gpios = <&gpio1 9 GPIO_ACTIVE_LOW>;
status = "disabled";
};
};
三星
gpio_c: gpioc {
compatible = "gpio-controller";
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
};
ft5x06: ft5x06038 {
compatible = "edt,edt-ft5406";
reg = <0x38>;
pinctrl-names = "default";
#if defined(RGB_1024x600) || defined(RGB_800x480)
pinctrl-0 = <&tsc2007_irq>;
interrupt-parent = <&gpio_c>;
interrupts = <26 IRQ_TYPE_EDGE_FALLING>;
#endif
#if defined(LvDs_800×1280) || defined(LvDS_1024x768)
pinctrl-0 = <>911_irq>;
interrupt-parent = <&gpio_b>;
interrupts = <29 IRQ_TYPE_EDGE_FALLING>;
#endif
reset-gpios = <&gpio_e 30 0>;
};
对比之后会发现,不同厂商对于gpio的配置都是类似的,只是里面的参数有些许区别,如果大家在之后遇到了其他平台,只需要稍加区分即可。