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 GPIOrelated 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 setThe 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 initialThe 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 node1 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" attribute1 pinctrl_test : testgrp {2fsl , 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 node1 pinctrl_test : testgrp {2fsl , pins = <3 MX6UL_PAD_GPIO1_IO00__GPIO1_IO00 config /*config is the specific setting value */4 >;5 };