Skip to contentSkip to conversation

Dumping GPIOs state during suspend state

PATCH In review Mintu Patel 2 participants 2 messages Dec 6, 2025 – Dec 7, 2025

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 Dumping GPIOs state during suspend state

It is difficult to find out which GPIOs are going high during suspend without manual probing with multimeters or oscilloscopes. In order to save the power especifically for battery operated devices, It becomes must to pull GPIOs low during suspend.

As of now there is no way to trace which GPIOs are high during suspend without manual probing with multimeters or oscilloscopes. This patch would help the developer to find the GPIOs are high during suspend state without struggling with hardware devices.

The patch would print the below logs:

[  244.029392] GPIO Chip : 3000000.pinctrl
[  244.029394] GPIO   Suspend state
[  244.029404] 3      1
[  244.029418] 17      1
[  244.029424] 21      1
[  244.029431] 30      1
[  244.029436] 32      1
[  244.029440] 33      1
[  244.029444] 34      1
[  244.029447] 35      1
[  244.029453] 41      1
[  244.029462] 51      1
[  244.029470] 57      1
[  244.029492] 90      1
[  244.029496] 91      1
[  244.029515] 114      1
[  244.029519] 115      1
[  244.029523] 117      1

Based on the above logs, GPIOs 3, 17, etc are high during suspend state. Thus particular driver/submodule can be modified for configuring the GPIOs accordingly for suspend and resume states.

---
 drivers/gpio/gpiolib.c | 36 ++++++++++++++++++++++++++++++++++++
 kernel/power/suspend.c |  8 ++++++++
 2 files changed, 44 insertions(+)
drivers/gpio/gpiolib.c +36 -0
index 94903fc1c145..65a8d2150d90 100644
@@ -51,6 +51,10 @@
 /* Device and char device-related information */
 static DEFINE_IDA(gpio_ida);
 static dev_t gpio_devt;
+#ifdef CONFIG_DEBUG_FS
+void gpio_state_fetch_at_suspend(void);
+DEFINE_SPINLOCK(gpio_lock);
+#endif
 #define GPIO_DEV_MAX 256 /* 256 GPIO chip devices supported */
 
 static int gpio_bus_match(struct device *dev, struct device_driver *drv)
@@ -4702,6 +4706,38 @@ void gpiod_put_array(struct gpio_descs *descs)
 }
 EXPORT_SYMBOL_GPL(gpiod_put_array);
 
