4.3.5. Pinctrl 调试指南
4.3.5.1. 概述
Pinctrl (Pin Control) 是 Linux 内核
4.3.5.2. 特点
芯片
多功能
引脚 :支持 GPIO、UART、SPI、I2C、PWM 等控制 多种 功能。 引脚
方向 :可以与 电平 配置 设置 引脚 的 输入/输出 方向 及 输出 电平(高/低)。 引脚
复用 :支持引脚 功能 的 复用(MUX_ALT),使得 一个 引脚 可以 承载 多种 功能。 电气
特性 :设置配置 上拉/下 拉 电阻、开漏 输出 等 电气 特性。 设备树
支持 :通过设备树(DTS)配置 引脚 的 功能 和 电气 特性。 灵活
的 :支持引脚 分配 根据 需求 动态分配 引脚 功能 和 接口。 可扩展性:支持
根据 定制 化 硬件 需求 进行 扩展 配置。
4.3.5.3. 功能描述
Pinctrl 典型应用

例如,在 Linux 系统
Pinctrl 功能原理
Pinctrl 的

主控
1. 解析
设备树
中 的 pinctrl 配置 通常 定义 了 引脚 的 功能、复用 模式、驱动 配置 等。主控 通过 解析 这些 设备树 属性 来 获取 硬件 引脚 的 配置 信息。
2. 主控
主控
在 驱动 中 通过 horizon_pinctrl_probe函数初始化 硬件 引脚 控制器。这 一步 包括 分配内存、设置 设备树 的 引脚 控制 信息 以及 解析 GPIO bank(引脚组)配置。 horizon_pinctrl_parse_gpio_bank:解析设备树 中 与 GPIO 引脚 组 相关 的 信息,为 硬件 控制器 初始化 引脚 组 配置。 horizon_pinctrl_probe_dt:进一步解析 设备树 中 的 pinctrl 配置,读取 引脚 复用 (muxing)、电气 配置 (如 上 拉、下 拉)等 设置。
3. 设备
使用
devm_pinctrl_register_and_init注册引脚 控制器。该 函数 初始化 设备,创建 必要 的 设备 结构,并 使 主控 能够 使用 该 引脚 控制器
4. 引脚
引脚
的 配置 和 状态 通过 pinctrl_commit_state函数应用。设备树 中 的 状态(如 默认 状态、睡眠 状态 等)通过 pinctrl_select_state 函数 进行 设置。这 使得 主控 能够 控制 引脚 的 不同 工作 模式。
5. 引脚
主控
通过 pin_request函数请求 特定 引脚。每个 引脚 在 使用 前 必须 被“请求”并 分配 给 某个 功能(如 GPIO 或 其他 设备 功能)。请求 时会 检查 引脚 是否 已 被 占用,确保 没有 冲突。
6. 设备树
pinctrl 通过
pinmux_enable_setting来设置 引脚 的 复用 模式。这些 设置 根据 设备树 中 定义 的 复用 配置(horizon,pins)来 选择 适当 的 功能。
Pinctrl 工作方式
Pinctrl 和 GPIO 子系统
在 Linux 中,GPIO 操作

传统
获取
设备树 中 的 引脚 信息。 根据
获取 到 的 引脚 信息 配置 引脚 的 复用 功能。 根据
获取 到 的 pin 信息 来 设置 pin 的 电气 特性,比如 上/下 拉、速度、驱动 能力 等。
Pinctrl 子系统结构

如上图
驱动代码
Kernel Space
kernel/drivers/pinctrl/hobot/aon.c # Pinctrl 驱动代码源文件
kernel/drivers/pinctrl/hobot/common.c # Pinctrl 驱动代码源文件
kernel/drivers/pinctrl/hobot/display.c # Pinctrl 驱动代码源文件
kernel/drivers/pinctrl/hobot/dsp.c # Pinctrl 驱动代码源文件
kernel/drivers/pinctrl/hobot/hsio.c # Pinctrl 驱动代码源文件
kernel/drivers/pinctrl/hobot/lsio.c # Pinctrl 驱动代码源文件
kernel/drivers/pinctrl/hobot/common.h # Pinctrl 驱动代码头文件
内核配置
CONFIG_PINCTRL_SINGLE

