2025-07-11 3:54 AM - edited 2025-07-11 3:56 AM
Using board based on stm32mp135f MPU, my goal is to configure a GPIO pin (let's say PD0, already freed from using with CAN) as a simple GPIO Output, active-high, with pull-up.
I read following ST Wiki entires:
- Overview of GPIO pins,
- GPIOLib overview,
- How_to_control_a_GPIO_in_userspace,
- How_to_control_a_GPIO_in_kernel_space,
- GPIO_device_tree_configuration
and additionally this FAQ: faq-stm32mp1-how-to-get-initialized-a-generic-gpio-to-control
This pin is free, so it can be set with gpioset command. But this holds the configuration only as long as the gpioset process is active in Linux, which is bad. And the configuration is not active when Linux boots.
Following this FAQ I have written a dummy device 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 "dummy GPIO device driver init\n");
return(0);
}
static int gpio_exit_remove(struct platform_device *pdev)
{
printk(KERN_INFO "dummy GPIO device driver exit\n");
return(0);
}
/* this structure does the matching with the device tree */
/* if it does not match the compatible field of DT, nothing happens */
static struct of_device_id dummy_match[] = {
{.compatible = "st,dummy-gpio-driver"},
{/* end node */}
};
static struct platform_driver dummy_gpio_driver = {
.probe = gpio_init_probe,
.remove = gpio_exit_remove,
.driver = {
.name = "dummy_gpio_driver",
.owner = THIS_MODULE,
.of_match_table = dummy_match,
}
};
module_platform_driver(dummy_gpio_driver);
MODULE_AUTHOR("MM");
MODULE_DESCRIPTION("Dummy GPIO device driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:dummy_gpio_driver");
I later created a pinctrl entry for that pin:
test_gpio_pins_a: test_gpio_pins-0 {
pins {
pinmux = <STM32_PINMUX('D', 0, GPIO)>;
bias-pull-up;
drive-push-pull;
slew-rate = <0>;
};
};
And node in DT root:
test_gpio {
compatible = "st,dummy-gpio-driver";
pinctrl-names = "default";
pinctrl-0 = <&test_gpio_pins_a>;
status = "okay";
};
When applied, the pin gets pulled-up. But from that moment it can't be longer used with gpioset (gpioset can't request it)
Later on I tried doing:
test_gpio {
compatible = "st,dummy-gpio-driver";
test-gpios = <&gpiod 0 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>;
status = "okay";
};
so without pinctrl at all. And I also added
gpiod_get(&pdev->dev, "test", GPIOD_OUT_HIGH);
in driver init_probe function.
But the result is the same -> pin can no longer be used with gpioset.
What is interesting, in FAQ I have mentioned, pin is configured that way but gpioset seems to still be able to request the pin...
Is there something I am missing? Do I really need to choose to only use kernel device driver (and not using gpioset anymore) or only use gpioset tool. In the first case, how can I control pin from userspace (communicate with that kernel driver?)? In the second case, how to configure pin permanently, so that is configured after reboot, and without that process running in background?