2025-10-15 5:48 AM
Hi,
we are developing a custom board based on the STM32MP157C. We would want to use several GPIOs for buttons. We have most of them working, but a couple GPIO pins do not yield input events to the Linux kernel.
The problematic pins are PC1, PC2, and PH7.
In U-Boot, I can read all these pins and they reflect the state of the button. Below is what happens reading the pin before pressing the corresponding button, while pressing it, and after releasing the button. So the button is connected to the CPU pins and is active high:
QSMP U-Boot > gpio input gpioc1
gpio: pin gpioc1 (gpio 33) value is 0
QSMP U-Boot > gpio input gpioc1
gpio: pin gpioc1 (gpio 33) value is 1
QSMP U-Boot > gpio input gpioc1
gpio: pin gpioc1 (gpio 33) value is 0
QSMP U-Boot > gpio input gpioc2
gpio: pin gpioc2 (gpio 34) value is 0
QSMP U-Boot > gpio input gpioc2
gpio: pin gpioc2 (gpio 34) value is 1
QSMP U-Boot > gpio input gpioc2
gpio: pin gpioc2 (gpio 34) value is 0
QSMP U-Boot > gpio input gpioh7
gpio: pin gpioh7 (gpio 119) value is 0
QSMP U-Boot > gpio input gpioh7
gpio: pin gpioh7 (gpio 119) value is 1
QSMP U-Boot > gpio input gpioh7
gpio: pin gpioh7 (gpio 119) value is 0
Proceeding to boot to Linux, the other keys produce input events but the buttons on PC1, PC2 and PH7 do not.
The pins are consumed by gpio-keys-polled:
# gpioinfo |grep Key
line 1: "PA1" input consumer="Key DOWN"
line 2: "PA2" input consumer="Key LEFT"
line 7: "PA7" input consumer="Key RIGHT"
line 9: "PA9" input consumer="Key UP"
line 15: "PA15" input consumer="Key PLUS"
line 0: "PB0" input consumer="Key START"
line 8: "PB8" input consumer="Key MENU"
line 1: "PC1" input consumer="Key CENTER"
line 2: "PC2" input consumer="Key STOP"
line 4: "PG4" input consumer="Key MINUS"
line 7: "PH7" input consumer="Key MODE"
Devicetree config is below. Using gpio-keys-polled as we have keys on same-numbered pins on different ports (e.g. PA1 and PC1) and apparently EXTI can be triggered on only one pin of the same number.
It seems as if the pins PC1, PC2 and PH7 do not get pinmuxed to GPIO function; while the others "happen" to have a proper pinmux in place. Of course I would like to explicitly define the pinmuxing for these pins. If I add a pinhandle to the gpio-keys block, at runtime the gpio-keys driver fails to allocate the first pin (and gives up) because pinctrl says they are already allocated. The pin it fails on is the first listed; it hops to the next if I omit PA1 from keys_pins. I understand this happens due to the pinctrl mechanism automatically allocating the pins as the driver is being initialized, and then gpio-keys tries to grab the pins again via the gpios= references. But relying only on the gpios allocation does not seem to mux the pins properly.
gpio-keys {
compatible = "gpio-keys-polled";
poll-interval = <50>;
pinctrl-names = "default";
pinctrl-0 = <&keys_pins>;
key-down {
label = "Key DOWN";
gpios = <&gpioa 1 (GPIO_ACTIVE_HIGH)>;
linux,code = <KEY_DOWN>;
linux,input-type = <EV_KEY>;
};
key-up {
label = "Key UP";
gpios = <&gpioa 9 (GPIO_ACTIVE_HIGH)>;
linux,code = <KEY_UP>;
linux,input-type = <EV_KEY>;
};
key-left {
label = "Key LEFT";
gpios = <&gpioa 2 (GPIO_ACTIVE_HIGH)>;
linux,code = <KEY_LEFT>;
linux,input-type = <EV_KEY>;
};
key-right {
label = "Key RIGHT";
gpios = <&gpioa 7 (GPIO_ACTIVE_HIGH)>;
linux,code = <KEY_RIGHT>;
linux,input-type = <EV_KEY>;
};
key-center {
label = "Key CENTER";
gpios = <&gpioc 1 (GPIO_ACTIVE_HIGH)>;
linux,code = <KEY_ENTER>;
linux,input-type = <EV_KEY>;
};
key-menu {
label = "Key MENU";
gpios = <&gpiob 8 (GPIO_ACTIVE_HIGH)>;
linux,code = <KEY_MENU>;
linux,input-type = <EV_KEY>;
};
key-mode {
label = "Key MODE";
gpios = <&gpioh 7 (GPIO_ACTIVE_HIGH)>;
linux,code = <KEY_B>;
linux,input-type = <EV_KEY>;
};
key-start {
label = "Key START";
gpios = <&gpiob 0 (GPIO_ACTIVE_HIGH)>;
linux,code = <KEY_PLAY>;
linux,input-type = <EV_KEY>;
};
key-stop {
label = "Key STOP";
gpios = <&gpioc 2 (GPIO_ACTIVE_HIGH)>;
linux,code = <KEY_A>;
linux,input-type = <EV_KEY>;
};
key-plus {
label = "Key PLUS";
gpios = <&gpioa 15 (GPIO_ACTIVE_HIGH)>;
linux,code = <KEY_KPPLUS>;
linux,input-type = <EV_KEY>;
};
key-minus {
label = "Key MINUS";
gpios = <&gpiog 4 (GPIO_ACTIVE_HIGH)>;
linux,code = <KEY_KPMINUS>;
linux,input-type = <EV_KEY>;
};
}:
# dmesg |grep stm32mp157-pinctrl
[ 0.748656] stm32mp157-pinctrl soc:pinctrl@50002000: pin PA1 already requested by gpio-keys; cannot claim for GPIOA:1
[ 0.758003] stm32mp157-pinctrl soc:pinctrl@50002000: pin-1 (GPIOA:1) status -22
Moving the pinhandle to pinctrl itself makes the allocation problem even worse: the pinctrl mechanism tries to allocate the pins before the GPIO banks are added at runtime:
&pinctrl {
pinctrl-names = "default";
pinctrl-0 = <&keys_pins>;
keys_pins: keys-pins {
pins {
pinmux = <STM32_PINMUX('A', 1, GPIO)>, /* down */
<STM32_PINMUX('A', 9, GPIO)>, /* up */
<STM32_PINMUX('A', 2, GPIO)>, /* left */
<STM32_PINMUX('A', 7, GPIO)>, /* right */
<STM32_PINMUX('C', 1, GPIO)>, /* center */
<STM32_PINMUX('B', 8, GPIO)>, /* menu */
<STM32_PINMUX('H', 7, GPIO)>, /* mode */
<STM32_PINMUX('B', 0, GPIO)>, /* start */
<STM32_PINMUX('C', 2, GPIO)>, /* stop */
<STM32_PINMUX('A', 15, GPIO)>, /* plus */
<STM32_PINMUX('G', 4, GPIO)>, /* minus */
<STM32_PINMUX('E', 11, GPIO)>, /* cover switch */
<STM32_PINMUX('I', 4, GPIO)>, /* conn1 detect */
<STM32_PINMUX('I', 5, GPIO)>, /* conn1 type */
<STM32_PINMUX('I', 6, GPIO)>, /* conn2 detect */
<STM32_PINMUX('D', 8, GPIO)>; /* conn2 type */
bias-disable;
};
};
};
# dmesg |grep stm32mp157-pinctrl
[ 0.338839] stm32mp157-pinctrl soc:pinctrl@50002000: No gpio range defined.
[ 0.338863] stm32mp157-pinctrl soc:pinctrl@50002000: request() failed for pin 1
[ 0.338877] stm32mp157-pinctrl soc:pinctrl@50002000: pin-1 (soc:pinctrl@50002000) status -22
[ 0.338893] stm32mp157-pinctrl soc:pinctrl@50002000: could not request pin 1 (PA1) from group PA1 on device soc:pinctrl@50002000
[ 0.338908] stm32mp157-pinctrl soc:pinctrl@50002000: Error applying setting, reverse things back
[ 0.338919] stm32mp157-pinctrl soc:pinctrl@50002000: failed to select default state
[ 0.340470] stm32mp157-pinctrl soc:pinctrl@50002000: GPIOA bank added
[ 0.341447] stm32mp157-pinctrl soc:pinctrl@50002000: GPIOB bank added
[ 0.342275] stm32mp157-pinctrl soc:pinctrl@50002000: GPIOC bank added
[ 0.343267] stm32mp157-pinctrl soc:pinctrl@50002000: GPIOD bank added
[ 0.344122] stm32mp157-pinctrl soc:pinctrl@50002000: GPIOE bank added
[ 0.345113] stm32mp157-pinctrl soc:pinctrl@50002000: GPIOF bank added
[ 0.346078] stm32mp157-pinctrl soc:pinctrl@50002000: GPIOG bank added
[ 0.347183] stm32mp157-pinctrl soc:pinctrl@50002000: GPIOH bank added
[ 0.348209] stm32mp157-pinctrl soc:pinctrl@50002000: GPIOI bank added
[ 0.348280] stm32mp157-pinctrl soc:pinctrl@50002000: Pinctrl STM32 initialized
[ 0.351320] stm32mp157-pinctrl soc:pinctrl@54004000: GPIOZ bank added
[ 0.351352] stm32mp157-pinctrl soc:pinctrl@54004000: Pinctrl STM32 initialized
So how should we define pinmuxing for gpio-keys pins?
We are using Linux 6.1 on Yocto mickledore. (Upgrade is possible if it fixes this problem.)
2025-10-15 6:11 AM
Hi @TOK
not really expert on this, try to help...
Behind the device tree settings, even if using "gpio-keys-polled", there is maybe some usage of EXTI, then you have some limitations due to HW.
source: Reference Manual and https://wiki.st.com/stm32mpu/wiki/EXTI_internal_peripheral#Peripheral_overview
This sound the case as you mention issues with PC1, PC2, and PH7, while you already have declared PA1, PA2 and PA7.
Maybe look if EXTI is somewhere else listed in device tree.
https://wiki.st.com/stm32mpu/wiki/Interrupt_overview
Otherwise, the way you declare your buttons are not the right one (i.e. not supported like this) or there might be some unseen bugs.
Regards
2025-10-15 7:24 AM
Thanks @PatrickF -- there is something to your suggestion. Simply commenting out the keys on PA1, PA2, and PA7 I do then get input events on the buttons at PC1, PC2 and PH7. So there seems to be some kind of resource congestion.