linux pinctrl and gpio driver
- Pinctrl: 负责引脚的功能复用(MUX)和电气属性配置(上下拉,驱动能力等).
- GPIO: 负责管理GPIO的输入输出,高低电平和中断.
芯片刚通电、Linux 还没启动时,几乎所有引脚的默认状态都是 GPIO 输入模式(且内部电阻断开,处于高阻态 High-Z)。
为什么?因为如果默认是输出高电平,而外部电路刚好接地,一通电芯片就烧了。默认设为“毫无防备的输入状态”是最安全的。只有少数几个用于调试的引脚(比如 UART 串口、JTAG),硬件工程师会设计成一上电就默认连通,方便开发者抓开机日志。
Pinctrl
只负责搭建好物理通路和电气环境
- Pin Enumeration (引脚枚举):
- 内核启动时,Pinctrl 驱动要做的第一件事就是向内核的 Pinctrl Core 注册:“我这个芯片一共有 128 个引脚,编号从 0 到 127,它们的名字分别叫 PA0, PA1…”。这通过 struct pinctrl_pin_desc 结构体数组实现。
- Pin Muxing (引脚复用 - struct pinmux_ops):
- 将引脚组合成 Group(组),并将 Group 映射到 Function(功能)。
- Group:比如引脚 10 和 11 组成一个叫 i2c0_pins 的组。
- Function:比如这个组可以提供 i2c0 功能。
- 底层动作:当设备树请求这个功能时,内核调用你写的 set_mux 回调函数,你的代码去写底层的物理寄存器(比如向 0xd401xxxx 写入特定掩码),拨动物理开关。
- Pin Configuration (引脚配置 - struct pinconf_ops):
设置引脚的电气属性。当设备树里写了 bias-pull-up; 时,内核会解析这个属性,并调用你驱动里的 pin_config_set 回调函数,去写芯片的上下拉寄存器。
K1 pinctrl & gpio 节点
1 | |
pinctrl 驱动操作集关键函数:
- dt_node_to_map
1 | |
- set_mux
1 | |
- pin_config_set
之前内核把设备树里的 bias-pull-up = <0> 解析成了宏 PIN_CONFIG_BIAS_PULL_UP。现在,轮到把宏变成具体的寄存器位
1 | |
- spacemit_pinconf_dbg_show
输入这行命令时:cat /sys/kernel/debug/pinctrl/d401e000.pinctrl-spacemit,k1-pinctrl/pinconf-pins
内核回调 dbg_show 函数
1 | |
- gpio_request_enable: spacemit_request_gpio
1 | |
当在外部的 GPIO 驱动里调用申请引脚时,内核底层就会间接触发 Pinctrl 里的这个 gpio_request_enable 函数,自动完成硬件级别的 Mux 切换.
GPIO
引脚的配置主要分为 “自动档” 和 “手动档”。
really_probe() 托管 (常见)
触发条件:只要在设备树节点里写了 pinctrl-names = “default”; 和 pinctrl-0 = <&xxx>;。在执行你的 probe 之前,内核调用 really_probe() -> pinctrl_bind_pins()。引脚自动切换到正确模式。直接在驱动里操作 UART 寄存器就行了。驱动内部申请 (GPIO)
- 2.1 这主要发生在 GPIO 子系统 介入的时候。
如果不是在写一个标准的 UART 驱动,而是在写一个点灯程序或者按键驱动(使用 GPIO 模式)
操作函数:你会调用 devm_gpiod_get() 或 gpio_request()。
申请 GPIO 44。GPIO 子系统发现这个引脚属于某个 Pinctrl 范围。GPIO 子系统会背地里调用 Pinctrl 框架的 pinctrl_gpio_request()。Pinctrl 框架再调用你 Pinctrl 驱动里的 set_mux,把这个引脚物理上切到“GPIO 功能”。
这种方式下,是 GPIO 驱动在指挥 Pinctrl 驱动。 - 2.2 需要动态切换引脚状态
比如一个 SD 卡驱动:
平时:工作在 default 状态(高速模式)。
休眠时:为了省电,需要切换到 sleep 状态(把引脚设为输入,防止漏电)。
pinctrl_select_state(p->p, p->pins_sleep);
这虽然是“手动”切换,但它操作的是 Pinctrl 中预设好的状态,而不是去申请单个引脚。
linux pinctrl and gpio driver
https://goko-son626.github.io/post/linux-pinctrl-and-gpio-driver.html

