i.MX6ULL(18) linux pinctrl subsystem

a brief introduction

In the previous chapter, we wrote the LED driver based on the device tree, but the essence of the driver has not changed, it is all configured with LED lights
The GPIO registers used are basically the same as the bare metal driver development method . Linux is a huge and complete system,
Especially the driver framework, the most basic driver like GPIO cannot use the "original" bare-metal driver development method, otherwise
It is equivalent to buying a car and then pushing it to work every day. The Linux kernel provides the pinctrl and gpio subsystems for
GPIO driver, in this chapter we will learn how to use the pinctrl and gpio subsystems to simplify GPIO driver development.
Nothing special to remember.

Two pinctrl subsystems

2.1 Introduction to the pinctrl subsystem

Linux drivers pay attention to driver separation and layering. The pinctrl and gpio subsystems are the products of driver separation and layering.
Driver separation and layering is actually a device driver framework designed according to the design idea of ​​object-oriented programming.
We will talk about separation and layering later. Originally, the pinctrl and gpio subsystems should be explained after the driver separation and layering chapters, but
No matter what the peripheral driver is, the GPIO driver is basically necessary, and the pinctrl and gpio subsystems are necessary for the GPIO driver.
It must be used, so the chapters of pintrcl and gpio subsystems are advanced.
Let's first review how to initialize the GPIO used by the LED lights in the previous chapter . The steps are as follows:
①. Modify the device tree and add corresponding nodes. The key point in the nodes is to set the reg attribute, which includes GPIO
related registers.
②. Obtain the addresses of the two registers IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03 and IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03 in the reg attribute, and initialize these two registers.
Two registers are used to set the multiplexing function, pull-up and pull-down, speed, etc. of the PIN GPIO1_IO03.
③. In ②, the GPIO1_IO03 PIN is multiplexed as the GPIO function, so GPIO1_IO03 needs to be set
The GPIO-related registers are the two registers GPIO1_DR and GPIO1_GDIR.
To sum up, in ②, complete the initialization of the PIN GPIO1_IO03 , set the multiplexing function of this PIN , up and down
Pull, etc., for example, set the PIN GPIO_IO03 as the GPIO function. ③Complete the initialization of GPIO and set GPIO
for input / output etc. If you have used STM32 , you should remember that STM32 also needs to set the multiplexing function of a certain PIN first.
Function, speed, pull-up and pull-down, etc., and then set the GPIO corresponding to the PIN . In fact, for most 32 -bit SOCs , the boot
The settings of the pin are basically these two aspects , so the Linux kernel introduces the pinctrl subsystem for the configuration of the PIN, and for the GPIO
The configuration launches the gpio subsystem . In this section, we will learn the pinctrl subsystem, and the next section will learn the gpio subsystem.
Most SOC pins support multiplexing. For example, GPIO1_IO03 of I.MX6ULL can be used as a common
GPIO can also be used as I2C1 SDA and so on. In addition, we also need to configure the electrical characteristics of the pin , such as up / down
Pull, speed, drive ability and more. The traditional way to configure the pin is to directly operate the corresponding register, but this configuration
The method is cumbersome and prone to problems ( such as pin function conflicts ) . The pinctrl subsystem is introduced to solve this problem
The main tasks of the pinctrl subsystem are as follows :
①. Obtain the pin information in the device tree.
②. Set the multiplexing function of the pin according to the obtained pin information
③. Set the electrical characteristics of the pin according to the obtained pin information, such as pull-up / pull-down, speed, drive capability, etc.
For our users, we only need to set the relevant properties of a certain pin in the device tree , and other initial
The transformation work is completed by the pinctrl subsystem, and the source code directory of the pinctrl subsystem is drivers/pinctrl .

2.2  pinctrl subsystem driver of  I.MX6ULL

2.2.1 Detailed explanation of PIN configuration information

