Contents

Linux Kernel GPIO support

Linux Driver

The i.MX GPIO driver is located at drivers/gpio/gpio-mxc.c and manages GPIO controllers by banks of 32 GPIOs.
Kernel setting for i.MX GPIOs is automatically provided through the non-visible option CONFIG_GPIO_MXC.

Devicetree GPIO Controller Bindings

All GPIO controllers are defined in devicetree. For example, the i.MX6QDL

gpio1: gpio@0209c000 {
    compatible = "fsl,imx6q-gpio", "fsl,imx35-gpio";
    reg = <0x0209c000 0x4000>;
    interrupts = <0 66 IRQ_TYPE_LEVEL_HIGH>,
    <0 67 IRQ_TYPE_LEVEL_HIGH>;
    gpio-controller;
    #gpio-cells = <2>;
    interrupt-controller;
    #interrupt-cells = <2>;
};

Devicetree GPIO IOMUX configuration

You must configure the pads that are to be used as i.MX6 GPIOs. See Pin multiplexing (IOMUX).

gpio1: gpio@0209c000 {
    compatible = "fsl,imx6q-gpio", "fsl,imx35-gpio";
    reg = <0x0209c000 0x4000>;
    interrupts = <0 66 IRQ_TYPE_LEVEL_HIGH>,
    <0 67 IRQ_TYPE_LEVEL_HIGH>;
    gpio-controller;
    #gpio-cells = <2>;
    interrupt-controller;
    #interrupt-cells = <2>;
};

For GPIOs that are managed by other drivers, you must configure their pad IOMUX inside the driver node-specific pinctrl-X to work according to the specified interface functionalities.

Device Tree GPIO attribute

If you look at Documentation/devicetree/bindings/pinctrl/fsl,imx6q-pinctrl.txt in the Linux kernel source tree, the number to the right of the pin control spec can be used for additional attributes like pull-ups, pull-downs, keepers, drive strength, etc.
The value 0x80000000 is “don’t know value please use the default”. Otherwise, the value consists of a bitwise-OR combination of the following values.

i.MX6QDL

CONFIG bits definition:
PAD_CTL_HYS                     (1 << 16)
PAD_CTL_PUS_100K_DOWN           (0 << 14)
PAD_CTL_PUS_47K_UP              (1 << 14)
PAD_CTL_PUS_100K_UP             (2 << 14)
PAD_CTL_PUS_22K_UP              (3 << 14)
PAD_CTL_PUE                     (1 << 13)
PAD_CTL_PKE                     (1 << 12)
PAD_CTL_ODE                     (1 << 11)
PAD_CTL_SPEED_LOW               (1 << 6)
PAD_CTL_SPEED_MED               (2 << 6)
PAD_CTL_SPEED_HIGH              (3 << 6)
PAD_CTL_DSE_DISABLE             (0 << 3)
PAD_CTL_DSE_240ohm              (1 << 3)
PAD_CTL_DSE_120ohm              (2 << 3)
PAD_CTL_DSE_80ohm               (3 << 3)
PAD_CTL_DSE_60ohm               (4 << 3)
PAD_CTL_DSE_48ohm               (5 << 3)
PAD_CTL_DSE_40ohm               (6 << 3)
PAD_CTL_DSE_34ohm               (7 << 3)
PAD_CTL_SRE_FAST                (1 << 0)
PAD_CTL_SRE_SLOW                (0 << 0)

i.MX7D

CONFIG bits definition:
PAD_CTL_PUS_100K_DOWN           (0 << 5)
PAD_CTL_PUS_5K_UP               (1 << 5)
PAD_CTL_PUS_47K_UP              (2 << 5)
PAD_CTL_PUS_100K_UP             (3 << 5)
PAD_CTL_PUE                     (1 << 4)
PAD_CTL_HYS                     (1 << 3)
PAD_CTL_SRE_SLOW                (1 << 2)
PAD_CTL_SRE_FAST                (0 << 2)
PAD_CTL_DSE_X1                  (0 << 0)
PAD_CTL_DSE_X4                  (1 << 0)
PAD_CTL_DSE_X2                  (2 << 0)
PAD_CTL_DSE_X6                  (3 << 0)

i.MX8M-Mini

CONFIG bits definition:
PAD_CTL_LVTTL (1 << 8)
PAD_CTL_HYS (1 << 7)
PAD_CTL_PUE (1 << 6)
PAD_CTL_ODE (1 << 5)
PAD_CTL_SRE_SLOW (0 << 3)
PAD_CTL_SRE_MED (1 << 3)
PAD_CTL_SRE_FAST (2 << 3)
PAD_CTL_SRE_MAX (3 << 3)
PAD_CTL_DSE_HIZ (0 << 0)
PAD_CTL_DSE_255 (1 << 0)
PAD_CTL_DSE_105 (2 << 0)
PAD_CTL_DSE_75 (3 << 0)
PAD_CTL_DSE_85 (4 << 0)
PAD_CTL_DSE_65 (5 << 0)
PAD_CTL_DSE_45 (6 << 0)
PAD_CTL_DSE_40 (7 << 0)