+#ifdef CONFIG_DEBUG_FS
+static void fetching_gpios_state_suspend(struct gpio_chip *chip) {
+
+	int gpio_num, value = 0;
+
+	pr_info("GPIO Chip : %s\n",chip->label);
+	pr_info("GPIO   Suspend state\n");
+	for (gpio_num = 0; gpio_num <chip->ngpio; gpio_num++ ) {
+		value = chip->get(chip, gpio_num);
+			if(value != 0) {
+			pr_info("%d      %d\n",gpio_num, value);
+			}
+	}
+	}
+
+void gpio_state_fetch_at_suspend() {
+
+	struct gpio_device *gdev;
+	unsigned long flags;
+
+	spin_lock_irqsave(&gpio_lock, flags);
+	list_for_each_entry(gdev, &gpio_devices, list)
+		if (gdev->chip != NULL) {
+			fetching_gpios_state_suspend( gdev->chip);
+		}
+
+	spin_unlock_irqrestore(&gpio_lock, flags);
+}
+
+EXPORT_SYMBOL_GPL(gpio_state_fetch_at_suspend);
+#endif
+
 static int gpio_stub_drv_probe(struct device *dev)
 {
 	/*
kernel/power/suspend.c +8 -0
index 09f8397bae15..e8d28206b053 100644
@@ -33,6 +33,10 @@
 
 #include "power.h"
 
+#ifdef CONFIG_DEBUG_FS
+extern void gpio_state_fetch_at_suspend(void);
+#endif
+
 const char * const pm_labels[] = {
 	[PM_SUSPEND_TO_IDLE] = "freeze",
 	[PM_SUSPEND_STANDBY] = "standby",
@@ -429,6 +433,10 @@ static int suspend_enter(suspend_state_t state, bool *wakeup)
 	if (suspend_test(TEST_PLATFORM))
 		goto Platform_wake;
 
+#ifdef CONFIG_DEBUG_FS
+	gpio_state_fetch_at_suspend();
+#endif
+
 	if (state == PM_SUSPEND_TO_IDLE) {
 		s2idle_loop();
 		goto Platform_wake;
Signature · 1 line
2.25.1
maintainer
#1 lore raw

Hi Mintu,

thanks for your patch!

Mainly I am awaiting the power state maintainers comment on this.

Quoted 1 line · Mintu Patel

It is difficult to find out which GPIOs are going high during suspend

Why is it not hard to find out which GPIOs are going low during suspend? I don't quite get this initial sentence, why does polarity even matter in this scenario?

Quoted 1 line

without manual probing with multimeters or oscilloscopes.

I understand this part, the system is suspended so it can't be inspected.

Quoted 2 lines

In order to save the power especifically for battery operated devices, It becomes must to pull GPIOs low during suspend.

This assumes a certain type of silicon architecture does it not.

IIUC it is important to pull GPIOs low *or* high in some cases, and what really needs to be avoided is pins being in tristate (high impedance, high-Z) becaus this can really cause leak current. Is this correct?

GPIO does have a notion about high
impedance state, because it has .set_config() that can actually put a pin into this state, while it is mostly handled by a back-end in pin control when available, so it is not something all GPIO drivers are semantically aware of.

Consider if you might want hooks like this in pin control rather than in GPIO, but maybe you want both.

Quoted 2 lines

As of now there is no way to trace which GPIOs are high during suspend without manual probing with multimeters or oscilloscopes.

This is already mentioned above.

Quoted 2 lines

This patch would help the developer to find the GPIOs are high during suspend state without struggling with hardware devices.

Fair enough, that is a reasonable usecase.

Quoted 21 lines

The patch would print the below logs:

[  244.029392] GPIO Chip : 3000000.pinctrl
[  244.029394] GPIO   Suspend state
[  244.029404] 3      1
[  244.029418] 17      1
[  244.029424] 21      1
[  244.029431] 30      1
[  244.029436] 32      1
[  244.029440] 33      1
[  244.029444] 34      1
[  244.029447] 35      1
[  244.029453] 41      1
[  244.029462] 51      1
[  244.029470] 57      1
[  244.029492] 90      1
[  244.029496] 91      1
[  244.029515] 114      1
[  244.029519] 115      1
[  244.029523] 117      1
Quoted 3 lines

Based on the above logs, GPIOs 3, 17, etc are high during suspend state. Thus particular driver/submodule can be modified for configuring the GPIOs accordingly for suspend and resume states.

I think I understand what you are trying to solve: you want to inspect what state the pins are not "during" suspend, but *at the moment suspend happens*, there is a difference there, and this is why some of the text is confusing me.

I would do this differently.

What I would do it:

- Go over all pins both when going into suspend *and* when going out of suspend. This creates a snapshot of the GPIO lines before and after suspend.

- Store not just pins that are high, because that is a pecularity of the system you are trying to debug here, store the state of *all* pins, because other users of this facility may very well want to know which pins are *low* at suspend and resume.

Quoted 1 line

+#ifdef CONFIG_DEBUG_FS

Why debug_fs? All this does is pr_info(), it doesn't need debugfs at all.

It could perhaps depend on CONFIG_DEBUG but I would suggest that you create a new Kconfig especially for this, like CONFIG_DEBUG_GPIO_STATES_AT_SUSPEND_RESUME OK maybe a bit long but you get my idea.

Quoted 1 line

+static void fetching_gpios_state_suspend(struct gpio_chip *chip) {

Use "fetch" (passive form) not "fetching" (active form).

But no, rename the function:
print_gpio_chip_states() because that is what it does.

drivers/gpio/gpiolib.c void gpiod_put_array(struct gpio_descs *descs) · line 4718

Quoted 8 lines
drivers/gpio/gpiolib.c +8 -0
+
+       int gpio_num, value = 0;
+
+       pr_info("GPIO Chip : %s\n",chip->label);
+       pr_info("GPIO   Suspend state\n");
+       for (gpio_num = 0; gpio_num <chip->ngpio; gpio_num++ ) {
+               value = chip->get(chip, gpio_num);
+                       if(value != 0) {

As mentioned I would do this for all states not just high pins.

drivers/gpio/gpiolib.c void gpiod_put_array(struct gpio_descs *descs) · line 4722

Quoted 4 lines
drivers/gpio/gpiolib.c +4 -0
+                       pr_info("%d      %d\n",gpio_num, value);
+                       }
+       }
+       }

This is just printing the state if rg

Quoted 1 line

+void gpio_state_fetch_at_suspend() {

I would call this
gpio_print_state_at_suspend()
because that is what it does.

kernel/power/suspend.c line 38

Quoted 3 lines
kernel/power/suspend.c +3 -0
+#ifdef CONFIG_DEBUG_FS
+extern void gpio_state_fetch_at_suspend(void);
+#endif

What about putting it in a new include
include/linux/gpio/system.h and include that?

kernel/power/suspend.c static int suspend_enter(suspend_state_t state, bool *wakeup) · line 436

Quoted 8 lines

const char * const pm_labels[] = {
[PM_SUSPEND_TO_IDLE] = "freeze",
[PM_SUSPEND_STANDBY] = "standby",

kernel/power/suspend.c +1 -0
@@ -429,6 +433,10 @@ static int suspend_enter(suspend_state_t state, bool *wakeup)
        if (suspend_test(TEST_PLATFORM))
                goto Platform_wake;
 
+#ifdef CONFIG_DEBUG_FS

This Kconfig needs to be changed as mentioned.

kernel/power/suspend.c static int suspend_enter(suspend_state_t state, bool *wakeup) · line 438

Quoted 2 lines
kernel/power/suspend.c +2 -0
+       gpio_state_fetch_at_suspend();
+#endif

As mentioned I would like this to be printed also on resume.

Yours,
Linus Walleij