07、设备树中Pinctrl的描述
📢本篇将介绍pinctrl
设备树的使用方法。
一、 DTS介绍
以下是更直白的解释:
在RK芯片的设备树里,pinctrl节点通常放在soc.dtsi文件(比如rk3568.dtsi)的最后。它的特点有:
- 结构不同:pinctrl节点没有像其他设备那样直接写寄存器地址(没有reg属性)。
- 传递地址方式:它通过"rockchip,grf = <&grf>"这行代码,告诉驱动"基础寄存器地址在这里"。
- 驱动用法:驱动会用这个基础地址 + 具体偏移量,来设置引脚的功能(比如让引脚变成SPI或USB信号线)和调整引脚参数(比如电平高低)。
- 对比GPIO:而GPIO的配置则直接通过gpio节点里的reg属性,直接指定具体的寄存器地址来控制电平。
简单总结:pinctrl是"告诉驱动基础地址,再让驱动自己计算具体位置",GPIO则是"直接告诉驱动具体寄存器位置"。就像买奶茶:pinctrl是说"去那家店,第三排第二个",而GPIO是直接"拿着店员给的现成奶茶"。
目录 arch/arm64/boot/dts/rockchip/rk3568.dtsi
C
pinctrl: pinctrl {
compatible = "rockchip,rk3568-pinctrl";
rockchip,grf = <&grf>;
rockchip,pmu = <&pmugrf>;
#address-cells = <2>;
#size-cells = <2>;
ranges;
gpio0: gpio0@fdd60000 {
compatible = "rockchip,gpio-bank";
reg = <0x0 0xfdd60000 0x0 0x100>;
interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&pmucru PCLK_GPIO0>, <&pmucru DBCLK_GPIO0>;
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
};
gpio1: gpio1@fe740000 {
compatible = "rockchip,gpio-bank";
reg = <0x0 0xfe740000 0x0 0x100>;
interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cru PCLK_GPIO1>, <&cru DBCLK_GPIO1>;
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
};
gpio2: gpio2@fe750000 {
compatible = "rockchip,gpio-bank";
reg = <0x0 0xfe750000 0x0 0x100>;
interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cru PCLK_GPIO2>, <&cru DBCLK_GPIO2>;
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
};
gpio3: gpio3@fe760000 {
compatible = "rockchip,gpio-bank";
reg = <0x0 0xfe760000 0x0 0x100>;
interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cru PCLK_GPIO3>, <&cru DBCLK_GPIO3>;
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
};
gpio4: gpio4@fe770000 {
compatible = "rockchip,gpio-bank";
reg = <0x0 0xfe770000 0x0 0x100>;
interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cru PCLK_GPIO4>, <&cru DBCLK_GPIO4>;
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
};
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
在arch/arm64/boot/dts/rockchip/rk3568-pinctrl.dtsi
文件中还存在通过引用的方式配置pinctrl
C
&pinctrl {
acodec {
/omit-if-no-ref/
acodec_pins: acodec-pins {
rockchip,pins =
/* acodec_adc_sync */
<1 RK_PB1 5 &pcfg_pull_none>,
/* acodec_adcclk */
<1 RK_PA1 5 &pcfg_pull_none>,
/* acodec_adcdata */
<1 RK_PA0 5 &pcfg_pull_none>,
/* acodec_dac_datal */
<1 RK_PA7 5 &pcfg_pull_none>,
/* acodec_dac_datar */
<1 RK_PB0 5 &pcfg_pull_none>,
/* acodec_dacclk */
<1 RK_PA3 5 &pcfg_pull_none>,
/* acodec_dacsync */
<1 RK_PA5 5 &pcfg_pull_none>;
};
};
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
二、新建pinctrl
rk3568-pinctrl.dtsi
⽂件已经枚举了rk3566芯⽚所有iomux
的实例,各模块⼀般不再需要创建iomux
实例;
若需要创建iomux
实例需要遵循如下规则:
- 必须在
pinctrl
节点下 - 必须以
function
+group
的形式添加 function
+group
的格式如下
C
function {
group {
rockchip,pin = <bank gpio func &ref>;
};
};
1
2
3
4
5
2
3
4
5
- 遵循其他dts的基本规则
三、引用pinctrl
模块引⽤pinctrl
是通过 pinctrl-names
和 pinctrl-0
连接模块和pinctrl
驱动。举例:uart2:
C
uart0: serial@fdd50000 {
compatible = "rockchip,rk3568-uart", "snps,dw-apb-uart";
reg = <0x0 0xfdd50000 0x0 0x100>;
interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&pmucru SCLK_UART0>, <&pmucru PCLK_UART0>;
clock-names = "baudclk", "apb_pclk";
reg-shift = <2>;
reg-io-width = <4>;
dmas = <&dmac0 0>, <&dmac0 1>;
pinctrl-names = "default";
pinctrl-0 = <&uart0_xfer>;
status = "disabled";
};
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
uart0_xfer
是⼀个pinctrl group
;
模块可以同时引⽤多组group
,例如:
C
spi0: spi@fe610000 {
compatible = "rockchip,rk3066-spi";
reg = <0x0 0xfe610000 0x0 0x1000>;
interrupts = <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>;
#address-cells = <1>;
#size-cells = <0>;
clocks = <&cru CLK_SPI0>, <&cru PCLK_SPI0>;
clock-names = "spiclk", "apb_pclk";
dmas = <&dmac0 20>, <&dmac0 21>;
dma-names = "tx", "rx";
pinctrl-names = "default", "high_speed";
pinctrl-0 = <&spi0m0_cs0 &spi0m0_cs1 &spi0m0_pins>;
pinctrl-1 = <&spi0m0_cs0 &spi0m0_cs1 &spi0m0_pins_hs>;
num-cs = <2>;
status = "disabled";
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
pinctrl-names
可以支持多个实例(state
),pinctrl
默认提供了4种实例:
C
#define PINCTRL_STATE_DEFAULT "default"
#define PINCTRL_STATE_INIT "init"
#define PINCTRL_STATE_IDLE "idle"
#define PINCTRL_STATE_SLEEP "sleep"
1
2
3
4
2
3
4
"init"
在driver probe
期间⽣效,probe done
之后可能会切换回 "default"
(如果probe
中切换到其他state
,就不会切换回 "init"
)。pinctrl-names
是可以⾃定义的,可以在driver
中去匹配解析。
C
pwm0: pwm@fdd70000 {
compatible = "rockchip,rk3568-pwm", "rockchip,rk3328-pwm";
reg = <0x0 0xfdd70000 0x0 0x10>;
interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;
#pwm-cells = <3>;
pinctrl-names = "active";
pinctrl-0 = <&pwm0m0_pins>;
clocks = <&pmucru CLK_PWM0>, <&pmucru PCLK_PWM0>;
clock-names = "pwm", "pclk";
status = "disabled";
};
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11