Skip to main content
tarzan2
Associate III
July 28, 2026
Question

MP2 gpioset/gpioget are either not or badly working

  • July 28, 2026
  • 5 replies
  • 56 views

Hello,

I’m using an Karo SOM module (MP257) on a custom board with SFP module.

The SFP module is powered with the main 3.3V regulator. It has a TX_DISABLE input (0=ON, 1=OFF). This input :

  • Is TTL
  • Has an internal pull-up R (around 10k)
  • Has an external pull-down R (10k)
  • In connected to PE2

This makes a voltage divider : without driving the TX_DISABLE line, the voltage is something like 3.3V / 2 (1.8V to be precise)

Some simple tests to confirm that :

  • SFP module unplugged => voltage is driven only by the pull down R => 0V
  • A source meter on the TX_DISABLE confirms the presence and value of the internal RPU.

 

Now let’s play with the MP2. Is this processor able to blink a led ? Don’t laugh, nothing could be further from the truth.

 

After linux boot :

 

gpioinfo shows PE2 is input. It should logically be driven by the driver, but for an obscure reason, this is not the case. At least we can do things manually…

 

Set it to 0 ?

gpioset -b disabled -d push-pull PE2=0

=> Voltage is still 1.8V

 

Ok, bad. Try to 1 ?

gpioset -b disabled -d push-pull PE2=1

=> Voltage is still 1.8V

 

ok, very bad. Add a bias R to the R divider ?

gpioset -b pull-down -d push-pull PE2=0
=> Voltage is still 1.8V

 

I’m checking the voltage with gpioset running.

 

Remove the external RPD : line is 3.3V, ok, but gpioget returns “inactive”. Same for another line (PE5), on 2 different boards. It's pretty unlikely that both PCBs have the same soldering issue. Probing directly on the SOM module pins show the same voltage : if the issue is hardware, it’s on the SOM module itself (at BGA level).

 

Finally, replacing the external 10k RPD by a 100ohm RPD pulls the line at 0V => SFP module is on => fiber link is set up. This is functionally working, but it would be nice to be able to drive a gpio…

 

At this point I can’t be 100% sure the problem is hw or sw.

 

I have 3 other simple outputs GPIO. Working fine, but showing the gpio driver is poorly implemented or, worse, poorly designed.

For example :

gpioset PD6=0 

  • Set PD6 = 0, working fine. This function is blocking. 
  • After exiting this function, PD6 is still 0.
  • gpioinfo : PD6 = active, ok
  • gpioget PD6 = active. But the port is now 0. Reading the port make it going back to 0.
  • gpioget PD6 = active => still active although the last command clearly reset it !

Reading an output port sometime make sense. The driver forbids that. This is basically what we can do 30 years ago using a PIC16*84 with a single step instruction… But impossible with a MP2 and a full featured OS.

Then, please, remove the --active-low options. Digital 0 is 0, 1 is 1. Hardware and software engineer can deel with inverted logic, adding a level of abstraction just make the things more ambiguous.

Finally, WTF (sorry !) the gpioset is blocking, since the GPIO keeps it direction and value once exited ?

ok, I’ve just read this on gpioset --help :

“The line output state is maintained until the process exits, but after that is not guaranteed.”

=> Not guaranteed ? Something is writing random values at random time on random free ports ? And gpioget still reads the original value ?

 

So, let’s redo it cleanly with a background task :

 

gpioset -d open-drain PD6=1 &

gpioget PD6

gpioget: unable to request lines: Device or resource busy

 

A good gpio driver shouldn’t behave that way.

 

Any help appreciated :)

Any update of the gpio driver appreciated, too.

 

5 replies

PatrickF
ST Employee
July 29, 2026

Hi ​@tarzan2 

please have a look to https://wiki.st.com/stm32mpu/wiki/How_to_control_a_GPIO_in_userspace


on STM32MP257F-EV1, this simple command set the green led ON without issues:

gpioset PD8=1
Ctrl + C

 

Notice that “gpioget” will set the IO in input (high-z), so the previous “gpioset” setting is lost. This is the expected behavior (although not instinctive).

The libgpiod is not written by ST, it is a Linux open source driver, and behavior on user space is maybe not fulfilling all cases for a specific device. See https://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git 

 

If needed, you need to write your own driver, see an example:

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


Regards

In order to give better visibility on the answered topics, please click on 'Best Answer' on the reply which solved your issue or answered your question.Tip of the day: Try Sidekick STM32 AI agent
tarzan2
tarzan2Author
Associate III
July 29, 2026

please have a look to https://wiki.st.com/stm32mpu/wiki/How_to_control_a_GPIO_in_userspace

Thank for the link, but I have already read that a long time ago.

gpioset / gpioget are working for port D, but not for port E (bit 1..5). I was suspecting this port was not clocked or not powered, but the bootflash is located on PE6..15, so PE must be properly powered/clocked. Not troed any yet, but I don’t think that driving it from the kernel space will solve this issue.

 

Notice that “gpioget” will set the IO in input (high-z), so the previous “gpioset” setting is lost. This is the expected behavior (although not instinctive).

So, in the very common case where someone has a open-drain I/O, it’s impossible to write ‘1’ and verify that nothing is externally pulling the line low. Incredibly frustrating. 

PatrickF
ST Employee
July 29, 2026

Have you tried ‘gpioinfo’ as you cannot control a GPIO which is already ‘used’ by another Linux process
notice that PE0 to PE5 are belonging to VDDIO1 domain which need to be supplied but also ‘enabled’ in the SW (usually assigning active peripherals to at least one of those pins inside Device Tree might be enough).

 


 

 


Regards.

In order to give better visibility on the answered topics, please click on 'Best Answer' on the reply which solved your issue or answered your question.Tip of the day: Try Sidekick STM32 AI agent
tarzan2
tarzan2Author
Associate III
July 29, 2026

gpioinfo shows PE1-5 are free. They should be used by the fiber driver, but this is another problem.

 

VDDIO1 domain which need to be supplied but also ‘enabled’ in the SW

 

How to do that ? I adder ‘regulator-always-on;’ on the device tree :

QSMP U-Boot > fdt print /firmware/scmi/protocol@17/regulators/regulator@0
regulator@0 {
regulator-always-on;
reg = <0x00000000>;
regulator-name = "vddio1";
regulator-min-microvolt = <0x00325aa0>;
regulator-max-microvolt = <0x00325aa0>;
phandle = <0x0000004e>;
};

It has worked only once. 

Also, I have some GPIOs and UARTs on PD/PB pin and powered by Vddio3-4.

After the boot I get :

[   35.805443] vddio3: disabling
[ 35.805521] vddio4: disabling


Why does the used port is shown as unused and unpowered ?

I have also added ‘regulator-always-on;’ for vddio3-4 in the device tree, it doesn’t change anything.

PatrickF
ST Employee
July 29, 2026

I’m not SW expert, but Linux could ask the system for ‘disabling’ a regulator (e.g. no Linux running driver use the related supply), but OpTee (which manage the powers and clocks) has it owns rules defined in it’s DT (e.g. always-on).

For PE0-5, maybe dump the PWR_CR8.VDDIO1SV bit value using devmem2 for instance (if read is allowed from user space)

devmem2 0x5421001C word

But if no device is associated to any of VDDIO1 PE0-5 pins, it is maybe normal that OpTee (or Linux?)  does not set VDDIO1SV bit.
 

Regards.

In order to give better visibility on the answered topics, please click on 'Best Answer' on the reply which solved your issue or answered your question.Tip of the day: Try Sidekick STM32 AI agent