Pinctrl的DTS配置
Pinctrl 控制器arch/arm64/boot/dts/hobot/x5.dtsi文件
4.3.5.4. Pinctrl使用
驱动DTS配置
在
示例:
设备树
/* arch/arm64/boot/dts/hobot/x5-evb.dts */
&uart2 {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_uart2>;
};
引脚
/* arch/arm64/boot/dts/hobot/pinmux-func.dtsi */
pinctrl_uart2: uart2grp {
horizon,pins = <
LSIO_UART2_RX LSIO_PINMUX_3 BIT_OFFSET16 MUX_ALT0 &pconf_drv_pu_mid_3v3
LSIO_UART2_TX LSIO_PINMUX_3 BIT_OFFSET18 MUX_ALT0 &pconf_drv_pu_mid_3v3
>;
};
};
这
&uart2:这个
节点 指 的 是 一个 名为 uart2 的 硬件 外设,通常 在 设备树 中,& 符号 表示 引用 一个 已经 在 其他 地方 定义 的 外设。这个 节点 表明 你 启用 了 UART2 外设,并且 它 的 状态 是 “okay”,即 表示 该 外设 处于 启用 状态。 status:这
行 代码 表明 启用 UART2 外设。 pinctrl-names:定义
引脚 控制(pin control)名 “default” 代表 引脚 控制 的 默认 状态。 pinctrl-0: 表示
将 引脚 控制 配置 为 名为 pinctrl_uart2 的 配置 节点,具体 配置 信息 如下: pinctrl_uart2: uart2grp:这
定义 了 一个 名为 uart2grp 的 引脚 组,并 给 它 起 了 一个 标签 pinctrl_uart2,用于 其他 地方 引用。 horizon,pins = <…>:该行
描述 了 UART2 的 两个 引脚 配置,包括 接收 引脚(LSIO_UART2_RX)和 发送 引脚(LSIO_UART2_TX)。每个 引脚 由 四个 部分 组成: 引脚
名称(LSIO_UART2_RX 和 LSIO_UART2_TX) :这代表 UART2 接收(RX)和 发送(TX)引脚,标识 了 这 两个 引脚 在 硬件 上 的 位置。 引脚
复用(LSIO_PINMUX_3) :代表引脚 的 复用 组。 偏移量(BIT_OFFSET16 和 BIT_OFFSET18):这些
是 与 引脚 相关 的 位 偏移,用于 定位 引脚 在 寄存器 中 的 位置。 引脚
复用 :MUX_ALT0 表示功能(MUX_ALT0) 引脚 的 复用 模式。在 这种 情况 下,表示 引脚 被 配置 为 UART 功能(而 非 其他 功能)。 驱动
配置(&pconf_drv_pu_mid_3v3) :这表示 引脚 的 驱动 配置,引用 了 一个 驱动 配置 节点 pconf_drv_pu_mid_3v3,它 定义 了 引脚 的 电气 属性,如 电压 域、上下 拉、驱动力 等。
另外
/* arch/arm64/boot/dts/hobot/pinmux-gpio.dtsi */
lsio_gpio0_8: lsio_gpio0_8 {
horizon,pins = <
LSIO_UART2_RX LSIO_PINMUX_3 BIT_OFFSET16 MUX_ALT2 &pconf_input_en_3v3
>;
};
lsio_gpio0_9: lsio_gpio0_9 {
horizon,pins = <
LSIO_UART2_TX LSIO_PINMUX_3 BIT_OFFSET18 MUX_ALT2 &pconf_input_en_3v3
>;
};
lsio_gpio0_8: lsio_gpio0_8:这是
一个 GPIO 引脚 的 配置 节点,表示 gpio0_8 引脚 的 设置。该 引脚 被 配置 为 与 LSIO_UART2_RX(UART2 的 接收 引脚)相对 应 的 GPIO 引脚。 horizon,pins = <…>:描述
了 该 引脚 的 复用 设置。这部分 的 内容 与 上面 的 UART2 配置 类似,不同 的 是 MUX_ALT2 代表 该 引脚 复用 功能 为 GPIO。 &pconf_input_en_3v3:引用
一个 名为 pconf_input_en_3v3 的 引脚 驱动 配置,表示 该 引脚 配置 为 输入 模式 并且 使用 3.3V 电压。
设备树
Pin-mux配置 :用于
引脚 配置 某个 功能,最 多 支持4种 功能。 MUX_ALT0 0x0
MUX_ALT1 0x1
MUX_ALT2 0x2
MUX_ALT3 0x3
drive-strength :引脚
电流 的 驱动 级,详细 驱动力 对应 表 如下:
IOL Low Level Output Current @VOL (max) = 0.125*VDDIO
| DS (Drive Strength) | Typical Current | Unit |
|---|---|---|
| 0b0000 | 3.8 | mA |
| 0b0001 | 5.7 | mA |
| 0b0010 | 7.5 | mA |
| 0b0011 | 9.4 | mA |
| 0b0100 | 11.3 | mA |
| 0b0101 | 13.2 | mA |
| 0b0110 | 15.0 | mA |
| 0b0111 | 16.9 | mA |
| 0b1000 | 18.8 | mA |
| 0b1001 | 20.7 | mA |
| 0b1010 | 22.6 | mA |
| 0b1011 | 24.4 | mA |
| 0b1100 | 26.3 | mA |
| 0b1101 | 28.2 | mA |
| 0b1110 | 30.0 | mA |
| 0b1111 | 31.9 | mA |
IOH High Level Output Current @VOH (min) = 0.75*VDDIO
| DS (Drive Strength) | Typical Current | Unit |
|---|---|---|
| 0b0000 | 5.3 | mA |
| 0b0001 | 7.9 | mA |
| 0b0010 | 10.6 | mA |
| 0b0011 | 13.2 | mA |
| 0b0100 | 15.8 | mA |
| 0b0101 | 18.5 | mA |
| 0b0110 | 21.1 | mA |
| 0b0111 | 23.7 | mA |
| 0b1000 | 26.3 | mA |
| 0b1001 | 29.0 | mA |
| 0b1010 | 31.6 | mA |
| 0b1011 | 34.2 | mA |
| 0b1100 | 36.9 | mA |
| 0b1101 | 39.5 | mA |
| 0b1110 | 42.1 | mA |
| 0b1111 | 44.7 | mA |
上下
拉 配置 :每个Pin脚 也 支持 上下 拉 配置,在arch/arm64/boot/dts/hobot/pinmux-func.dtsi可以 设置 默认 配置,可 支持 的 上下 拉 配置 有: bias-pull-up
bias-disable
bias-pull-down
施密特
触发 配置 :施密特 触发器 能够 有效 地 去除 输入 信号 的 噪声 并 稳定 其 输出,密特 触发器 的 核心 特点 是 它 有 一个 上下 阈值,只有 当 输入 信号 穿越 这些 阈值 时,输出 才 会 改变。
每个
第一列:0x38,代表pin reg,例如LSIO的
基 地址 为0x3418_0000,则 对应 lsio_uart2_txd_pu 地址 = 基 地址 + pin reg 。 第二列:lsio_pin_ctrl_12,代表
寄存器 地址 名。 第三列:RW,RW 通常
表示 寄存器 或 内存 区域 的 访问 权限。它 意味着 该 区域 的 内容 可以 被 读取(Read)和 写入(Write) 第四
列:偏移 比特 位,代表 对应 寄存器 区域 地址。 第五
列:对应 寄存器 的 区域。 第六
列:代表 该 寄存器 功能 的 默认值。 第七
列:代表 不同 寄存器 的 功能 描述,例如 上下 拉,施密特 触发,电压 域,驱动力。
| 0x38 | lsio_pin_ctrl_12 | RW | [31] | lsio_uart2_ms | 0x0 | SDIO mode select for PAD LSIO_UART2_TXD,LSIO_UART2_RXD, LSIO_UART3_TXD, LSIO_UART3_RXD, LSIO_UART4_TXD, LSIO_UART4_RXD, 0: 3.3v; 1: 1.8v |
|---|---|---|---|---|---|---|
| RSV | [30:15] | RSV | 0x0 | reserved bits | ||
| RW | [14] | lsio_uart2_txd_pu | 0x0 | lsio_uart2_txd pull up enable: 1: pull up enable; 0: pull up disable; | ||
| RW | [13] | lsio_uart2_txd_pd | 0x0 | lsio_uart2_txd pull down enable: 1: pull down enable; 0: pull down disable; | ||
| RW | [12:9] | lsio_uart2_txd_ds | 0x3 | lsio_uart2_txd driving selector; | ||
| RW | [8] | lsio_uart2_txd_st | 0x0 | lsio_uart2_txd; Schmitt trigger enable. 1: enables Schmitt trigger input function; 0: no Schmitt trigger input function; | ||
| RSV | [7] | RSV | 0x0 | reserved bits | ||
| RW | [6] | lsio_uart2_rxd_pu | 0x0 | lsio_uart2_rxd pull up enable: 1: pull up enable; 0: pull up disable; | ||
| RW | [5] | lsio_uart2_rxd_pd | 0x0 | lsio_uart2_rxd pull down enable: 1: pull down enable; 0: pull down disable; | ||
| RW | [4:1] | lsio_uart2_rxd_ds | 0x3 | lsio_uart2_rxd driving selector; | ||
| RW | [0] | lsio_uart2_rxd_st | 0x0 | lsio_uart2_rxd; Schmitt trigger enable. 1: enables Schmitt trigger input function; 0: no Schmitt trigger input function; |
Pinctrl 设备树解析

