前言
前面我们写的GPIO驱动程序都是自己在驱动里面定义好gpio引脚需要用到的寄存器,然后在驱动程序里面直接去配置这些寄存器。Linux是一个成熟的,跨平台的通用操作系统,对于配置引脚这样的最基本的功能,是已经有一套现成的框架可以用的,这就是pinctrl子系统。
需要注意的是pinctrl子系统是用于配置引脚的,包括引脚的复用功能,电气属性等。而当将引脚复用为gpio功能之后,就可以使用另一个叫做gpio的子系统去操作这个gpio引脚,包括将其设置为输入还是输出,输出高电平还是低电平等等。
设备树描述
在IMX6ULL中,负责引脚复用功能以及引脚电气属性配置的模块是IOMUXC控制器,其在设备树中的节点是iomuxc:
/* imx6ull.dtsi */ iomuxc: iomuxc@020e0000{compatible="fsl,imx6ul-iomuxc";reg=<0x020e0000 0x4000>;};/* imx6ull_alientek_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_GPIO1_IO00__ANATOP_OTG1_ID 0x13058 /* USB_OTG1_ID */>;};pinctrl_led: ledgrp{fsl,pins=<MX6UL_PAD_GPIO1_IO03__GPIO1_IO03 0x10B0 /* LED0 */>;};pinctrl_beep: beepgrp{fsl,pins=<MX6ULL_PAD_SNVS_TAMPER1__GPIO5_IO01 0x10B0 /* beep */>;};...};};iomuxc:IOMUXC控制器(也可说是pinctrl子系统)的设备树节点compatible:与IOMUXC控制器的平台驱动做匹配reg:IOMUXC控制器的寄存器组起始地址和长度iomuxc节点中的每个子节点都是一个group,也就是一组实现特定功能的物理引脚配置的集合。pinctrl子系统会解析出这些group节点,并在内核中建立和设置很多关于这些group中的每个pin(引脚)配置的映射关系,供其它外设使用到这些引脚时能快速索引并进行配置。
iomuxc节点除了作为IOMUXC控制器节点,其还是一个虚拟的外设节点,对于那些需要在系统启动时就需要配置成特定功能的引脚,可以直接在iomuxc节点中配置。这样,iomuxc节点匹配上IOMUXC控制器驱动的时候,pinctrl子系统就会直接配置这些引脚,比如示例中的:
&iomuxc{pinctrl-names="default";pinctrl-0=<&pinctrl_hog_1>;imx6ul-evk{...};};就表示在系统启动并初始化pinctrl子系统的时候,就将pinctrl_hog_1引脚组里面的引脚配置成给定的复用功能和电气属性(hog是霸占,强制使用的意思)。