当前位置:   article > 正文

Pinctrl的配置与使用

pinctrl

https://blog.csdn.net/spongebob1912/article/details/109496964
https://blog.csdn.net/weixin_44555609/article/details/127906297

简述

soc内部管脚众多,而多数管脚又可以配置成不同的功能,我们称之为管脚复用;Linux引入pinctrl子系统,是为了统一各芯片厂商对这些管脚的管理跟配置。

通过调整pinctrl寄存器,我们可以配置一个或一组管脚,配置项包括function、上拉下拉、驱动强度等,下面仅从使用者的角度介绍pinctrl在实践中的应用。

应用实例

1.管脚定义

高通平台为例,在dts文件夹中我们会找到名为pinctrl的dtsi,里面配置了几乎所有用到的管脚,个别里面没有配置的管脚默认用作gpio,以下面一组管脚为例。

/* interrupt active */
pmx_ts_int_active {
	ts_int_active: ts_int_active {
		mux {
			pins = "gpio65";
			function = "gpio";
		};
 
		config {
			pins = "gpio65";
			drive-strength = <8>;
			bias-pull-up;
		};
	};
};
/* interrupt suspend */
pmx_ts_int_suspend {
	ts_int_suspend: ts_int_suspend {
		mux {
			pins = "gpio65";
			function = "gpio";
		};
 
		config {
			pins = "gpio65";
			drive-strength = <2>;
			bias-pull-down;
		};
	};
};
  • 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

里面定义了一个管脚的两种状态,分别是active状态管脚gpio65,function gpio内置上拉,强度为8;suspend状态管脚gpio65,function gpio内置下拉,强度为2;

2.pinctrl state定义

为设备添加自己的管脚定义,这个过程我们称之为pinctrl state定义;

pinctrl-names = "cyttsp_ts_active",
	"cyttsp_ts_suspend","cyttsp_ts_release";
pinctrl-0 = <&ts_int_active &ts_reset_active>;
pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>;
pinctrl-2 = <&ts_release>;
  • 1
  • 2
  • 3
  • 4
  • 5

dts中某个设备的节点中添加如上引用,三个pinctrl name分别对应下面三个pinctrl-x,每个pinctrl-x我们称之为一个pinctrl state,后续我们将在代码中通过name来找到相应的pinctrl state;

每组pinctrl state可以引用多个管脚定义。

3.pinctrl state切换

在完成管脚定义及pinctrl state定义之后,我们将在代码中获取pinctrl state,并使用他们;

#define PINCTRL_STATE_ACTIVE	"cyttsp_ts_active"
#define PINCTRL_STATE_SUSPEND	"cyttsp_ts_suspend"
#define PINCTRL_STATE_RELEASE	"cyttsp_ts_release"
 
struct pinctrl *ts_pinctrl;
struct pinctrl_state *pinctrl_state;
 
/* get pinctrl handle */
ts_pinctrl = devm_pinctrl_get(dev);
if (IS_ERR_OR_NULL(ts_pinctrl)) {
	rc = PTR_ERR(ts_pinctrl);
	dev_err(dev, "%s: Target does not use pinctrl %d\n", __func__, rc);
	return rc;
}
 
/* find pinctrl state by name */
pinctrl_state = pinctrl_lookup_state(ts_pinctrl, PINCTRL_STATE_ACTIVE);
if (IS_ERR_OR_NULL(pinctrl_state)) {
	rc = PTR_ERR(pinctrl_state);
	dev_err(dev, "%s: Can not lookup cyttsp_ts_active pinstate %d\n", __func__, rc);
	return rc;
}
 
/* select the pinctrl state */
rc = pinctrl_select_state(ts_pinctrl, pinctrl_state);
if (rc < 0)
	dev_err(dev, "%s: Cannot get active pinctrl state\n", __func__);
  • 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

1.获取pinctrl handler,每个设备都会有自己的pinctrl handler,如果没有,调用接口时将为它创建一个

源码参考/kernel/msm-3.18/drivers/pinctrl/core.c create_pinctrl();

2.得到pinctrl handler后,我们通过dts里配置的pinctrl-name,找到相应的pinctrl state;

示例中找的是cyttsp_ts_active,对应dts里的state为pinctrl-0,该state包含两个管脚定义,分别是ts_int_active,ts_reset_active,具体定义到pinctrl dtsi里面查看;

3.找到相应的pinctrl state,只需调用pinctrl接口切换至该state即可,相应管脚即可切换为pinctrl dtsi中定义的状态;

示例中将切换至ts_int_active状态,相应的管脚gpio65将被配置为gpio,内置上拉,强度为8,其他管脚同理。

补充说明

在驱动跟设备成功匹配后,驱动探测时将获取该设备名为default的pinctrl state,并切换至该state,这个过程中就会调用devm_pinctrl_get,获取或创建pinctrl handler;

若相应dts节点没有定义名为default的pinctrl state,则输出日志后返回,执行driver probe;

具体源码请参考/kernel/msm-3.18/drivers/base/dd.c really_probe()

pinctrl-0 / pinctrl-name 的调用过程

以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";
	};
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

模块引用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";
	};
};
  • 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

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"
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

“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";
	};
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/330340
推荐阅读
相关标签
  

闽ICP备14008679号