驱动调用代码
在
static int hobot_pinctrl_probe(struct platform_device *pdev)
{
...
g_xxx_dev->pinctrl = devm_pinctrl_get(&pdev->dev);
if (IS_ERR(g_xxx_dev->pinctrl)) {
dev_warn(&pdev->dev, "pinctrl get none\n");
g_xxx_dev->pins_xxxx = NULL;
}
...
/* 按照 pinctrl-names lookup state */
g_xxx_dev->pins_xxxx = pinctrl_lookup_state(g_xxx_dev->pinctrl, "xxx_func");
if (IS_ERR(g_xxx_dev->pins_xxxx)) {
dev_info(&pdev->dev, "xxx_func get error %ld\n",
PTR_ERR(g_xxx_dev->pins_xxxx));
g_xxx_dev->pins_xxxx = NULL;
}
...
}
int xxxx_pinmux_select(void)
{
if (!g_xxx_dev->pins_xxxx)
return -ENODEV;
/* 切换到对应的state */
return pinctrl_select_state(g_xxx_dev->pinctrl, g_xxx_dev->pins_xxxx);
}
用户空间调试
Uboot Space
Pinctrl 功能
Kernel Space
如果
首先,检查
mount | grep debugfs
如果
mount -t debugfs none /sys/kernel/debug
确保 debugfs 已/sys/kernel/debug/pinctrl/34180000.lsio_iomuxc/
该
root@buildroot:~$ ls /sys/kernel/debug/pinctrl/34180000.lsio_iomuxc/
gpio-ranges pinconf-groups pinconf-pins pingroups pinmux-functions pinmux-pins pinmux-select pins
以“pinmux-pins”为例,这个
root@buildroot:~$ cat /sys/kernel/debug/pinctrl/34180000.lsio_iomuxc/pinmux-pins
pin 14 (lsio_spi0_sclk): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 36 (lsio_spi0_ssn): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 37 (lsio_spi0_miso): vdd08_gpu_reg@3 (GPIO UNCLAIMED) function lsio_iomuxc group lsio_gpio1_5
pin 38 (lsio_spi0_mosi): soc:cam:vcon@3 (GPIO UNCLAIMED) function lsio_iomuxc group lsio_gpio1_6
pin 15 (lsio_spi1_ssn_1): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 16 (lsio_spi1_sclk): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 17 (lsio_spi1_ssn): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 18 (lsio_spi1_miso): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 19 (lsio_spi1_mosi): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 20 (lsio_spi2_sclk): 34020000.spi (GPIO UNCLAIMED) function lsio_iomuxc group spi2grp
pin 21 (lsio_spi2_ssn): 34020000.spi (GPIO UNCLAIMED) function lsio_iomuxc group spi2grp
pin 22 (lsio_spi2_miso): 34020000.spi (GPIO UNCLAIMED) function lsio_iomuxc group spi2grp
pin 23 (lsio_spi2_mosi): 34020000.spi (GPIO UNCLAIMED) function lsio_iomuxc group spi2grp
pin 24 (lsio_spi3_sclk): 3d060000.mipi_host (GPIO UNCLAIMED) function lsio_iomuxc group lsio_gpio0_24
pin 25 (lsio_spi3_ssn): 34110000.lpwm (GPIO UNCLAIMED) function lsio_iomuxc group pinctrl_lpwm1_1
pin 26 (lsio_spi3_miso): 3d080000.mipi_host (GPIO UNCLAIMED) function lsio_iomuxc group lsio_gpio0_26
pin 27 (lsio_spi3_mosi): 3d090000.mipi_host (GPIO UNCLAIMED) function lsio_iomuxc group lsio_gpio0_27
pin 28 (lsio_spi4_sclk): 341a0000.serial (GPIO UNCLAIMED) function lsio_iomuxc group uart5grp
pin 29 (lsio_spi4_ssn): 341a0000.serial (GPIO UNCLAIMED) function lsio_iomuxc group uart5grp
pin 30 (lsio_spi4_miso): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 31 (lsio_spi4_mosi): 35010000.gmac-tsn (GPIO UNCLAIMED) function lsio_iomuxc group lsio_gpio0_31
pin 32 (lsio_spi5_sclk): 34100000.lpwm (GPIO UNCLAIMED) function lsio_iomuxc group pinctrl_lpwm0_0
pin 33 (lsio_spi5_ssn): 34100000.lpwm (GPIO UNCLAIMED) function lsio_iomuxc group pinctrl_lpwm0_1
pin 34 (lsio_spi5_miso): 34100000.lpwm (GPIO UNCLAIMED) function lsio_iomuxc group pinctrl_lpwm0_2
pin 35 (lsio_spi5_mosi): 34100000.lpwm (GPIO UNCLAIMED) function lsio_iomuxc group pinctrl_lpwm0_3
pin 39 (lsio_i2c0_scl): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 40 (lsio_i2c0_sda): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 41 (lsio_i2c1_scl): 34170000.pwm (GPIO UNCLAIMED) function lsio_iomuxc group pinctrl_pwm3_0
pin 42 (lsio_i2c1_sda): 34170000.pwm (GPIO UNCLAIMED) function lsio_iomuxc group pinctrl_pwm3_1
pin 43 (lsio_i2c2_scl): 340d0000.i2c (GPIO UNCLAIMED) function lsio_iomuxc group i2c2grp
pin 44 (lsio_i2c2_sda): 340d0000.i2c (GPIO UNCLAIMED) function lsio_iomuxc group i2c2grp
pin 45 (lsio_i2c3_scl): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 46 (lsio_i2c3_sda): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 47 (lsio_i2c4_scl): 340f0000.i2c (GPIO UNCLAIMED) function lsio_iomuxc group i2c4grp
pin 48 (lsio_i2c4_sda): 340f0000.i2c (GPIO UNCLAIMED) function lsio_iomuxc group i2c4grp
pin 0 (lsio_uart7_rx): gpiochip8 (GPIO UNCLAIMED) function lsio_iomuxc group lsio_gpio0_0
pin 1 (lsio_uart7_tx): gpiochip8 (GPIO UNCLAIMED) function lsio_iomuxc group lsio_gpio0_1
pin 3 (lsio_uart7_rts): gpiochip8 (GPIO UNCLAIMED) function lsio_iomuxc group lsio_gpio0_3
pin 2 (lsio_uart7_cts): gpiochip8 (GPIO UNCLAIMED) function lsio_iomuxc group lsio_gpio0_2
pin 4 (lsio_uart1_rx): gpiochip8 (GPIO UNCLAIMED) function lsio_iomuxc group lsio_gpio0_4
pin 5 (lsio_uart1_tx): gpiochip8 (GPIO UNCLAIMED) function lsio_iomuxc group lsio_gpio0_5
pin 7 (lsio_uart1_rts): gpiochip8 (GPIO UNCLAIMED) function lsio_iomuxc group lsio_gpio0_7
pin 6 (lsio_uart1_cts): gpiochip8 (GPIO UNCLAIMED) function lsio_iomuxc group lsio_gpio0_6
pin 8 (lsio_uart2_rx): 34080000.serial (GPIO UNCLAIMED) function lsio_iomuxc group uart2grp
pin 9 (lsio_uart2_tx): 34080000.serial (GPIO UNCLAIMED) function lsio_iomuxc group uart2grp
pin 10 (lsio_uart3_rx): 341c0000.i2c (GPIO UNCLAIMED) function lsio_iomuxc group i2c5grp
pin 11 (lsio_uart3_tx): 341c0000.i2c (GPIO UNCLAIMED) function lsio_iomuxc group i2c5grp
pin 12 (lsio_uart4_rx): gpiochip8 (GPIO UNCLAIMED) function lsio_iomuxc group lsio_gpio0_12
pin 13 (lsio_uart4_tx): gpiochip8 (GPIO UNCLAIMED) function lsio_iomuxc group lsio_gpio0_13
打印
pin 36:表示
引脚 编号 是 36。 lsio_spi0_miso:表示
该 引脚 的 名称。 vdd08_gpu_reg@3:这部分
说明 该 引脚 在 设备树 中 被 vdd08_gpu_reg 节点 所 使用。 function lsio_iomuxc:表示
该 引脚 的 功能 通过 lsio_iomuxc(IOMUX 控制器)来 管理。 group lsio_gpio1_5:该
引脚 属于 lsio_gpio1_5 组,说明 该 引脚 被 复用 为 GPIO 功能。