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 gpiochip0: GPIOs 0-31, parent: platform/30200000.gpio, 30200000.gpio: gpio-7 ( |eth_phy_pwr ) out lo gpio-9 ( |phy-reset ) out hi gpiochip1: GPIOs 32-63, parent: platform/30210000.gpio, 30210000.gpio: gpio-38 ( |sysfs ) out hi gpio-39 ( |sysfs ) out hi gpio-42 ( |sysfs ) out hi gpio-43 ( |enable ) out hi gpio-44 ( |cd ) in lo IRQ gpio-51 ( |VSD_3V3 ) out hi gpio-52 ( |sysfs ) out lo gpiochip2: GPIOs 64-95, parent: platform/30220000.gpio, 30220000.gpio: gpiochip3: GPIOs 96-127, parent: platform/30230000.gpio, 30230000.gpio: gpio-102 ( |Back ) in hi IRQ gpio-104 ( |ov5640_mipi_pwdn ) out lo gpio-109 ( |Home ) in hi IRQ gpio-111 ( |Down ) in hi IRQ gpio-113 ( |eMMC ) out lo gpio-114 ( |Up ) in hi IRQ gpiochip4: GPIOs 128-159, parent: platform/30240000.gpio, 30240000.gpio: gpio-133 ( |sysfs ) out lo gpio-137 ( |spi_imx ) in lo gpio-156 ( |ov5640_mipi_reset ) 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 -c 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 -t 0 -c gpiochip3 21=1
Set GPIO4_21 low:
gpioset -t 0 -c gpiochip3 21=0
Read GPIO4_21:
gpioget -c gpiochip3 21
libgpiod C++ Application
libgpiod provides bindings for C++, Python and Rust 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 GPIO0_IO05:
Makefile:
LDFLAGS = -lgpiodcxx -lgpiod # Nome do executável e arquivos fonte TARGET = main SRCS = main.cpp all: $(TARGET) $(TARGET): $(SRCS) $(CXX) $(SRCS) $(LDFLAGS) -o $(TARGET) clean: rm -f $(TARGET)
main.cpp
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-FileCopyrightText: 2023 Kent Gibson <warthog618@gmail.com> /* Minimal example of reading a single line. */ #include <cstdlib> #include <filesystem> #include <gpiod.hpp> #include <iostream> namespace { /* Example configuration - customize to suit your situation */ const ::std::filesystem::path chip_path("/dev/gpiochip0"); const ::gpiod::line::offset line_offset = 5; } /* namespace */ int main() { auto request = ::gpiod::chip(chip_path) .prepare_request() .set_consumer("get-line-value") .add_line_settings( line_offset, ::gpiod::line_settings().set_direction( ::gpiod::line::direction::INPUT)) .do_request(); ::std::cout << line_offset << "=" << (request.get_value(line_offset) == ::gpiod::line::value::ACTIVE ? "Active" : "Inactive") << ::std::endl; return EXIT_SUCCESS; }
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 imx8mm-pinfunc.h.
If you search it for GPIO4_IO2, for example, you will see a group of definitions with same prefix (pad name), "MX8MM_IOMUXC_SAI1_RXD0".
#define MX8MM_IOMUXC_SAI1_RXD0_SAI1_RX_DATA0 0x164 0x3CC 0x000 0x0 0x0 #define MX8MM_IOMUXC_SAI1_RXD0_SAI5_RX_DATA0 0x164 0x3CC 0x4D4 0x1 0x1 #define MX8MM_IOMUXC_SAI1_RXD0_PDM_DATA0 0x164 0x3CC 0x534 0x3 0x1 #define MX8MM_IOMUXC_SAI1_RXD0_CORESIGHT_TRACE0 0x164 0x3CC 0x000 0x4 0x0 #define MX8MM_IOMUXC_SAI1_RXD0_GPIO4_IO2 0x164 0x3CC 0x000 0x5 0x0 #define MX8MM_IOMUXC_SAI1_RXD0_CCMSRCGPCMIX_BOOT_CFG0 0x164 0x3CC 0x000 0x6 0x0 #define MX8MM_IOMUXC_SAI1_RXD0_SIM_M_HADDR17 0x164 0x3CC 0x000 0x7 0x0
Adding only the one with the GPIO4_IO2 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/imx8mm-var-dart.dts and add the definition for the GPIO you need in the iomuxc node.
&iomuxc { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_hog>; imx8mm-var-dart { 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/freescale/imx8mm-var-dart.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.