以RK平台为例:
Rockchip pinctrl驱动包括Pinctrl驱动( drivers/pinctrl/pinctrl-rockchip.c ) 和 GPIO驱动
( drivers/gpio/gpio-rockchip.c )。
Pinctrl驱动是主要驱动,提供IO的方法集,包括PINMUX、PINCONF 和 GPIO。
GPIO驱动是完成 gpiochip 的功能,包括 GPIO 和 IRQ
通常在 dts 配置中可以看到某个模块中对 pin 引脚的配置,如下所示
注:通常模块调用pinctrl-names pinctrl-0配置默认的IOMUX或者IOCONFIG,但不是所有的节点都可以加这两个属性,如果模块被driver_probe_device调用,它就可以加这两个属性。
调试方法: drivers/base/dd.c 的 pinctrl_bind_pins 函数,在这里加打印看调用关系。
{
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";
};
};
模块引用pinctrl是通过 pinctrl-names 和 pinctrl-0 连接模块和pinctrl驱动。
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)。
在Documentation/driver-api/pinctl.rst 文档中有相应的描述
###include/linux/pinctrl/pinctrl-state.h
#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去匹配解析,如下
{
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";
};
};