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
