Pinctrl子系统
Pinctrl 子系统的作用就是:负责引脚的复用(Mux)和电气特性的配置(Config)。
1. 主要还是用设备树
在讲 API 之前,必须先澄清一个让很多新手困惑的事实:在 95% 的驱动开发中,你不需要在 C 代码里写任何一行 Pinctrl 的代码!
为什么?因为 Linux 设备模型(Device Core)在调用你的 probe 函数之前,会自动去设备树(DTS)里寻找 pinctrl 相关的属性,并帮你把引脚配置好。
典型的设备树写法:
&i2c1 {
status = "okay";
/* 下面这两行就是告诉内核:当这个设备激活时,去配置引脚 */
pinctrl-names = "default", "sleep";
pinctrl-0 = <&i2c1_xfer>; /* 默认状态的引脚配置 */
pinctrl-1 = <&i2c1_sleep>; /* 休眠状态的引脚配置 */
};
只要你在设备树里写了 pinctrl-names = "default" 和 pinctrl-0,内核会在 probe 前自动应用 default 状态。
那么,什么时候我们需要在代码里调用 Pinctrl API 呢?
当你的驱动需要在运行时动态切换引脚状态时(例如:系统进入低功耗模式时,把引脚从 default 切换到 sleep 状态;或者将一个引脚在 PWM 功能和 GPIO 功能之间来回切换)。
2. 常用数据结构 (Consumer 端)
对于驱动开发者(消费者)来说,我们只关心以下两个不透明的结构体(即我们只拿指针,不看内部细节):
2.1 struct pinctrl
struct pinctrl {
struct list_head node; /* 链表节点:用于将该句柄挂载到全局 pinctrl 句柄链表中 */
struct device *dev; /* 设备指针:指向持有该 pinctrl 句柄的消费者设备(即你的驱动设备) */
struct list_head states; /* 状态链表:该设备拥有的所有状态(如 default, sleep)都挂在这里 */
struct pinctrl_state *state; /* 当前状态:指向当前正在生效的引脚状态结构体 */
struct list_head dt_maps; /* 设备树映射链表:存放从设备树(DTS)解析出来的引脚映射表 */
struct kref users; /* 引用计数:用于管理该 pinctrl 实例的生命周期,防止被提前释放 */
};
2.2 struct pinctrl_state
struct pinctrl_state {
struct list_head node; /* 链表节点:用于将该状态挂载到 struct pinctrl 的 states 链表中 */
const char *name; /* 状态名称:对应设备树 pinctrl-names 中的字符串(如 "default", "sleep") */
struct list_head settings; /* 设置链表:该状态下所有具体的引脚设置(mux 或 config)都挂在这里 */
};
3. 核心函数与宏
3.1 struct pinctrl *devm_pinctrl_get(struct device *dev)
作用:获取指定设备的 Pinctrl 句柄。它会解析设备树中与该设备关联的所有引脚配置。带有 devm_ 前缀,意味着它是资源托管型的,当驱动卸载时,内核会自动调用 put 释放句柄。
参数:dev:指向当前硬件设备的指针 (struct device *)。
返回值:
- 成功: 返回指向 struct pinctrl 的指针。
- 失败: 返回错误指针。必须使用 IS_ERR() 宏来检查,并通过 PTR_ERR() 获取错误码。
3.2 void devm_pinctrl_put(struct pinctrl *p)
作用:显式释放通过 devm_pinctrl_get 获取的句柄。
参数:p:待释放的 struct pinctrl 指针。
3.3 struct pinctrl_state *pinctrl_lookup_state(struct pinctrl *p, const char *name)
作用:在 Pinctrl 句柄中根据名称查找具体的引脚状态(如 "default", "sleep", "idle")。
参数:
- p:由 get 函数获取的 Pinctrl 句柄。
- name:状态名称字符串。这必须与设备树 pinctrl-names 属性中定义的字符串完全一致。
返回值:
- 成功: 返回指向 struct pinctrl_state 的指针。
- 失败: 返回错误指针(需用 IS_ERR() 检查)。
3.4 int pinctrl_select_state(struct pinctrl *p, struct pinctrl_state *state)
作用:将指定的引脚状态立即应用到物理硬件上。此时,内核会操作 SoC 的寄存器,改变引脚的复用功能(Mux)和电气特性(Config)。
参数:
- p:Pinctrl 句柄。
- state:由 lookup 函数获取的目标状态指针。
返回值:
- 成功: 返回 0。
- 失败: 返回负数错误码。

浙公网安备 33010602011771号