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:
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 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:
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:
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:
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.