i.MX8M-nano

CONFIG bits definition:
PAD_CTL_PE (1 << 8)
PAD_CTL_HYS (1 << 7)
PAD_CTL_PUE (1 << 6)
PAD_CTL_ODE (1 << 5)
PAD_CTL_SRE_SLOW (0 << 4)
PAD_CTL_SRE_FAST (1 << 4)
PAD_CTL_DSE_X1 (0 << 1)
PAD_CTL_DSE_X4 (1 << 1)
PAD_CTL_DSE_X2 (2 << 1)
PAD_CTL_DSE_X6 (3 << 1)

NO_PAD_CTL (1 << 31) indicates this pin does not need config.

SION bit is not possible to read the real signal level of a GPIO pin that is configured as an output. You can use the software input on (SION) bit to read the value of an output GPIO.

To enable the SION bit, set the bit 30 (special value). For example, to enable the SION bit for EXP_GPIO_0, use the following in the device tree (note that 0x80000000 | (1 << 30) = 0xC0000000 ):

Note: SION bit mode increases the power consumption of the module, so it is disabled by default.

Linux User GPIO support

GPIO state

The current state of the system’s GPIOs can be obtained in user-mode, as shown in the following example:

root@var-som-mx6:~# cat /sys/kernel/debug/gpio 
GPIOs 0-31, platform/209c000.gpio, 209c000.gpio:
 gpio-25  (phy-reset           ) out lo    

GPIOs 32-63, platform/20a0000.gpio, 20a0000.gpio:

GPIOs 64-95, platform/20a4000.gpio, 20a4000.gpio:
 gpio-77  (ov5640_mipi_pwdn    ) out lo    
 gpio-86  (usb_otg_vbus        ) out lo    

GPIOs 96-127, platform/20a8000.gpio, 20a8000.gpio:
 gpio-101 (tlv320aic3x reset   ) out lo    
 gpio-106 (ov5640_mipi_reset   ) out lo    
 gpio-110 (2194000.usdhc cd    ) in  hi    
 gpio-111 (2194000.usdhc ro    ) in  hi    
 gpio-120 (spi_imx             ) out lo    
 gpio-121 (ads7846_pendown     ) in  hi    

GPIOs 128-159, platform/20ac000.gpio, 20ac000.gpio:
 gpio-141 (PCIe reset          ) out lo    

GPIOs 160-191, platform/20b0000.gpio, 20b0000.gpio:
 gpio-178 (sysfs               ) out lo    

GPIOs 192-223, platform/20b4000.gpio, 20b4000.gpio:
 gpio-200 (wlan-en-regulator   ) out lo  

Each GPIO is defined as in or out and the state is shown as lo or hi.
For example pin 110 is the SD card card-detect. When an SD card is plugged in, the state will be:

 gpio-110 (2194000.usdhc cd    ) in  lo

When the SD card is removed, the state will be:

 gpio-110 (2194000.usdhc cd    ) in  hi 

Hog GPIO devicetree Pin Multiplexing

Assuming this GPIO is defined in your device tree, and not reserved by a driver by checking GPIO State, see the previous chapter. The following is an example of how to define in devicetree an IOMUX GPIOs node specifically for using them directly from the userspace.

Example for phyFLEX-i.MX6 RDK imx6qdl-phytec-pfla02.dtsi device tree

&iomuxc {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_hog>;
	[...]
	pinctrl_hog: hoggrp {
		fsl,pins = <
			MX6QDL_PAD_SD4_DAT1__GPIO2_IO09 0x1b0b0 /* PMIC interrupt */
			MX6QDL_PAD_ENET_TXD0__GPIO1_IO30 0x1b0b0 /* Green LED */
			MX6QDL_PAD_EIM_EB3__GPIO2_IO31 0x1b0b0 /* Red LED */
			MX6QDL_PAD_DISP0_DAT14__GPIO5_IO08 0x1b0b0 /* GPIO00 */
			MX6QDL_PAD_DISP0_DAT13__GPIO5_IO07 0x1b0b0 /* GPIO01 */
			MX6QDL_PAD_DI0_PIN2__GPIO4_IO18 0x1b0b0 /* GPIO02 */
			MX6QDL_PAD_DI0_PIN3__GPIO4_IO19 0x1b0b0 /* GPIO03 */
			MX6QDL_PAD_GPIO_6__GPIO1_IO06 0x1b0b0 /* GPIO04 */
			MX6QDL_PAD_GPIO_9__GPIO1_IO09 0x1b0b0 /* GPIO05 */
			/* MX6QDL_PAD_GPIO_17__GPIO7_IO12 0x1b0b0*/ /* GPIO06 */
			MX6QDL_PAD_GPIO_18__GPIO7_IO13 0x1b0b0 /* GPIO07 */
			MX6QDL_PAD_GPIO_19__GPIO4_IO05 0x1b0b0 /* GPIO08 */
			MX6QDL_PAD_EIM_CS0__GPIO2_IO23 0xb0b1 /* GPIO09 */
			MX6QDL_PAD_EIM_CS1__GPIO2_IO24 0xb0b1 /* GPIO10 */
		>;
	};
	[...]
};

