Controlling GPIO in Linux
This application note shows how to control STM32MP1 GPIOs in Linux.
1. Kernel sys Interface to GPIO is Deprecated
Starting with Linux kernel version 6.0, the /sys/class/gpio
interface is removed from the kernel. The libgpiod3
library and utilities from the libgpiod-tools
package should be used to configure and control processor's GPIOs from the user space.
2. Changes to the Kernel Configuration
No changes in the kernel configuration is required to control GPIOs from the user space in Linux.
It must be ensured though that the GPIO pin to be controlled from the user space is not assigned to any driver in Linux. The GPIO assignments for all the available pins can be found out using the gpioinfo
utility in the Linux command line and from the /sys/kernel/debug/gpio
file:
root@stm32mp15-som:~# gpioinfo
gpiochip0 - 16 lines:
line 0: "PA0" input
line 1: "PA1" input consumer="kernel"
line 2: "PA2" input consumer="kernel"
…
line 10: "PD10" output consumer="regulators:sub_nrst-regulator"
line 11: "PD11" output consumer="regulators:eth_reg"
line 12: "PD12" input
line 13: "PD13" output consumer="panel-backlight"
line 14: "PD14" output consumer="regulators:usb-host-regulator"
line 15: "PD15" input
…
root@stm32mp15-som:~# cat /sys/kernel/debug/gpio
gpiochip0: GPIOs 0-15, parent: platform/soc:pinctrl@50002000, GPIOA:
gpio-0 (PA0 )
gpio-1 (PA1 )
gpio-2 (PA2 )
…
gpio-58 (PD10 |regulators:sub_nrst-) out hi
gpio-59 (PD11 |regulators:eth_reg ) out hi
gpio-60 (PD12 )
gpio-61 (PD13 |panel-backlight ) out hi
gpio-62 (PD14 |regulators:usb-host-) out hi
3. Testing GPIO
For the User Push Button 1 the specific pin is MCO1 (PI11). The signal is pulled up when the button is not pressed and is driven low when the button is pressed. The gpioget
command is used to print the state of a GPIO line. The command may be supplied with the active-low parameter if the requested signal is active low, as, for example, the line for the User Push Button 1. So, if the command is issued when the button is not pressed, the output should indicate that the line is not active:
root@stm32mp15-som:~# gpioget --active-low PI11
"PI11"=inactive
If the command issued with the button pressed, the output should indicate that the line is active:
root@stm32mp15-som:~# gpioget --active-low PI11
"PI11"=active
After the button is released, the line becomes inactive again:
For the User LED 1 the specific pin is A13. Now run the following shell command to turn the User LED 1 on and off at a 1Hz frequency:
4. Alternative Ways to Access GPIO
In Linux, you may access GPIOs using different approaches, not only the ones described in this application note above. Here are some external links that might be usefull if you decide to try an alternative approach.
ITo work with GPIOs from the user space, there are the following possibilities:
Using the drivers of the Linux LED/Input subsystems:
https://www.kernel.org/doc/Documentation/leds/leds-class.txt
https://www.kernel.org/doc/Documentation/input/input.txt
These drivers allow to use different GPIO-related mechanisms already implemented in Linux. For example, you may simply force a LED connected to GPIO output to blink with the specified frequency, or simply force input subsystem to generate a some-button-pressed event on changing GPIO input.
5. Controlling GPIO from Kernel
The following article describes accessing GPIOs from the kernel context:
https://lwn.net/Articles/532714/
As an example of a device driver that makes use of the kernel GPIO APIs, refer to the device driver for the Goodix touch-screen controller. The device driver configures and uses a GPIO input for interrupt.
The relevant device tree file is linux-stm32mp/arch/arm/boot/dts/stm32mp157a-som.dts
. Refer specifically to the goodix_ts@14
node and the goodix,irq-gpio
property.
The device driver itself is linux/drivers/input/touchscreen/goodix.c. Refer specifically to the goodix_get_gpio_config()
, devm_request_threaded_irq()
, gpiod_direction_output()
, and gpiod_direction_input()
functions.