Pinctrl 调试指南
X3 Pinctrl 使用 Linux Kernel 主线代码的 pinctl-single 作为驱动,主要通过配置 DTS 来实现 pinctrl 功能。
管脚查询
IO 管脚的复用和配置可以在 datasheets 查阅《PL-2500-3-X3 PIN SW Reg-V1.2.xls》。
在 《PL-2500-3-X3 PIN SW Reg-V1.2.xls》可以比较直观的查询到管脚的上电默认状态、复用、驱动能力、上下拉、施密特触发配置。
驱动代码
drivers/pinctrl/pinctrl-single.c # pinctrl 驱动代码源文件
include/linux/platform_data/pinctrl-single.h # pinctrl 驱动代码头文件
内核配置
CONFIG_PINCTRL_SINGLE

Pinctrl 的 DTS 配置
/* arch/arm64/boot/dts/hobot/hobot-pinctrl-xj3.dtsi */
pinctrl: pinctrl@0xA6004000 {
compatible = "pinctrl-single";
reg = <0x0 0xA6004000 0x0 0x200>;
#pinctrl-cells = <1>;
#gpio-range-cells = <0x3>;
pinctrl-single,register-width = <32>;
pinctrl-single,function-mask = <0x3FF>;
/* pin base, nr pins & gpio function */
pinctrl-single,gpio-range = <&range 0 120 3>;
i2c0_func: i2c0_func {
pinctrl-single,pins = <
0x020 (MUX_F0 | DRIVE2_09MA | SCHMITT2_DIS | PULL2_UP)
0x024 (MUX_F0 | DRIVE2_09MA | SCHMITT2_DIS | PULL2_UP)
>;
};
...
}
Pinctrl 使用
驱动 DTS 配置
驱动在使用 Pinctrl 的接口前,需要在 DTS 里配置相应的 pinctrl 配置组,当驱动 probe 的时候,会将"default"对应的这组 Pinctrl 配置到寄存器里面,而其它组的配置需要在代码里面解析出来,再选择切换使用,以 iar 为例:
/* arch/arm64/boot/dts/hobot/hobot-xj3.dtsi */
iar: iar@0xA4001000 {
compatible = "hobot,hobot-iar";
reg = <0 0xA4301000 0 0x400>, <0 0xA4355000 0 0x1000>;
clocks = <&iar_pix_clk>, <&iar_ipi_clk>, <&sif_mclk>;
clock-names = "iar_pix_clk","iar_ipi_clk", "sif_mclk";
interrupt-parent = <&gic>;
interrupts = <0 69 4>;
resets = <&rst 0x40 12>;
pinctrl-names = "bt_func", "rgb_func", "rgb_gpio_func", "bt1120_voltage_func";
pinctrl-0 = <&btout_func>;
pinctrl-1 = <&rgb_func>;
pinctrl-2 = <&rgb_gpio_func>;
pinctrl-3 = <&bt1120_1_8v_func>;
disp_panel_reset_pin = <28>;
reset-names = "iar";
status = "disabled";
};
iar pinctrl 中引用的配置组在 arch/arm64/boot/dts/hobot/hobot-pinctrl-xj3.dtsi 中,内容如下:
btout_func: btout_func {
pinctrl-single,pins = <
0x138 (MUX_F0 | DRIVE1_12MA | SCHMITT2_ENA | PULL2_DOWN) /*BT1120_OUT_CLK*/
0x13c (MUX_F0 | DRIVE1_12MA | SCHMITT2_DIS | PULL2_DOWN) /*BT1120_OUT_DAT0*/
0x140 (MUX_F0 | DRIVE1_12MA | SCHMITT2_DIS | PULL2_DOWN)
0x144 (MUX_F0 | DRIVE1_12MA | SCHMITT2_DIS | PULL2_DOWN)
0x148 (MUX_F0 | DRIVE1_12MA | SCHMITT2_DIS | PULL2_DOWN)
0x14c (MUX_F0 | DRIVE1_12MA | SCHMITT2_DIS | PULL2_DOWN)
0x150 (MUX_F0 | DRIVE1_12MA | SCHMITT2_DIS | PULL2_DOWN)
0x154 (MUX_F0 | DRIVE1_12MA | SCHMITT2_DIS | PULL2_DOWN)
0x158 (MUX_F0 | DRIVE1_12MA | SCHMITT2_DIS | PULL2_DOWN) /*BT1120_OUT_DAT7*/
0x15c (MUX_F0 | DRIVE1_12MA | SCHMITT2_DIS | PULL2_DOWN) /*BT1120_OUT_DAT8*/
0x160 (MUX_F0 | DRIVE1_12MA | SCHMITT2_DIS | PULL2_DOWN)
0x164 (MUX_F0 | DRIVE1_12MA | SCHMITT2_DIS | PULL2_DOWN)
0x168 (MUX_F0 | DRIVE1_12MA | SCHMITT2_DIS | PULL2_DOWN)
0x16c (MUX_F0 | DRIVE1_12MA | SCHMITT2_DIS | PULL2_DOWN)
0x170 (MUX_F0 | DRIVE1_12MA | SCHMITT2_DIS | PULL2_DOWN)
0x174 (MUX_F0 | DRIVE1_12MA | SCHMITT2_DIS | PULL2_DOWN)
0x178 (MUX_F0 | DRIVE1_12MA | SCHMITT2_DIS | PULL2_DOWN) /*BT1120_OUT_DAT15*/
>;
};
pinctrl 配置组将多个 pin 配置组合到一起,每个 pin 的配置包含 2 列,第一列表示 pin 脚配置寄存器的偏移地址,值为 pin 脚号乘以 4,例如 BT1120_OUT_CLK 的 Pin 脚号为 78,因此偏移地址为 78 * 4 = 312 ,转换为 16 进制就是 0x138;第二列表示 Pin 的功能复用配置 Pin-mux。
Pin-mux 配置
X3 每个芯片的 Pin 脚支持最多 4 种功能,在配置某个功能时,客户可以通过寄存器手册查看对应功能的 pinmux 值,例如 Pin 脚 78 的 mux 配置为 0,也就是 MUX_F0 时 Pin 的功能为 BT1120_OUT_CLK。
/* include/dt-bindings/pinctrl/hobot-xj3.h */
/* MUX functions for pins */
#define MUX_F0 0
#define MUX_F1 1
#define MUX_F2 2
#define MUX_F3 3
驱动强度配置
X3 每个 Pin 脚支持配置最大的输出电流,驱动电流的配置在 Pin 脚配置寄存器中占输出电流的配置主要分为两类,同样的寄存器值在不同类的 Pin 上表示的驱动电流不一致,例如 DRIVE1 上 0 表示 3mA,而 DRIVE2 上表示 6mA,具体某个 Pin 脚属于哪一类,客户可以通过 arch/arm64/boot/dts/hobot/hobot-pinctrl-xj3.dtsi 来查看,hobot-pinctrl-xj3.dtsi 中已经列出了 X3 芯片的所有 pin 脚。
/* include/dt-bindings/pinctrl/hobot-xj3.h */
/* drive strength definition */
#define DRIVE_MASK (4 << 2)
#define DRIVE1_03MA (0 << 2)
#define DRIVE2_06MA (0 << 2)
#define DRIVE1_06MA (1 << 2)
#define DRIVE2_09MA (1 << 2)
#define DRIVE1_09MA (2 << 2)
#define DRIVE2_12MA (2 << 2)
#define DRIVE1_12MA (3 << 2)
#define DRIVE2_15MA (3 << 2)
#define DRIVE1_17MA (4 << 2)
#define DRIVE2_18MA (4 << 2)
#define DRIVE1_20MA (5 << 2)
#define DRIVE2_21MA (5 << 2)
#define DRIVE1_22MA (6 << 2)
#define DRIVE2_24MA (6 << 2)
#define DRIVE1_25MA (7 << 2)
#define DRIVE2_27MA (7 << 2)
#define DRIVE1_33MA (8 << 2)
#define DRIVE2_30MA (8 << 2)
#define DRIVE1_35MA (9 << 2)
#define DRIVE2_33MA (9 << 2)
#define DRIVE1_37MA (10 << 2)
#define DRIVE2_36MA (10 << 2)
#define DRIVE1_39MA (11 << 2)
#define DRIVE2_39MA (11 << 2)
#define DRIVE1_41MA (12 << 2)
#define DRIVE2_41MA (12 << 2)
#define DRIVE1_42_5MA (13 << 2)
#define DRIVE2_42_5MA (13 << 2)
#define DRIVE1_44MA (14 << 2)
#define DRIVE2_44MA (14 << 2)
#define DRIVE1_45MA (15 << 2)
#define DRIVE2_45MA (15 << 2)
上下拉配置
X3J3 每个 Pin 脚也支持上下拉配置,和驱动强度配置类似,上下拉的配置也分为两类,两类需要操作的寄存器 bit 位置不同,具体 Pin 脚的上下拉类别, hobot-pinctrl-xj3.dtsi 中已经列出,在客户可以通过 hobot-pinctrl-xj3.dtsi 查找即可。
/* include/dt-bindings/pinctrl/hobot-xj3.h */
/*
* PULL1 -> bit7(0==pulldown, 1==pullup)
* bit6(0==pull disable, 1==pull enable)
*
* PULL2 -> bit8(0==pullup enable, 1==pullup enable)
* bit7(0==pulldown diable, 1==pulldown enable)
*/
/* pin states bits */
#define PULL1_MASK (3 << 6)
#define PULL2_MASK (3 << 7)
#define PULL1_EN (1 << 6)
#define PULL1_DIS (0)
#define PULL2_DIS (0)
#define PULL1_UP (PULL1_EN | (1 << 7))
#define PULL2_UP (1 << 8)
#define PULL1_DOWN (PULL1_EN | (0 << 7))
#define PULL2_DOWN (1 << 7)
施密特触发配置
X3J3 每个 Pin 脚也支持上下拉配置,和驱动强度配置类似,施密特触发的配置也分为两类,两类需要操作的寄存器 bit 位置不同,具体 Pin 脚的施密特触发配置类别, hobot-pinctrl-xj3.dtsi 中已经列出,在客户可以通过 hobot-pinctrl-xj3.dtsi 查找即可。
/* include/dt-bindings/pinctrl/hobot-xj3.h */
/*
* SCHMITT1 -> bit8(0==diable, 1==enable)
*
* SCHMITT2 -> bit9(0==diable, 1==enable)
*/
/* pin schmitt */
#define SCHMITT1_ENA (1 << 8)
#define SCHMITT1_DIS (0 << 8)
#define SCHMITT2_ENA (1 << 9)
#define SCHMITT2_DIS (0 << 9)