Manipulating a single GPIO via /sys/class/gpio

GPIOs in i.MX are grouped in groups of 32 pins.

The Linux GPIO number for a certain GPIO pin can be determined by adding the GPIO pin index to the port base index. For instance:

  • i.MX6 GPIO2_4 (port 2, pin 4) is: 32 + 4 = 36
  • PMIC GPIO3 is: 240 + 3 = 243

Since the i.MX6 CPU has seven ports, all of which have 32 pins, the following formula also applies for i.MX6 CPU GPIOs (without requiring the user to know the GPIO base of each port):

LinuxGPIO_num = (<imx6_gpio_port> – 1) * 32 + <imx6_gpio_pin>

For example, i.MX6 GPIO2_4 (port 2, pin 4) translates to: (2 – 1) * 32 + 4 = 36

For example, GPIO1_3 belongs to the first group, pin 3. Its absolute number will be 3.
GPIO7_4 will be (7-1)*32+4=196.

To export the GPIO for userspace use:

# echo 196 > /sys/class/gpio/export

To configure as output:

# echo out > /sys/class/gpio/gpio196/direction

Set GPIO high:

# echo 1 > /sys/class/gpio/gpio196/value

Set GPIO low:

# echo 0 > /sys/class/gpio/gpio196/value

To configure as input:

# echo in > /sys/class/gpio/gpio196/direction

Read the current value:

# cat /sys/class/gpio/gpio196/value

To free the GPIO after you’re done using it:

# echo 196 > /sys/class/gpio/unexport

Using the libgpiod tool

The package libgpiod (added by packagegroup-dey-core) provides a set of tools (gpioset, gpioget…​) for controlling the GPIOs from user space.

You can still control the GPIOs from the sysfs, but this ABI is not recommended. See https://www.kernel.org/doc/html/latest/admin-guide/gpio/sysfs.html.

Detect GPIO ports

Use gpiodetect to list the GPIO ports detected by the kernel:

~# gpiodetect
gpiochip0 [gpio1] (32 lines)
gpiochip1 [gpio2] (32 lines)
gpiochip2 [gpio3] (32 lines)
gpiochip3 [gpio4] (32 lines)
gpiochip4 [gpio5] (32 lines)
gpiochip5 [gpio6] (32 lines)
gpiochip6 [gpio7] (32 lines)
gpiochip7 [da9063-gpio] (16 lines)

where:

  • Ports gpio0 to gpio6 are the i.MX6 GPIO ports.

Information about a GPIO port

Use gpioinfo to list the lines of a given port:

~# gpioinfo gpio1
gpiochip0 - 32 lines:
	line   0:      unnamed       unused   input  active-high
	line   1:      unnamed       unused   input  active-high
	line   2:      unnamed       unused   input  active-high
	line   3:      unnamed        "rts"  output  active-high [used]
	line   4:      unnamed "mca-fw-update" output active-high [used]
	line   5:      unnamed       unused   input  active-high
	line   6:      unnamed   "5v_board"  output  active-high [used]
	line   7:      unnamed      "sysfs"  output  active-high [used]
	line   8:      unnamed      "sysfs"  output  active-high [used]
	line   9:      unnamed       unused   input  active-high
	line  10:      unnamed       unused   input  active-high
	line  11:      unnamed       unused   input  active-high
	line  12:      unnamed       unused  output  active-high
	line  13:      unnamed       unused   input  active-high
	line  14:      unnamed       unused   input  active-high
	line  15:      unnamed       unused   input  active-high
	line  16:      unnamed       unused   input  active-high
	line  17:      unnamed       unused   input  active-high
	line  18:      unnamed       unused   input  active-high
	line  19:      unnamed       unused   input  active-high
	line  20:      unnamed       unused   input  active-high
	line  21:      unnamed       unused   input  active-high
	line  22:      unnamed       unused   input  active-high
	line  23:      unnamed       unused   input  active-high
	line  24:      unnamed       unused   input  active-high
	line  25:      unnamed       unused   input  active-high
	line  26:      unnamed       unused   input  active-high
	line  27:      unnamed       unused   input  active-high
	line  28:      unnamed       unused   input  active-high
	line  29:      unnamed       unused   input  active-high
	line  30:      unnamed       unused   input  active-high
	line  31:      unnamed       unused   input  active-high

Set an output high/low

Use gpioset to set a i.MX6 GPIO as output, such as GPIO5_IO27. Use =1 to set it high, or =0 to set it low:

~# gpioset gpio5 27=1
~# gpioset gpio5 27=0

Read an input

Use gpioget to read the value of a i.MX6 GPIO input, such as GPIO5_IO27:

~# gpioget gpio5 27
0

Use a GPIO as interrupt

Use gpiomon to wait for an event on a given GPIO, such as GPIO5_IO27:

~# gpiomon --num-events 1 --rising-edge gpio5 27