一、pinctrl子系统

借助pinctrl子系统来设置一个引脚的复用功能和属性。

pinctrl子系统的主要工作内容:

  • 获取设备树中pin的信息
  • 根据获取到的pin信息来设置pin的复用功能
  • 根据获取到的pin信息设置pin的电气特性,比如上拉下拉、速度、驱动能力等

对于使用者来说,只需要在设备树里面设置好某个pin的相关属性即可,其余的初始化工作均由pinctrl子系统来完成,pinctrl子系统源码目录为:drivers/pinctrl。

二、设备树如何描述pin配置信息

pinctrl子系统根据设备树中的描述信息来设置pin功能。

1. iomuxc设备树节点

在imx6ull的设备树中,iomucx节点就是imx6ull iomuxc外设对应的节点,用来设置引脚复用。

(1)iomuxc子节点在​​arch/arm/boot/dts/imx6ul.dtsi​​文件中的描述。

iomuxc: iomuxc@020e0000 {
compatible = "fsl,imx6ul-iomuxc";
reg = <0x020e0000 0x4000>;
};

iomucx外设的兼容性为"fsl,imx6ul-iomuxc",寄存器起始地址为0x020e0000、大小为0x4000。

(2)iomucx子节点在​​arch/arm/boot/dts/imx6ull-atk-emmc.dts​​文件中的补充描述(节选部分代码)。

&iomuxc {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_hog_1>;
imx6ul-evk {
pinctrl_hog_1: hoggrp-1 {
fsl,pins = <
MX6UL_PAD_UART1_RTS_B__GPIO1_IO19 0x17059 /* SD1 CD */
MX6UL_PAD_GPIO1_IO05__USDHC1_VSELECT 0x17059 /* SD1 VSELECT */
MX6UL_PAD_GPIO1_IO09__GPIO1_IO09 0x17059 /* SD1 RESET */
>;
};
};
};

其中​​MX6UL_PAD_UART1_RTS_B__GPIO1_IO19​​表示MX6UL_PAD_UART1_RTS_B引脚作为GPIO1_IO19使用。

2. 节点描述值的意义

​MX6UL_PAD_UART1_RTS_B__GPIO1_IO19​​​这些宏在​​arch/arm/boot/dts/imx6ull-pinfunc.h​​​和​​arch/arm/boot/dts/imx6ul-pinfunc.h​​文件中定义,比如MX6UL_PAD_UART1_CTS_B引脚所有可复用的引脚宏定义如下:

#define MX6UL_PAD_UART1_RTS_B__UART1_DCE_RTS                      0x0090 0x031C 0x0620 0x0 0x3
#define MX6UL_PAD_UART1_RTS_B__UART1_DTE_CTS 0x0090 0x031C 0x0000 0x0 0x0
#define MX6UL_PAD_UART1_RTS_B__ENET1_TX_ER 0x0090 0x031C 0x0000 0x1 0x0
#define MX6UL_PAD_UART1_RTS_B__USDHC1_CD_B 0x0090 0x031C 0x0668 0x2 0x1
#define MX6UL_PAD_UART1_RTS_B__CSI_DATA05 0x0090 0x031C 0x04CC 0x3 0x1
#define MX6UL_PAD_UART1_RTS_B__ENET2_1588_EVENT1_OUT 0x0090 0x031C 0x0000 0x4 0x0
#define MX6UL_PAD_UART1_RTS_B__GPIO1_IO19 0x0090 0x031C 0x0000 0x5 0x0
#define MX6UL_PAD_UART1_RTS_B__USDHC2_CD_B 0x0090 0x031C 0x0674 0x8 0x2

宏定义所给出的5个值的意义为:

<mux_reg conf_reg input_reg mux_mode input_val>
  • mux_reg:引脚复用寄存器
  • conf_reg:引脚电气属性寄存器
  • input_reg:输入寄存器,偏移为0表示没有
  • mux_mode:引脚复用模式
  • input_val:输入寄存器的值

i.MX6ULL驱动开发 | 06 - pinctrl子系统_引脚

引脚电气属性寄存器的值在宏定义之后,比如 MX6UL_PAD_UART1_RTS_B__GPIO1_IO19 的电气属性配置为0x17059。

i.MX6ULL驱动开发 | 06 - pinctrl子系统_linux_02

三、pinctrl驱动大概实现框架

1. 如何找到imx6ull对应的pinctrl子系统驱动

驱动是根据设备树节点的兼容性(compatible)来匹配驱动。

imx6ull.dtsi描述文件中,iomucx的兼容性如图:

i.MX6ULL驱动开发 | 06 - pinctrl子系统_#define_03

在内核源码中全局搜索该兼容性字符串,寻找对应驱动:

i.MX6ULL驱动开发 | 06 - pinctrl子系统_linux_04

找到驱动文件为:drivers/pinctrl/freescale/pinctrl-imx6ul.c

2. 驱动模块的加载与卸载

该驱动模块的加载与卸载函数如下:

i.MX6ULL驱动开发 | 06 - pinctrl子系统_#define_05

3. 平台驱动结构体

在驱动模块入口中,调用​​platform_driver_register​​ API来注册一个平台设备驱动,注册的驱动结构体如下:

i.MX6ULL驱动开发 | 06 - pinctrl子系统_linux_06

4. 驱动probe挂载函数

驱动probe挂载函数实现如下:

i.MX6ULL驱动开发 | 06 - pinctrl子系统_#define_07

底层再调用imx的pinctrl probe函数,该函数实现在​​drivers/pinctrl/freescale/pinctrl-imx.c​​文件中,其中会设置这样一组ops操作函数:

i.MX6ULL驱动开发 | 06 - pinctrl子系统_引脚_08

操作函数的定义如下:

i.MX6ULL驱动开发 | 06 - pinctrl子系统_#define_09

其中 imx_pinconf_set 函数就会去操作底层寄存器完成引脚复用功能设置和电气属性设置:

i.MX6ULL驱动开发 | 06 - pinctrl子系统_linux_10

5. 驱动remove移除函数

驱动remove卸载函数如下:

i.MX6ULL驱动开发 | 06 - pinctrl子系统_linux_11