LinRT BSP Digital Data Software LLC 1110 Brickell Ave, Suite 430, Miami, FL 33131, USA LinRT 305-847-9042

LinRT Pin Multiplexing Wiki Page : Real-Time Linux Yocto BSP for i.MX and x86 SBC

Definition

Modern microcontrollers have got capabilities to adapt their pin layout for using peripherals with a maximum of flexibility with a limited number of pins.
The solution proposed is the IOMUX controller and Pin Multiplexing by giving the possibility to do an internal routing configuration of pins with electrical setting consideration, as impedance, electrical level, frequency bandwidth, default state…

IOMUX controller and Pin Multiplexing Wiki Page

Read NXP Influence of Pin Setting on System Function and Performance Application Notes for more details.

IOMUX controller and Pin Multiplexing

The Pin Multiplexing (IOMUX Controller) can be set by Bootloader and Linux Kernel at boot time, and usually define by pinctrl nodes in the device tree.
MCU/MPU proposes a specific PAD definition for each PIN, a default IOMUX PAD setting at boot time, and the possibility to change it by an alternate configuration.
For the Linux Kernel, the pin functions definitions files can be found in directory arch/arm/boot/dts/ and depending on the platform you are using.
For example NXP iMX6QDL, the PAD defines by the relevant files imx6dl-pinfunc.h and imx6q-pinfunc.h, and read i.MX6QDL Reference Manual for more details.

Example of PAD entries for Phytec Mira phyCORE-i.MX6Q SBC Connector X17-30 signal :

PC-HOST$ cat kernel-source/arch/arm/boot/dts/imx6q-pinfunc.h | grep MX6QDL_PAD_SD3_DAT2
#define MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x2c8 0x6b0 0x000 0x0 0x0
#define MX6QDL_PAD_SD3_DAT2__GPIO7_IO06 0x2c8 0x6b0 0x000 0x5 0x0

Note: only two functions are defined for this Pin, iMX6QDL can have up to 8 alternate functions for one Pin.

Devicetree Implementation of IOMUX

Simple peripheral IOMUX pinctrl

The following pinctrl example of devicetree gives the definition of 4 signals using by the SPI_1 controller.
Example with SPI_1 controller Phytec phyCORE-i.MX6Q SOM ./arch/arm/boot/dts/imx6qdl-phytec-phycore-som.dtsi

&ecspi1 {
    pinctrl-names = "default";
    pinctrl-0 = <&pinctrl_ecspi1>;
    cs-gpios = <&gpio3 19 GPIO_ACTIVE_LOW>;
    status = "okay";

    m25p80: flash@0 {
       compatible = "jedec,spi-nor";
       spi-max-frequency = <20000000>;
       reg = <0>;
       status = "disabled";
    };
};


&iomux {
[...]
    pinctrl_ecspi1: ecspi1grp {
        fsl,pins = <
                   MX6QDL_PAD_EIM_D16__ECSPI1_SCLK 0x100b1
                   MX6QDL_PAD_EIM_D17__ECSPI1_MISO 0x100b1
                   MX6QDL_PAD_EIM_D18__ECSPI1_MOSI 0x100b1
                   MX6QDL_PAD_EIM_D19__GPIO3_IO19 0x1b0b0
        >;
    };
};

In this example, one pinctrl node is defined, corresponding the “default” pinctrl definition used by the imx-spi.c driver, and the PAD should be set only if the driver is probed !

If the peripheral is not activate by devicetree status set to “okay” or the peripheral driver is not compiled with the kernel, the  PAD corresponding will be set as the default alternate function defined for the MPU/MCU.

PAD settings concatenation

For some usage like spi or i2c bus controller, ICs connected to the bus can need ENABLE, RESET and/or INTERRUPT signals. In this case, it is possible to concatenate the pintctrl-0 with multiple entries.
Example with devicetree camera bindings on Phytec Nunki phyCORE-i.MX6Q SBC ./arch/arm/boot/dts/imx6qdl-phytec-phycore-som.dtsi

 /* OV5642-CSI0 */
ov5642_0: ov564x_0@3c {
    compatible = "ovti,ov564x";
    reg = <0x3c>;
    pinctrl-names = "default";
    pinctrl-0 = <&pinctrl_cam0data &pinctrl_cam0clk>;

[...]
};


