您现在的位置是:首页 >技术教程 >RK3588 设备树pinctrl gpio子系统解析,解决GPIO无法正确拉高拉低的问题,RK3588设备树详解网站首页技术教程
RK3588 设备树pinctrl gpio子系统解析,解决GPIO无法正确拉高拉低的问题,RK3588设备树详解
一、RK3588设备树结构
firefly的官方说明文档RK3588gpio系统说明
function {
group {
rockchip,pin = <bank gpio func &ref>;
};
};
其中,bank是所属的组,Core-3588J 有 5 组 GPIO bank:GPIO0-GPIO4,每组又以 A0-A7, B0-B7, C0-C7, D0-D7 作为编号区分。
首先,对于firefly的rk3588j的开发板,其设备树有几个比较重要的文件,
分别是/kernel/arch/arm64/boot/dts/rockchip/rk3588s-pinctrl.dtsi
;
/kernel/arch/arm64/boot/dts/rockchip/rk3588s.dtsi
;
kernel/arch/arm64/boot/dts/rockchip/rk3588-firefly-itx-3588j.dtsi
;
/kernel/arch/arm64/boot/dts/rockchip/rk3588.dtsi
;
这个几个文件将其外围设备基本描述完全了,另外还有一些可能位于/kernel/arch/arm64/boot/dts/rockchip/rk3588-diff.dtsi
内,
第一个文件rk3588s-pinctrl.dtsi,该文件枚举了3588所有的iomux实例(3588s和3588是firefly的两款开发板,频脚基本一致,所有有些3588会引用3588s的设备树文件);例如rk3588s-pinctrl.dtsi文件中关于uart6的设备树描述:
上图是串口6的一个设备树,
rockchip,pins =
/* uart6_rx_m1 */
<1 RK_PA0 10 &pcfg_pull_up>,
该描述就是说明使用的引脚是GPIO1_A0;
可以看到4个引脚rx/tx/rtsn/ctsn。另外多了一个rx/tx是串口6的复用,这里是将串口6的所有可以的复用全部罗列出来,其他的外设也是类似,最终实际用的哪一路复用在文件rk3588-firefly-itx-3588j.dtsi中确定,还是串口6,在该文件中的描述为:
二、RK3588 GPIO口上拉下拉失败
在调试中发现有些gpio口无法正确的实现上下拉,其原因在于该io口被其他外设复用使能。解决方法就是将该外设disabled。
上下拉设置方法:
:/ # ls /sys/class/gpio/
export gpiochip128 gpiochip32 gpiochip64 unexport
gpiochip0 gpiochip200 gpiochip509 gpiochip96
:/ # echo 56 > /sys/class/gpio/export
:/ # ls /sys/class/gpio/
export gpiochip0 gpiochip200 gpiochip509 gpiochip96
gpio56 gpiochip128 gpiochip32 gpiochip64 unexport
:/ # ls /sys/class/gpio/gpio56
active_low device direction edge power subsystem uevent value
:/ # cat /sys/class/gpio/gpio56/direction
in
:/ # cat /sys/class/gpio/gpio56/value
0
以GPIO3_D4为例,该IO口在原开发板上被用作了HDMI1的rx引脚,其设备树描述位于rk3588-firefly-itx-3588j.dtsi
文件中,如下:
hdmim1_rx是一个设备使用gpio引脚的描述,在文件rk3588.dtsi
中被引用,如下:
但是我们发现其实,该外设在此文件中的状态是disabled,其实,一般而言,每个厂家的芯片可能对应很多开发板,有些开发板没有这个功能,有些开发板有这个功能,因此,在公共文件中一般都会把该芯片支持的共有外设都失能,然后在开发板对应的文件中再使能,这里就是如此。
打开文件rk3588-firefly-itx-3588j.dtsi
找到hdmirx_ctrler,可以看到
我们只需要将okay改成disabled即可。
三、RK3588频脚计算方式
与一般的计算方式没有区别:
GPIO pin脚计算公式:pin = bank * 32 + number
GPIO 小组编号计算公式:number = group * 8 + X
以下,摘自官网:
下面演示GPIO1_D0 pin脚计算方法:
bank = 1; //GPIO1_D0 => 1, bank ∈ [0,4]
group = 3; //GPIO1_D0 => 3, group ∈ {(A=0), (B=1), (C=2), (D=3)}
X = 0; //GPIO1_D0 => 0, X ∈ [0,7]
number = group * 8 + X = 3 * 8 + 0 = 24
pin = bank*32 + number= 1 * 32 + 24 = 56;
GPIO1_D0 对应的设备树属性描述为:<&gpio1 24 GPIO_ACTIVE_HIGH>,由kernel-5.10/include/dt-bindings/pinctrl/rockchip.h的宏定义可知,也可以将GPIO1_D0描述为<&gpio1 RK_PD0 GPIO_ACTIVE_HIGH>。
另外提供个简单的计算小程序源码:
#include <stdio.h>
#include <stdlib.h>
int main()
{
while(1){
char gpio_group;
int bank;
int X;
int group;
printf("++++++++++++++++++++++++++++++++++++++++++++
");
printf("bank number eg.GPIO1_D2,bank is 1
");
printf("group number eg.GPIO1_D2,group is 'D'
");
printf("code number eg.GPIO1_D2,code is 2
");
printf("++++++++++++++++++++++++++++++++++++++++++++
");
printf("Input Example:1,d,2
");
scanf("%d,%c,%d", &bank,&gpio_group,&X);
switch (gpio_group)
{
case 'a':
case 'A'/* constant-expression */:
/* code */
group = 0;
break;
case 'b':
case 'B':
group = 1;
break;
case 'c':
case 'C':
group = 2;
break;
case 'd':
case 'D':
group = 3;
break;
default:
printf("group number error!
");
return 1;
break;
};
int number = group * 8 + X ;
int pin = bank*32 + number;
printf("GPIO pin is %d
", pin);
system("pause");}
return 0;
}
只需要输入bank,code和序号即可,例如计算GPIO1_D0 ,输入1,D,0
回车:
引脚为56号。
最后:虽然由于每家芯片的驱动不同,设备树的书写格式可能有所不同,但是基本的设备树格式都是一样的。大道至简,殊途同归。