To use the pinctrl subsystem, we need to set the PIN configuration information in the device tree . After all, the pinctrl subsystem needs
Configure the PIN function according to the information you provide . Generally, a node will be created in the device tree to describe the PIN configuration information .
interest. Open the imx6ull.dtsi file and find a node called iomuxc, as shown below:
示例代码 45.1.2.1 iomuxc 节点内容 1
 iomuxc: iomuxc@020e0000 {
 compatible = "fsl,imx6ul-iomuxc";
 reg = <0x020e0000 0x4000>;
};
The iomuxc node is the node corresponding to the IOMUXC peripheral of I.MX6ULL . It seems that the content is very little, and nothing can be seen.
For the content related to PIN configuration, don't worry! There are few imx6ull-14x14-evk-emmc.dts. Open imx6ull-14x14-evk-emmc.dts and find the content as shown below: the main pin content and board-related common parts of many imx6ull series are put into higher-level 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 */
			>;
		};

		pinctrl_csi1: csi1grp {
			fsl,pins = <
				MX6UL_PAD_CSI_MCLK__CSI_MCLK		0x1b088
				MX6UL_PAD_CSI_PIXCLK__CSI_PIXCLK	0x1b088
				MX6UL_PAD_CSI_VSYNC__CSI_VSYNC		0x1b088
				MX6UL_PAD_CSI_HSYNC__CSI_HSYNC		0x1b088
				MX6UL_PAD_CSI_DATA00__CSI_DATA02	0x1b088
				MX6UL_PAD_CSI_DATA01__CSI_DATA03	0x1b088
				MX6UL_PAD_CSI_DATA02__CSI_DATA04	0x1b088
				MX6UL_PAD_CSI_DATA03__CSI_DATA05	0x1b088
				MX6UL_PAD_CSI_DATA04__CSI_DATA06	0x1b088
				MX6UL_PAD_CSI_DATA05__CSI_DATA07	0x1b088
				MX6UL_PAD_CSI_DATA06__CSI_DATA08	0x1b088
				MX6UL_PAD_CSI_DATA07__CSI_DATA09	0x1b088
			>;
		};

		pinctrl_enet1: enet1grp {
			fsl,pins = <
				MX6UL_PAD_ENET1_RX_EN__ENET1_RX_EN	0x1b0b0
				MX6UL_PAD_ENET1_RX_ER__ENET1_RX_ER	0x1b0b0
				MX6UL_PAD_ENET1_RX_DATA0__ENET1_RDATA00	0x1b0b0
				MX6UL_PAD_ENET1_RX_DATA1__ENET1_RDATA01	0x1b0b0
				MX6UL_PAD_ENET1_TX_EN__ENET1_TX_EN	0x1b0b0
				MX6UL_PAD_ENET1_TX_DATA0__ENET1_TDATA00	0x1b0b0
				MX6UL_PAD_ENET1_TX_DATA1__ENET1_TDATA01	0x1b0b0
				MX6UL_PAD_ENET1_TX_CLK__ENET1_REF_CLK1	0x4001b031
			>;
		};

		pinctrl_enet2: enet2grp {
			fsl,pins = <
				MX6UL_PAD_GPIO1_IO07__ENET2_MDC		0x1b0b0
				MX6UL_PAD_GPIO1_IO06__ENET2_MDIO	0x1b0b0
				MX6UL_PAD_ENET2_RX_EN__ENET2_RX_EN	0x1b0b0
				MX6UL_PAD_ENET2_RX_ER__ENET2_RX_ER	0x1b0b0
				MX6UL_PAD_ENET2_RX_DATA0__ENET2_RDATA00	0x1b0b0
				MX6UL_PAD_ENET2_RX_DATA1__ENET2_RDATA01	0x1b0b0
				MX6UL_PAD_ENET2_TX_EN__ENET2_TX_EN	0x1b0b0
				MX6UL_PAD_ENET2_TX_DATA0__ENET2_TDATA00	0x1b0b0
				MX6UL_PAD_ENET2_TX_DATA1__ENET2_TDATA01	0x1b0b0
				MX6UL_PAD_ENET2_TX_CLK__ENET2_REF_CLK2	0x4001b031
			>;
		};

		pinctrl_flexcan1: flexcan1grp{
			fsl,pins = <
				MX6UL_PAD_UART3_RTS_B__FLEXCAN1_RX	0x1b020
				MX6UL_PAD_UART3_CTS_B__FLEXCAN1_TX	0x1b020
			>;
		};

		pinctrl_flexcan2: flexcan2grp{
			fsl,pins = <
				MX6UL_PAD_UART2_RTS_B__FLEXCAN2_RX	0x1b020
				MX6UL_PAD_UART2_CTS_B__FLEXCAN2_TX	0x1b020
			>;
		};

		pinctrl_i2c1: i2c1grp {
			fsl,pins = <
				MX6UL_PAD_UART4_TX_DATA__I2C1_SCL 0x4001b8b0
				MX6UL_PAD_UART4_RX_DATA__I2C1_SDA 0x4001b8b0
			>;
		};

		pinctrl_i2c2: i2c2grp {
			fsl,pins = <
				MX6UL_PAD_UART5_TX_DATA__I2C2_SCL 0x4001b8b0
				MX6UL_PAD_UART5_RX_DATA__I2C2_SDA 0x4001b8b0
			>;
		};

		pinctrl_lcdif_dat: lcdifdatgrp {
			fsl,pins = <
				MX6UL_PAD_LCD_DATA00__LCDIF_DATA00  0x79
				MX6UL_PAD_LCD_DATA01__LCDIF_DATA01  0x79
				MX6UL_PAD_LCD_DATA02__LCDIF_DATA02  0x79
				MX6UL_PAD_LCD_DATA03__LCDIF_DATA03  0x79
				MX6UL_PAD_LCD_DATA04__LCDIF_DATA04  0x79
				MX6UL_PAD_LCD_DATA05__LCDIF_DATA05  0x79
				MX6UL_PAD_LCD_DATA06__LCDIF_DATA06  0x79
				MX6UL_PAD_LCD_DATA07__LCDIF_DATA07  0x79
				MX6UL_PAD_LCD_DATA08__LCDIF_DATA08  0x79
				MX6UL_PAD_LCD_DATA09__LCDIF_DATA09  0x79
				MX6UL_PAD_LCD_DATA10__LCDIF_DATA10  0x79
				MX6UL_PAD_LCD_DATA11__LCDIF_DATA11  0x79
				MX6UL_PAD_LCD_DATA12__LCDIF_DATA12  0x79
				MX6UL_PAD_LCD_DATA13__LCDIF_DATA13  0x79
				MX6UL_PAD_LCD_DATA14__LCDIF_DATA14  0x79
				MX6UL_PAD_LCD_DATA15__LCDIF_DATA15  0x79
				MX6UL_PAD_LCD_DATA16__LCDIF_DATA16  0x79
				MX6UL_PAD_LCD_DATA17__LCDIF_DATA17  0x79
				MX6UL_PAD_LCD_DATA18__LCDIF_DATA18  0x79
				MX6UL_PAD_LCD_DATA19__LCDIF_DATA19  0x79
				MX6UL_PAD_LCD_DATA20__LCDIF_DATA20  0x79
				MX6UL_PAD_LCD_DATA21__LCDIF_DATA21  0x79
				MX6UL_PAD_LCD_DATA22__LCDIF_DATA22  0x79
				MX6UL_PAD_LCD_DATA23__LCDIF_DATA23  0x79
			>;
		};

		pinctrl_lcdif_ctrl: lcdifctrlgrp {
			fsl,pins = <
				MX6UL_PAD_LCD_CLK__LCDIF_CLK	    0x79
				MX6UL_PAD_LCD_ENABLE__LCDIF_ENABLE  0x79
				MX6UL_PAD_LCD_HSYNC__LCDIF_HSYNC    0x79
				MX6UL_PAD_LCD_VSYNC__LCDIF_VSYNC    0x79
			>;
		};

		pinctrl_pwm1: pwm1grp {
			fsl,pins = <
				MX6UL_PAD_GPIO1_IO08__PWM1_OUT   0x110b0
			>;
		};

		pinctrl_qspi: qspigrp {
			fsl,pins = <
				MX6UL_PAD_NAND_WP_B__QSPI_A_SCLK      0x70a1
				MX6UL_PAD_NAND_READY_B__QSPI_A_DATA00 0x70a1
				MX6UL_PAD_NAND_CE0_B__QSPI_A_DATA01   0x70a1
				MX6UL_PAD_NAND_CE1_B__QSPI_A_DATA02   0x70a1
				MX6UL_PAD_NAND_CLE__QSPI_A_DATA03     0x70a1
				MX6UL_PAD_NAND_DQS__QSPI_A_SS0_B      0x70a1
			>;
		};

		pinctrl_sai2: sai2grp {
			fsl,pins = <
				MX6UL_PAD_JTAG_TDI__SAI2_TX_BCLK	0x17088
				MX6UL_PAD_JTAG_TDO__SAI2_TX_SYNC	0x17088
				MX6UL_PAD_JTAG_TRST_B__SAI2_TX_DATA	0x11088
				MX6UL_PAD_JTAG_TCK__SAI2_RX_DATA	0x11088
				MX6UL_PAD_JTAG_TMS__SAI2_MCLK		0x17088
			>;
		};

		pinctrl_tsc: tscgrp {
			fsl,pins = <
				MX6UL_PAD_GPIO1_IO01__GPIO1_IO01	0xb0
				MX6UL_PAD_GPIO1_IO02__GPIO1_IO02	0xb0
				MX6UL_PAD_GPIO1_IO03__GPIO1_IO03	0xb0
				MX6UL_PAD_GPIO1_IO04__GPIO1_IO04	0xb0
			>;
		};

		pinctrl_uart1: uart1grp {
			fsl,pins = <
				MX6UL_PAD_UART1_TX_DATA__UART1_DCE_TX 0x1b0b1
				MX6UL_PAD_UART1_RX_DATA__UART1_DCE_RX 0x1b0b1
			>;
		};

		pinctrl_uart2: uart2grp {
			fsl,pins = <
				MX6UL_PAD_UART2_TX_DATA__UART2_DCE_TX	0x1b0b1
				MX6UL_PAD_UART2_RX_DATA__UART2_DCE_RX	0x1b0b1
				MX6UL_PAD_UART3_RX_DATA__UART2_DCE_RTS	0x1b0b1
				MX6UL_PAD_UART3_TX_DATA__UART2_DCE_CTS	0x1b0b1
			>;
		};

		pinctrl_uart2dte: uart2dtegrp {
			fsl,pins = <
				MX6UL_PAD_UART2_TX_DATA__UART2_DTE_RX	0x1b0b1
				MX6UL_PAD_UART2_RX_DATA__UART2_DTE_TX	0x1b0b1
				MX6UL_PAD_UART3_RX_DATA__UART2_DTE_CTS	0x1b0b1
				MX6UL_PAD_UART3_TX_DATA__UART2_DTE_RTS	0x1b0b1
			>;
		};

		pinctrl_usdhc1: usdhc1grp {
			fsl,pins = <
				MX6UL_PAD_SD1_CMD__USDHC1_CMD     0x17059
				MX6UL_PAD_SD1_CLK__USDHC1_CLK     0x10071
				MX6UL_PAD_SD1_DATA0__USDHC1_DATA0 0x17059
				MX6UL_PAD_SD1_DATA1__USDHC1_DATA1 0x17059
				MX6UL_PAD_SD1_DATA2__USDHC1_DATA2 0x17059
				MX6UL_PAD_SD1_DATA3__USDHC1_DATA3 0x17059
			>;
		};

		pinctrl_usdhc1_100mhz: usdhc1grp100mhz {
			fsl,pins = <
				MX6UL_PAD_SD1_CMD__USDHC1_CMD     0x170b9
				MX6UL_PAD_SD1_CLK__USDHC1_CLK     0x100b9
				MX6UL_PAD_SD1_DATA0__USDHC1_DATA0 0x170b9
				MX6UL_PAD_SD1_DATA1__USDHC1_DATA1 0x170b9
				MX6UL_PAD_SD1_DATA2__USDHC1_DATA2 0x170b9
				MX6UL_PAD_SD1_DATA3__USDHC1_DATA3 0x170b9
			>;
		};

		pinctrl_usdhc1_200mhz: usdhc1grp200mhz {
			fsl,pins = <
				MX6UL_PAD_SD1_CMD__USDHC1_CMD     0x170f9
				MX6UL_PAD_SD1_CLK__USDHC1_CLK     0x100f9
				MX6UL_PAD_SD1_DATA0__USDHC1_DATA0 0x170f9
				MX6UL_PAD_SD1_DATA1__USDHC1_DATA1 0x170f9
				MX6UL_PAD_SD1_DATA2__USDHC1_DATA2 0x170f9
				MX6UL_PAD_SD1_DATA3__USDHC1_DATA3 0x170f9
			>;
		};

		pinctrl_usdhc2: usdhc2grp {
			fsl,pins = <
				MX6UL_PAD_NAND_RE_B__USDHC2_CLK     0x10069
				MX6UL_PAD_NAND_WE_B__USDHC2_CMD     0x17059
				MX6UL_PAD_NAND_DATA00__USDHC2_DATA0 0x17059
				MX6UL_PAD_NAND_DATA01__USDHC2_DATA1 0x17059
				MX6UL_PAD_NAND_DATA02__USDHC2_DATA2 0x17059
				MX6UL_PAD_NAND_DATA03__USDHC2_DATA3 0x17059
			>;
		};

		pinctrl_usdhc2_8bit: usdhc2grp_8bit {
			fsl,pins = <
				MX6UL_PAD_NAND_RE_B__USDHC2_CLK     0x10069
				MX6UL_PAD_NAND_WE_B__USDHC2_CMD     0x17059
				MX6UL_PAD_NAND_DATA00__USDHC2_DATA0 0x17059
				MX6UL_PAD_NAND_DATA01__USDHC2_DATA1 0x17059
				MX6UL_PAD_NAND_DATA02__USDHC2_DATA2 0x17059
				MX6UL_PAD_NAND_DATA03__USDHC2_DATA3 0x17059
				MX6UL_PAD_NAND_DATA04__USDHC2_DATA4 0x17059
				MX6UL_PAD_NAND_DATA05__USDHC2_DATA5 0x17059
				MX6UL_PAD_NAND_DATA06__USDHC2_DATA6 0x17059
				MX6UL_PAD_NAND_DATA07__USDHC2_DATA7 0x17059
			>;
		};

		pinctrl_usdhc2_8bit_100mhz: usdhc2grp_8bit_100mhz {
			fsl,pins = <
				MX6UL_PAD_NAND_RE_B__USDHC2_CLK     0x100b9
				MX6UL_PAD_NAND_WE_B__USDHC2_CMD     0x170b9
				MX6UL_PAD_NAND_DATA00__USDHC2_DATA0 0x170b9
				MX6UL_PAD_NAND_DATA01__USDHC2_DATA1 0x170b9
				MX6UL_PAD_NAND_DATA02__USDHC2_DATA2 0x170b9
				MX6UL_PAD_NAND_DATA03__USDHC2_DATA3 0x170b9
				MX6UL_PAD_NAND_DATA04__USDHC2_DATA4 0x170b9
				MX6UL_PAD_NAND_DATA05__USDHC2_DATA5 0x170b9
				MX6UL_PAD_NAND_DATA06__USDHC2_DATA6 0x170b9
				MX6UL_PAD_NAND_DATA07__USDHC2_DATA7 0x170b9
			>;
		};

		pinctrl_usdhc2_8bit_200mhz: usdhc2grp_8bit_200mhz {
			fsl,pins = <
				MX6UL_PAD_NAND_RE_B__USDHC2_CLK     0x100f9
				MX6UL_PAD_NAND_WE_B__USDHC2_CMD     0x170f9
				MX6UL_PAD_NAND_DATA00__USDHC2_DATA0 0x170f9
				MX6UL_PAD_NAND_DATA01__USDHC2_DATA1 0x170f9
				MX6UL_PAD_NAND_DATA02__USDHC2_DATA2 0x170f9
				MX6UL_PAD_NAND_DATA03__USDHC2_DATA3 0x170f9
				MX6UL_PAD_NAND_DATA04__USDHC2_DATA4 0x170f9
				MX6UL_PAD_NAND_DATA05__USDHC2_DATA5 0x170f9
				MX6UL_PAD_NAND_DATA06__USDHC2_DATA6 0x170f9
				MX6UL_PAD_NAND_DATA07__USDHC2_DATA7 0x170f9
			>;
		};

		pinctrl_wdog: wdoggrp {
			fsl,pins = <
				MX6UL_PAD_LCD_RESET__WDOG1_WDOG_ANY    0x30b0
			>;
		};
	};
};
It is to add data to the iomuxc node. Different peripherals use different PINs and their configurations are also different. Therefore, one radish and one pit organize all the PINs used by a certain peripheral in a sub-node. sample code
The pinctrl_hog_1 subnode in 45.1.2.2 is a collection of PINs related to hot plugging , such as the ID pin of USB OTG .
The pinctrl_flexcan1 subnode is the PIN used by the flexcan1 peripheral , and the pinctrl_wdog subnode is the wdog peripheral
The PIN used . If you need to add the PIN of our custom peripherals in iomuxc, you need to create a new subnode, and then
Then put all the PIN configuration information of this custom peripheral into this sub-node. The register bank structure in the imx6ull reference document is also designed in this way.
The pinctrl/gpio subsystem is implemented by semiconductor manufacturers and defines all gpio pin multiplexing control corresponding registers 
Device tree --> pin register group ----> device function ---> corresponding N register ----> register (gpio pin 1:1) ----> & gpio/pinctrl --> multiplexing ( control register)

