GPIO¶
GPIO state¶
The current state of the system's GPIOs can be obtained in user-mode, as shown in the following example:
gpiochip0: GPIOs 0-31, parent: platform/30200000.gpio, 30200000.gpio:
gpio-5 ( |hdmi_on ) out lo
gpio-7 ( |ads7846_pendown ) in hi IRQ
gpio-10 ( |int ) in hi IRQ
gpio-12 ( |spi_imx ) out hi
gpiochip1: GPIOs 32-63, parent: platform/30210000.gpio, 30210000.gpio:
gpio-38 ( |sysfs ) out hi
gpio-39 ( |sysfs ) out hi
gpio-40 ( |sysfs ) out hi
gpio-41 ( |sysfs ) out lo
gpio-42 ( |spi_imx ) out hi
gpio-44 ( |cd ) in lo IRQ ACTIVE LOW
gpio-51 ( |regulator-usdhc2-vmm) out hi
gpio-52 ( |regulator-eqos-phy-p) out hi
gpiochip2: GPIOs 64-95, parent: platform/30220000.gpio, 30220000.gpio:
gpiochip3: GPIOs 96-127, parent: platform/30230000.gpio, 30230000.gpio:
gpio-101 ( |reset ) out hi ACTIVE LOW
gpio-102 ( |Back ) in hi IRQ ACTIVE LOW
gpio-104 ( |powerdown ) out hi
gpio-105 ( |powerdown ) out hi
gpio-108 ( |reset ) out hi ACTIVE LOW
gpio-109 ( |Home ) in hi IRQ ACTIVE LOW
gpio-111 ( |Down ) in hi IRQ ACTIVE LOW
gpio-113 ( |eMMC ) out lo
gpio-114 ( |Up ) in hi IRQ ACTIVE LOW
gpiochip4: GPIOs 128-159, parent: platform/30240000.gpio, 30240000.gpio:
gpio-137 ( |spi_imx ) out hi
gpio-142 ( |scl ) out lo
gpio-143 ( |sda ) in lo
gpio-144 ( |scl ) out lo
gpio-145 ( |sda ) in lo
gpio-146 ( |scl ) out lo
gpio-147 ( |sda ) in lo
gpio-148 ( |scl ) out lo
gpio-149 ( |sda ) in lo
gpio-156 ( |reset ) out hi ACTIVE LOW
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:
When the SD card is removed, the state will be:
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:
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:
Set GPIO4_21 low:
Read GPIO4_21:
Note: To verify the output value of a GPIO pin after using the gpioset command, you can physically connect (jumper) it to a separate GPIO configured as an input. Then, use the gpioget command on the input pin to read the output state.
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 <[email protected]>
/* 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:
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 imx8mp-pinfunc.h.
If you search it for GPIO4_IO22, for example, you will see a group of definitions with same prefix (pad name), "MX8MP_IOMUXC_SAI2_RXC".
#define MX8MP_IOMUXC_SAI2_RXC__AUDIOMIX_SAI2_RX_BCLK 0x1A0 0x400 0x000 0x0 0x0
#define MX8MP_IOMUXC_SAI2_RXC__AUDIOMIX_SAI5_TX_BCLK 0x1A0 0x400 0x50C 0x1 0x2
#define MX8MP_IOMUXC_SAI2_RXC__CAN1_TX 0x1A0 0x400 0x000 0x3 0x0
#define MX8MP_IOMUXC_SAI2_RXC__UART1_DCE_RX 0x1A0 0x400 0x5E8 0x4 0x3
#define MX8MP_IOMUXC_SAI2_RXC__UART1_DTE_TX 0x1A0 0x400 0x000 0x4 0x0
#define MX8MP_IOMUXC_SAI2_RXC__GPIO4_IO22 0x1A0 0x400 0x000 0x5 0x0
#define MX8MP_IOMUXC_SAI2_RXC__AUDIOMIX_PDM_BIT_STREAM01 0x1A0 0x400 0x4C4 0x6 0x5
Adding only the one with the GPIO4_IO22 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/imx8mp-var-dart-dt8mcustomboard.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/freescale/imx8mp-var-dart-dt8mcustomboard.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.