&iomux { 
    ...

    pinctrl_cam0clk: cam0clkgrp {
        fsl,pins = <
            MX6QDL_PAD_GPIO_0__CCM_CLKO1 0xb9
        >;
    };

    pinctrl_cam0data: cam0datagrp {
        fsl,pins = <
            MX6QDL_PAD_CSI0_DAT8__IPU1_CSI0_DATA08 0x1b0b0
            MX6QDL_PAD_CSI0_DAT9__IPU1_CSI0_DATA09 0x1b0b0
            MX6QDL_PAD_CSI0_DAT10__IPU1_CSI0_DATA10 0x1b0b0
            MX6QDL_PAD_CSI0_DAT11__IPU1_CSI0_DATA11 0x1b0b0
            MX6QDL_PAD_CSI0_DAT12__IPU1_CSI0_DATA12 0x1b0b0
            MX6QDL_PAD_CSI0_DAT13__IPU1_CSI0_DATA13 0x1b0b0
            MX6QDL_PAD_CSI0_DAT14__IPU1_CSI0_DATA14 0x1b0b0
            MX6QDL_PAD_CSI0_DAT15__IPU1_CSI0_DATA15 0x1b0b0
            MX6QDL_PAD_CSI0_DAT16__IPU1_CSI0_DATA16 0x1b0b0
            MX6QDL_PAD_CSI0_DAT17__IPU1_CSI0_DATA17 0x1b0b0
            MX6QDL_PAD_CSI0_DAT18__IPU1_CSI0_DATA18 0x1b0b0
            MX6QDL_PAD_CSI0_DAT19__IPU1_CSI0_DATA19 0x1b0b0
            MX6QDL_PAD_CSI0_MCLK__IPU1_CSI0_HSYNC 0x1b0b0
            MX6QDL_PAD_CSI0_PIXCLK__IPU1_CSI0_PIXCLK 0x4001b0b0
            MX6QDL_PAD_CSI0_VSYNC__IPU1_CSI0_VSYNC 0x1b0b0
       >;
    };
};

Multiple IOMUX pinctrl settings definition

For some peripherals, itis possible to define different PAD configurations depending on a specific mode as sleeping mode, or specific speed usage by adding extra pinctrl configuration. Example of 3 frequency adaptations for SDHC controller PAD on Phytec phyFLEX-i.MX6Q Rapid Development Kit ./arch/arm/boot/dts/imx6qdl-phytec-pfla02.dtsi

&usdhc3 {
    pinctrl-names = "default", "state_100mhz", "state_200mhz";

    pinctrl-0 = <&pinctrl_usdhc3 &pinctrl_usdhc3_cdwp>;
    pinctrl-1 = <&pinctrl_usdhc3_100mhz &pinctrl_usdhc3_cdwp>;
    pinctrl-2 = <&pinctrl_usdhc3_200mhz &pinctrl_usdhc3_cdwp>;
    ...

};

&iomux { 
... 
    pinctrl_usdhc3: usdhc3grp {
        fsl,pins = <
            MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059
            MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059
            MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059
            MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059
            MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059
            MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059
        >;
    };

    pinctrl_usdhc3_100mhz: usdhc3grp100mhz {
        fsl,pins = <
            MX6QDL_PAD_SD3_CMD__SD3_CMD 0x170b9
            MX6QDL_PAD_SD3_CLK__SD3_CLK 0x100b9
            MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x170b9
            MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x170b9
            MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x170b9
            MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x170b9
        >;
    };

    pinctrl_usdhc3_200mhz: usdhc3grp200mhz {
        fsl,pins = <
            MX6QDL_PAD_SD3_CMD__SD3_CMD 0x170f9
            MX6QDL_PAD_SD3_CLK__SD3_CLK 0x100f9
            MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x170f9
            MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x170f9
            MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x170f9
            MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x170f9
        >;
    };

    pinctrl_usdhc3_cdwp: usdhc3cdwp {
        fsl,pins = <
            MX6QDL_PAD_ENET_RXD0__GPIO1_IO27 0x1b0b0
            MX6QDL_PAD_ENET_TXD1__GPIO1_IO29 0x1b0b0
        >;
    };
};

For more details about pin multiplexing, see Linux devicetree imx pinctrl-bindings documentation

 

LinRT Real-Time Linux Yocto BSP Helpdesk Support
Help-Desk LinRT Real-Time Linux Yocto BSP Helpdesk Support