PINCTRL 使用指南
1. 模块介绍
1.1. 术语定义
术语 | 定义 | 注释说明 |
---|---|---|
GPIO | General Purpose Input Output | 通用输入输出 |
GIC | Generic Interrupt Controller | 通用中断控制器 |
PINCTRL | Pin Controller | pin脚控制器 |
1.2. 模块简介
PINCTRL模块,负责管理SOC中各个pin的状态,如驱动能力,内部是否有上下拉,gpio的输入输出,以及是否功能复用等。通过PINCTRL模块,将SOC的pin脚个数,各个pin脚可实现的功能等信息统一注册到内核中,方便系统进行统一管理。
在linux内核中,pin的功能复用由pinctrl子系统实现,gpio的输入、输出、中断功能由gpio子系统实现。而AIC的PINCTRL模块,既包括了gpio的输入输出功能,也包括了pin的功能复用。所以在驱动实现上,统一将这些功能分类整合到pinctrl子系统的框架下,即硬件gpio模块的驱动实现在pinctrl子系统下。PINCTRL驱动实际包含了3个子系统的内容:gpio子系统,pinctrl子系统,以及irqchip子系统的驱动。
2. PINCTRL配置
2.1. 内核配置
在luban根目录下执行 make kernel-menuconfig,进入kernel的功能配置,按如下选择:
Linux
Device Drivers
Pin controllers--->
[*] Artinchip pin controller version1 device driver
2.2. DTS配置
2.2.1. pinctrl结点DTS配置
在dtsi文件中,配置pinctrl结点:
pinctrl: pinctrl@19200000 {
compatible = "artinchip,aic-pinctrl-v1.0";
reg = <0x19200000 0x800>;
clocks = <&cmu CLK_GPIO>;
resets = <&rst RESET_GPIO>;
};
2.2.2. gpio子结点DTS配置
在xxx-pinctrl.dtsi文件,配置SOC中所有功能模块的pins结点信息。以GPIOA为例说明,如下图:
gpio_a: bank-0 {
interrupts-extended = <&plic0 68 IRQ_TYPE_LEVEL_HIGH>;
gpio-controller;
artinchip,bank-port = <0>;
artinchip,bank-name = "PA";
gpio-ranges = <&pinctrl 0 0 12>;
gpio_regs = <0x0000 0x0004 0x0008 0x000C 0x0010 0x0080>;
debounce = <1>;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
};
各属性值含义如下:
- artinchip,bank-port:GPIOA的索引值
- artinchip,bank-name:GPIOA在struct gpio_chip结构体中的名字
- gpio-ranges:第一个数值表示GPIOA的第一个pin脚在GPIOA中的索引值;第二个数值表示GPIOA的第一个pin脚在整个SOC的GPIO中的序号索引值;第三个数值表示GPIOA中pin脚的个数
- interrupt-controller:GPIOA使用中断时,把GPIOA看做是一个中断控制器
2.2.3. 功能模块pin脚复用DTS配置
以uart0的引脚复用为例进行说明:
uart0_pins_a: uart0-0 {
pins {
pinmux = <AIC_PINMUX('A', 0, 5)>,
<AIC_PINMUX('A', 1, 5)>;
bias-disable;
drive-strength = <3>;
};
};
uart0_pins_b: uart0-1 {
pins {
pinmux = <AIC_PINMUX('A', 2, 5)>,
<AIC_PINMUX('A', 3, 5)>;
bias-disable;
drive-strength = <3>;
};
};
在xxx-pinctrl.dtsi文件中,描述了各个模块所有的pin脚配置信息,如上图。UART0有两种引脚配置,分别用uart0_pins_a和uart0_pins_b表示。pinmux属性表示的是模块所使用的的引脚配置信息,AIC_PINMUX是自定义的一个表示u32数据的宏,AIC_PINMUX(‘A’, 2, 5)表示把PA2脚配置为function 5,即可作为uart引脚。所以,uart0_pins_a使用的pin脚是PA0和PA1,uart_pins_b使用的pin脚是PA2和PA3。
2.2.4. 功能模块pin脚引用DTS 配置
在xxx-pinctrl.dtsi文件中,列出了所有的模块的pin脚配置信息。那么一个模块具体使用哪一组pin脚,一般是在board.dts文件中指定。在board.dts文件,各个模块的结点引用pinctrl的pin脚配置,声明本模块所使用的pin脚。如下图,uart0使用uart0_pins_a的引脚配置,即使用PA0和PA1脚。
&uart0 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_pins_a>;
status = "okay";
};
3. 调试指南
3.1. 调试开关
PINCTRL模块的驱动有一些dev_dbg调试信息,默认情况下是没有打开的,当需要跟踪调试时,可通过以下步骤打开这些调试信息。
3.1.1. 调整log等级
在luban根目录下执行 make kernel-menuconfig,进入kernel的功能配置,调整内核的log等级。
Kernel hacking--->
printk and dmesg options--->
(8) Default console loglevel (1-15)
3.1.2. 打开调试开关
Kernel hacking--->
Artinchip Debug--->
[*] Pinctrl driver debug
3.2. debugfs调试
pinctrl子系统中实现了一些调试函数,可以打印各个gpio口的配置信息,所以可以利用debugfs查看信息,辅助调试。
3.2.1. 打开debugfs
SDK已默认打开了debugfs。也可以通过以下方式打开:
Kernel hacking--->
Generic Kernel Debugging Instruments
Debug Filesystem
Debugfs default access(Access normal)--->
3.2.2. 挂载debugfs
内核启动后,需要手动挂载debugfs:
mount -t debugfs none /sys/kernel/debug
将debugfs挂载到/sys/kernel/debug目录下。
3.2.3. 查看debugfs结点
打开debugfs中pinctrl目录:
cd /sys/kernel/debug/pinctrl
可以看到该目录下有多个结点,可打印当前pinctrl各种信息,用于辅助调试。
4. 测试指南
待补充
5. 设计说明
5.1. 源码说明
PINCTRL模块的底层驱动位于:linux-5.10/drivers/pinctrl/artinchip/
驱动文件如下:
文件 | 说明 |
---|---|
pinctrl-aic.h | pinctrl公用头文件,一些结构体和宏定义 |
pinctrl-aic.c | pinctrl驱动的核心文件,实现了gpio/pinctrl/irq的驱动 |
pinctrl-aic-v1.c | pinctrl v1.0的pin脚功能列表,并将该功能列表注册到内核中 |
5.2. 模块架构
在linux内核中,pin脚的配置涉及到pinctrl,gpio和irqchip三个子系统。在内核子系统的划分中,pinctrl子系统用来配置pin脚的电气属性及功能复用;gpio子系统主要是GPIO的输入输出设置;同时,GPIO口使用中断时,内核将GPIO controller视为一个级联到GIC的中断控制器,又涉及到irqchip子系统的内容。
在把pin脚复用为GPIO口时,pinctrl子系统和gpio子系统具有一些功能相同的接口,所以,一些SOC厂商将gpio的驱动和pinctrl的驱动合并在了一起,PINCTRL模块的驱动实现也是采用的这种方式。所以,PINCTRL模块的驱动主要包括了三部分内容:
- 电气属性和功能复用配置
- gpio输入输出设置
- gpio controller作为irqchip的驱动实现