MX8M GPIO
GPIO state
The current state of the system's GPIOs can be obtained in user-mode, as shown in the following example:
# cat /sys/kernel/debug/gpio gpiochip3: GPIOs 0-31, parent: platform/47400080.gpio, 47400080.gpio: gpio-0 ( |spi0 CS0 ) out hi ACTIVE LOW gpio-1 ( |sda ) in lo gpio-7 ( |regulator-eqos-phy ) out hi gpiochip0: GPIOs 32-63, parent: platform/43810080.gpio, 43810080.gpio: gpio-43 ( |powerdown ) out hi gpio-44 ( |spi1 CS0 ) out hi ACTIVE LOW gpio-49 ( |cam_buf_dis ) in lo gpio-50 ( |regulator-usdhc2 ) out hi gpio-54 ( |sda ) in lo gpio-55 ( |scl ) out lo gpio-60 ( |sda ) in lo gpio-61 ( |scl ) out lo gpiochip1: GPIOs 64-95, parent: platform/43820080.gpio, 43820080.gpio: gpio-64 ( |cd ) in lo IRQ ACTIVE LOW gpio-71 ( |regulator-usdhc3 ) out hi gpio-91 ( |reset ) out hi ACTIVE LOW gpiochip2: GPIOs 96-127, parent: platform/43830080.gpio, 43830080.gpio: gpio-110 ( |regulator-wl-on ) out hi gpiochip4: GPIOs 504-511, parent: i2c/4-0020, 4-0020, can sleep: gpio-505 ( |Back ) in hi IRQ ACTIVE LOW gpio-506 ( |Home ) in hi IRQ ACTIVE LOW gpio-507 ( |Menu ) in hi IRQ ACTIVE LOW gpio-509 ( |regulator-fec-phy-rs) out hi gpio-510 ( |regulator-fec-phy-vs) out hi gpio-511 ( |regulator-fec-phy ) out hi
Each GPIO is defined as in or out and the state is shown as lo or hi.
For example pin 44 is the SD card card-detect.
When an SD card is plugged in, the state will be:
gpio-44 ( |cd ) in lo IRQ
When the SD card is removed, the state will be:
gpio-44 ( |cd ) in hi IRQ
Manipulating GPIO using libgpiod
The Linux GPIO sysfs interface is being deprecated. Moving forward, user space should use the character device /dev/gpiochip*
instead. libgpiod provides bindings and utilities for for manipulating GPIO via user space.
libgpiod via command line
libgpiod provides command line utilities for GPIO:
gpiodetect | List all gpiochips present on the system, their names, labels and number of GPIO lines |
gpioinfo | List all lines of specified gpiochips, their names, consumers, direction, active state and additional flags |
gpioget | Read values of specified GPIO lines |
gpioset | Set values of specified GPIO lines, potentially keep the lines exported and wait until timeout, user input or signal |
gpiofind | Find the gpiochip name and line offset given the line name |
gpiomon | Wait for events on GPIO lines, specify which events to watch, how many events to process before exiting or if the events should be reported to the console |
i.MX GPIOs are organized in banks of 32 pins. Each bank corresponds to a character device /dev/gpiochip<bank index>
. The gpiodetect
utility can be used to inspect the available gpiochip character devices:
# gpiodetect gpiochip0 [30200000.gpio] (32 lines) gpiochip1 [30210000.gpio] (32 lines) ...
The gpioinfo
utility can be used to inspect the lines for a given gpiochip:
# gpioinfo gpiochip0 gpiochip0 - 32 lines: line 0: unnamed "spi_imx" output active-high [used] line 1: unnamed unused input active-high line 2: unnamed unused input active-high ...
The gpioset
and gpioget
utilities can be used to manipulate GPIO from the command line.
For example, assuming GPIO4_21 is configured as a GPIO in your device tree:
Set GPIO4_21 high:
gpioset gpiochip3 21=1
Set GPIO4_21 low:
gpioset gpiochip3 21=0
Read GPIO4_21:
gpioget gpiochip3 21
libgpiod C Application
libgpiod provides bindings for C/C++ applications. C++ examples are available in the libgpiod /tree/bindings/cxx/examples directory.
Below is a simple C application demonstrating how to use the bindings with GPIO4_IO21:
Makefile:
all: main.cpp $(CC) $(CCFLAGS) -Og -lgpiod main.c -g -o hello.bin clean: rm -f hello.bin
main.c
#include <gpiod.h> #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <string.h> #define CONSUMER "Variscite Demo" int main(int argc, char **argv) { unsigned int i, ret, val; struct gpiod_chip *chip; struct gpiod_line *line; const char * chipname = "gpiochip3"; const unsigned int line_num = 21; chip = gpiod_chip_open_by_name(chipname); if (!chip) { perror("Open chip failed\n"); goto end; } line = gpiod_chip_get_line(chip, line_num); if (!line) { perror("Get line failed\n"); goto close_chip; } ret = gpiod_line_request_output(line, CONSUMER, 0); if (ret < 0) { perror("Request line as output failed\n"); goto release_line; } /* Blink 5 times */ val = 0; for (i = 0; i < 5; i++) { ret = gpiod_line_set_value(line, val); if (ret < 0) { perror("Set line output failed\n"); goto release_line; } printf("Output %u on line #%u\n", val, line_num); sleep(1); val = !val; } release_line: gpiod_line_release(line); close_chip: gpiod_chip_close(chip); end: return 0; }
libgpiod Python Application
libgpiod provides bindings for python applications:
# pip3 install gpiod
Python examples are available in the libgpiod /tree/bindings/python/examples directory.
Kernel Device Tree GPIO configuration
Device Tree GPIO files
Pin Func files
In the directory arch/arm64/boot/dts/freescale of the Linux kernel source you will find the pin functions definition files.
The relevant file is imx93-pinfunc.h.
If you search it for GPIO_IO25, for example, you will see a group of definitions with same prefix (pad name), "MX93_PAD_GPIO_IO25".
#define MX93_PAD_GPIO_IO25__GPIO2_IO25 0x0074 0x0224 0x0000 0x0 0x0 #define MX93_PAD_GPIO_IO25__USDHC3_DATA1 0x0074 0x0224 0x0464 0x1 0x0 #define MX93_PAD_GPIO_IO25__CAN2_TX 0x0074 0x0224 0x0000 0x2 0x0 #define MX93_PAD_GPIO_IO25__MEDIAMIX_DISP_DATA21 0x0074 0x0224 0x0000 0x3 0x0 #define MX93_PAD_GPIO_IO25__TPM4_CH3 0x0074 0x0224 0x0000 0x4 0x0 #define MX93_PAD_GPIO_IO25__JTAG_MUX_TCK 0x0074 0x0224 0x03D4 0x5 0x1 #define MX93_PAD_GPIO_IO25__LPSPI7_PCS1 0x0074 0x0224 0x0000 0x6 0x0 #define MX93_PAD_GPIO_IO25__FLEXIO1_FLEXIO25 0x0074 0x0224 0x03C4 0x7 0x0
Adding only the one with the GPIO_IO25 suffix (function) to your dts file will let you use the pin as GPIO.
Define a pin as GPIO in the kernel Device Tree
You need to add the relevant definitions to your device tree, as explained in the Pin Func files section above.
Edit arch/arm64/boot/dts/freescale/imx93-var-som-symphony.dts and add the definition for the GPIO you need in the iomuxc node.
&iomuxc { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_hog>; pinctrl_hog: hoggrp { fsl,pins = < /* Add your GPIO definitions here */ >; }; … };
Please consult Variscite's blog post i.MX Device Tree Pinmux Settings Guide for further information.
Device Tree GPIO attribute
If you look at the pin control definitions in arch/arm64/boot/dts/ in the Linux kernel source tree, the number to the right of the pin mux macro can be used for additional attributes like pull-up, slew rate, open drain, drive strength, etc. This value is written to the IOMUXC_SW_PAD_CTRL_ register of the relevant pin.
Please consult the SOC reference manual for details about the relevant register.