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。
  • 失败: 返回负数错误码。
posted @ 2026-04-16 09:38  r5ett  阅读(99)  评论(0)    收藏  举报