Skip to main content
Emmanuel COMBETTE DE RYMON
ST Employee
May 28, 2020

FAQ: How to initialize a 'generic GPIO' (to control a LED) with a pull-up/pull down?

  • October 14, 2026 at 12:56 PM
  • 0 replies
  • 18700 views

This article covers the following topics: 

  • How to configure and drive a standalone generic GPIO at runtime
  • How an internal pull-up is configured, using an LED as an example

This article applies to the STM32MP1 and STM32MP2 series.

Background

Two frameworks are available to configure and control a pin: pinctrl and GPIOLib. The selected framework depends on the pin usage:

  • Pinctrl is used mainly when an internal peripheral controls a pin. It handles pin configuration and allows a specific function to be assigned to a pin. The Pinctrl overview article provides an overview of the pinctrl framework.
  • GPIOLib is used when a generic GPIO must be controlled dynamically at runtime. It allows software to control a pin. The GPIOLib overview article provides an overview of the GPIOLib framework.

Dynamic GPIO reconfiguration through GPIO sysfs (/sys/class/gpio/gpioxx) is deprecated. Use GPIOLib instead.

Answer

To do this, add a GPIO property to a node in the existing device driver, or create an st,dummy device driver, as shown in the following example. This configuration initializes and controls a generic GPIO through GPIOLib.

https://wiki.st.com/stm32mpu/wiki/GPIO_device_tree_configuration

Example with a foo device driver that initializes a GPIO with the internal pull-up enabled.

In the foo device driver code:

gpiod_get(&pdev->dev, "function", GPIOD_OUT);

Device tree:

foo_device {
...
function-gpios = <&gpiob 5 GPIO_ACTIVE_HIGH | GPIO_PULL_UP>;
...
};

Examples of GPIOLib usage:

https://wiki.st.com/stm32mpu/wiki/How_to_control_a_GPIO_in_userspace

https://wiki.st.com/stm32mpu/wiki/How_to_control_a_GPIO_in_kernel_space

In OpenSTLinux Ecosystem versions earlier than 2.0.0, GPIOLib cannot initialize a GPIO with an internal pull-up or pull-down by using the GPIO_PULL_UP or GPIO_PULL_DOWN flags.

Instead, use pinctrl bindings and pinctrl with strict mode disabled. Strict mode prevents the configuration of a pin in two different places to avoid dual allocation.

At probe time, a dummy driver initializes the GPIO with the bias, that is, the internal pull-up or pull-down. GPIOLib then allows the GPIO output state to be changed to high or low.

The following example uses GPIOA14 on the STM32MP157F-DK2 board.

workspace/sources/linux-stm32mp/arch/arm/boot/dts/stm32mp157-pinctrl.dtsi
soc {

pinctrl: pin-controller@50002000 {
keyleds_pins_a: keyleds_pins_a-0 {
pins {
pinmux = <STM32_PINMUX('A', 14, GPIO)>;
bias-pull-up;
drive-push-pull;
slew-rate = <0>;
};
};
};
};

workspace/sources/linux-stm32mp/arch/arm/boot/dts/stm32mp157a-dk1.dts
/ {
ledpa4 {
compatible = "st,dummy";
pinctrl-names = "default";
pinctrl-0 = <&keyleds_pins_a>;
status = "okay";
};
};

Create a dummy driver:

#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/gpio/consumer.h>
#include <linux/platform_device.h>
static int gpio_init_probe(struct platform_device *pdev)
{
printk(KERN_INFO "GPIO example init\n");
return 0;
}
static int gpio_exit_remove(struct platform_device *pdev)
{
printk(KERN_INFO "GPIO example exit\n");
return 0;
}
/* This structure matches the device tree. */
/* If the compatible field in the device tree does not match, nothing happens. */
static struct of_device_id dummy_match[] = {
{.compatible = "st,dummy"},
{/* end node */}
};
static struct platform_driver dummy_driver = {
.probe = gpio_init_probe,
.remove = gpio_exit_remove,
.driver = {
.name = "dummy_driver",
.owner = THIS_MODULE,
.of_match_table = dummy_match,
}
};
module_platform_driver(dummy_driver);
MODULE_AUTHOR("STMicroelectronics");
MODULE_DESCRIPTION("GPIO example with pinctrl configuration");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:dummy_driver");


Test on the STM32MP157f-DK board in Linux Console window


1/ Reboot the board

more /sys/kernel/debug/pinctrl/soc\:pin-controller@50002000/pin

pin 14 (PA14): input - high - floating
 

gpioinfo gpiochip0 | grep 14

line14: unamed unused input active-high

2/ Activate the green LED by GPIOLib:

gpioset gpiochip0 14=0

The green LED is on.

more /sys/kernel/debug/pinctrl/soc\:pin-controller@50002000/pin

pin 14 (PA14): output - low - push pull - floating - low speed
 Reg: : MODE-OD(or ID) - OTYPE - PUPD - OSPEED 

 

3/ Probe dumy_device

modprobe dummy_device more /sys/kernel/debug/pinctrl/soc\:pin-controller@50002000/pin

pin 14 (PA14): output - high - push pull - pull up - low speed

4/ Activate the LED by GPIOLib:

gpioset gpiochip0 14=0

The green LED is on.

more /sys/kernel/debug/pinctrl/soc\:pin-controller@50002000/pin

pin 14 (PA14): output - low - push pull - pull up - low speed


To disable strict mode:

workspace/sources/linux-stm32mp/drivers/pinctrl/stm32/pinctrl-stm32.c

static const struct pinmux_ops stm32_pmx_ops = {
.get_functions_count = stm32_pmx_get_funcs_cnt,
.get_function_name = stm32_pmx_get_func_name,
.get_function_groups = stm32_pmx_get_func_groups,
.set_mux = stm32_pmx_set_mux,
.gpio_set_direction = stm32_pmx_gpio_set_direction,

/* PATCH GPIOLib */
.strict = false,
/* .strict = true, */

};

 

This topic has been closed for replies.