Combining this with example code 45.1.2.1 gives the completed iomuxc node as follows:
 iomuxc: iomuxc@020e0000 {
 compatible = "fsl,imx6ul-iomuxc";
 reg = <0x020e0000 0x4000>;

   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 */
			    >;
		    };

......

};
In line 2 , the compatible attribute value is " fsl,imx6ul-iomuxc ", as mentioned earlier when explaining the device tree, Linux
The kernel will search for the corresponding driver file according to the compatbile attribute value, so we search the word globally in the Linux kernel source code
The string " fsl,imx6ul-iomuxc " will find the pinctrl driver file of the I.MX6ULL SOC .
Lines 9~12 , the PIN configuration information used by the pinctrl_hog_1 child node, we will use UART1_RTS_B in line 9
Take this PIN as an example to explain how to add PIN configuration information. The configuration information of UART1_RTS_B is as follows:
MX6UL_ PAD_UART1_RTS_B __GPIO1_IO19   0x17059   
First of all, let me explain that the PIN UART1_RTS_B is used as the detection pin of the SD card , that is, through this PIN, the
It can detect whether the SD card is inserted.
The configuration information of UART1_RTS_B is divided into two parts: pin __IO multiplexing
The configuration of a PIN mainly includes two aspects, one is to set the multiplexing function of this PIN, and the other is to set the electrical characteristics of this PIN.
First look at MX6UL_PAD_UART1_RTS_B__GPIO1_IO19, this is a macro definition, defined in the file
In arch/arm/boot/dts/imx6ul-pinfunc.h, imx6ull.dtsi will refer to the header file imx6ull-pinfunc.h, while
imx6ul-pinfunc.h will refer to the header file imx6ul-pinfunc.h
There are 8 macro definitions starting with "MX6UL_PAD_UART1_RTS_B" in the sample code 45.1.2.4 , everyone
Careful observation should reveal that these 8 macro definitions correspond to the 8 multiplexed IOs of the UART1_RTS_B PIN . check
Read " I.MX6ULL Reference Manual" to know that the optional multiplexed IO of UART1_RTS_B is shown in Figure 45.1.2.1 :
IOMUXC_SW_MUX_CTL_PAD_UART1_RTS_B control register_pin
The macro definition MX6UL_PAD_UART1_RTS_B__GPIO1_IO19 in line 196 of the sample code indicates that the
The IO of UART1_RTS_B is multiplexed as GPIO1_IO19 . This macro definition is followed by 5 numbers, which is the macro definition
The specific value of is as follows:
0x0090 0x031C 0x0000 0x5 (multiplex mode) 0x0
<mux_reg           conf_reg              input_reg               mux_mode                    input_val>

