Rockchip RK3588 kernel dts解析之GPIO Pinctrl
Rockchip RK3588 kernel dts解析之GPIO Pinctrl
文章目录
RK3588有5个GPIO控制器,每个控制器可以控制32个IO,作为GPIO功能时,端口行为由GPIO控制器寄存器配置。
There are five GPIOs (GPIO0 in PD_PMU,GPIO1/GPIO2/GPIO3/GPIO4 in PD_BUS)
GPIO的命令规则
- 控制器和GPIO控制器数量一致
- 端口固定 A、B、C和D
- 索引序号固定 0、1、2、3、4、5、6、7
IOMUX(输入输出复用)
Rockchip Pin可以复用成多种功能,同一个控制器如果存在多种复用引脚,一般叫做m0、m1、m2等等,如I2C控制器有两组复用引脚,分别是i2cm0、i2cm1。
引脚复用配置的可以查看datasheet的寄存器IOC,举例RK3588 BUS_IOC_GPIO1B_IOMUX_SEL_H Address: Operational Base + offset (0x002C)
gpio1b7_sel
4’h0: GPIO
4’h2: MIPI_CAMERA2_CLK_M0
4’h3: SPDIF1_TX_M0
4’h4: PCIE30X2_PERSTN_M3
4’h5: HDMI_RX_CEC_M2
4’h6: SATA2_ACT_LED_M1
4’h9: I2C5_SDA_M3
4’ha: UART1_RX_M1
4’hb: PWM13_M2
GPIO上下拉
GPIO 可以配置3种模式
- bias-disable
- bias-pull-up
- bias-pull-down
上下拉配置是作用于IO PAD,配置对GPIO/IOMUX都起作用。
GPIO驱动强度
RK3588 TRM中GPIO0_C7的驱动强度等级如下:
gpio0c7_ds
GPIO0C7 DS control Driver Strength Selection
3’b000: 100ohm
3’b100: 66ohm
3’b010: 50ohm
3’b110: 40ohm
3’b001: 33ohm
3’b101: 25ohm
软件驱动依然按照Level来处理,即上述寄存器描述对应:
3’b000: Level0
3’b100: Level4
3’b010: Level2
3’b110: Level6
3’b001: Level1
3’b101: Level5
DTS中drive-strength=<5>;
表示配置为Level5,即寄存器写3'b101
DTS介绍
RK3588的pinctrl的配置在rk3588s-pinctrl.dtsi
,这里面定义了RK3588芯片设计好的所有GPIO的功能,如
I2C2可以使用2组GPIO,分别是i2c2m0_xfer
和i2c2m1_xfer
i2c2m0_xfer: i2c2m0-xfer {
rockchip,pins =
/* i2c2_sclm0 */
<0 RK_PB5 1 &pcfg_pull_none_smt>,
/* i2c2_sdam0 */
<0 RK_PB6 1 &pcfg_pull_none_smt>;
};
/omit-if-no-ref/
i2c2m1_xfer: i2c2m1-xfer {
rockchip,pins =
/* i2c2_sclm1 */
<4 RK_PB5 1 &pcfg_pull_none_smt>,
/* i2c2_sdam1 */
<4 RK_PB4 1 &pcfg_pull_none_smt>;
};
可以根据硬件设计来配置对应的gpio,默认dts配置的都是m0,如果有硬件设计使用的不是m0则需要重新配置。修改方法如下
&i2c2 {
status = "okay";
pinctrl-0 = <&i2c2m1_xfer>;
};
新建pinctrl
rk3588s-pinctrl.dtsi文件已经枚举了rk3588s芯片所有iomux的实例,各模块一般不再需要创建iomux实例;创建iomux实例需要遵循如下规则:
-
必须在pinctrl节点下
-
必须以function+group的形式添加
-
function+group的格式如下
function { group { rockchip,pin = <bank gpio func &ref>; }; };
-
遵循其他dts的基本规则
引用pinctrl
模块引用pinctrl是通过 pinctrl-names
和 pinctrl-0
连接模块和pinctrl驱动。
举例 rk3588 uart2:
{
uart2: serial@feb50000 {
compatible = "rockchip,rk3588-uart", "snps,dw-apb-uart";
reg = <0x0 0xfeb50000 0x0 0x100>;
interrupts = <GIC_SPI 333 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cru SCLK_UART2>, <&cru PCLK_UART2>;
clock-names = "baudclk", "apb_pclk";
reg-shift = <2>;
reg-io-width = <4>;
dmas = <&dmac0 10>, <&dmac0 11>;
pinctrl-names = "default";
pinctrl-0 = <&uart2m1_xfer>;
status = "disabled";
};
};
uart2m1_xfer
是一个pinctrl group;模块可以同时引用多组group.
举例 rk3588 pdm1:
{
pdm1: pdm@fe4c0000 {
compatible = "rockchip,rk3588-pdm";
reg = <0x0 0xfe4c0000 0x0 0x1000>;
clocks = <&cru MCLK_PDM1>, <&cru HCLK_PDM1>;
clock-names = "pdm_clk", "pdm_hclk";
assigned-clocks = <&cru MCLK_PDM1>;
assigned-clock-parents = <&cru PLL_AUPLL>;
dmas = <&dmac1 4>;
dma-names = "rx";
power-domains = <&power RK3588_PD_AUDIO>;
pinctrl-names = "default";
pinctrl-0 = <&pdm1m0_clk
&pdm1m0_clk1
&pdm1m0_sdi0
&pdm1m0_sdi1
&pdm1m0_sdi2
&pdm1m0_sdi3>;
/* 等同于如下写法 */
/*
* pinctrl-0 = <&pdm1m0_clk>,
* <&pdm1m0_clk1>,
* <&pdm1m0_sdi0>,
* <&pdm1m0_sdi1>,
* <&pdm1m0_sdi2>,
* <&pdm1m0_sdi3>;
*/
#sound-dai-cells = <0>;
status = "disabled";
};
};
pinctrl-names
可以支持多个实例,pinctrl 默认的有4种实例(state):
#define PINCTRL_STATE_DEFAULT "default"
#define PINCTRL_STATE_INIT "init"
#define PINCTRL_STATE_IDLE "idle"
#define PINCTRL_STATE_SLEEP "sleep"
“init” 在driver probe期间生效,probe done之后可能会切换回 “default”(如果probe中切换到其他state,就不会切换回 “init”)。
pinctrl-names
是可以自定义的,有driver去匹配解析。
举例 rk3588 pwm4:
{
pwm4: pwm@febd0000 {
compatible = "rockchip,rk3588-pwm", "rockchip,rk3328-pwm";
reg = <0x0 0xfebd0000 0x0 0x10>;
#pwm-cells = <3>;
pinctrl-names = "active";
pinctrl-0 = <&pwm4m0_pins>;
clocks = <&cru CLK_PWM1>, <&cru PCLK_PWM1>;
clock-names = "pwm", "pclk";
status = "disabled";
};
};