Register offset address conf_reg post offset input_reg post offset mux_reg post value        input_reg post value, invalid here

0x0090 : mux_reg register offset address, the iomuxc node in the device tree is the node corresponding to the IOMUXC peripheral
point, according to its reg attribute, it can be known that the initial address of the IOMUXC peripheral register is 0x020e0000 .
0x020e0000+0x0090=0x020e0090 , the IOMUXC_SW_MUX_CTL_PAD_UART1_RTS_B register address is exactly 0x020e0090

0x17059
Students who respond quickly should have guessed it, 0x17059 is the value of the conf_reg register! This value is set by the user, usually
Use this value to set the pull-up / pull-down, drive capability and speed of an IO , etc. Here it is equivalent to setting the register
The value of IOMUXC_SW_PAD_CTL_PAD_UART1_RTS_B is 0x17059

2.2.2  , PIN driver explanation

slightly....

2.3 Add pinctrl node template in device tree

We already have a more in-depth understanding of pinctrl , let's learn how to add an external device to the device tree
PIN information set . For pinctrl device tree binding information of I.MX series SOC , please refer to the document
Documentation/devicetree/bindings/pinctrl/fsl,imx-pinctrl.txt . Here we make a virtual device called " test "
Prepare, the test uses the GPIO function of the PIN GPIO1_IO00, the pinctrl node addition process is as follows:
1. Create the corresponding node
Put the PIN of the same peripheral device into one node, open imx6ull-alientek-emmc.dts , in the iomuxc node
Add the " pinctrl_test " node under the " imx6ul-evk " sub-node in . After the addition is complete, it looks like this:
Sample code 45.1.2.10 test device pinctrl node
1 pinctrl_test : testgrp {
2 /* Specific PIN information */
3 };
2. Add "fsl, pins" attribute
The device tree stores information through attributes, so we need to add an attribute, the attribute name must be " fsl,pins ",
Because for the I.MX series SOC , the pinctrl driver obtains the configuration of the PIN by reading the " fsl,pins " attribute value
After the configuration information is completed, it will look like this:
Sample code 45.1.2.11 Add "fsl, pins" attribute
1 pinctrl_test : testgrp {
2
fsl , pins = <
3 /* PIN configuration information used by the device */
4 >;
5 };
3. Add PIN configuration information in the " fsl,pins " attribute
Finally, add specific PIN configuration information in the " fsl,pins " attribute , as follows after completion:
Example code 45.1.2.13 complete test device pinctrl child node
1 pinctrl_test : testgrp {
2
fsl , pins = <
3 MX6UL_PAD_GPIO1_IO00__GPIO1_IO00 config /*config is the specific setting value */
4 >;
5 };

Guess you like

Origin blog.csdn.net/TyearLin/article/details/131842176