Skip to content

Commit d9af269

Browse files
committed
driver: gpio: Add sleep delay in gpio isr
When EC wakes by GPIO, it may fall back to SUSPEND_TO_IDLE before the host or peripherals have a chance to take further action. Add a lightweight delay-sleep mechanism to keep system awake for as short period after a GPIO wake event. Signed-off-by: Elmo Lan <[email protected]>
1 parent c102a8e commit d9af269

File tree

1 file changed

+35
-0
lines changed

1 file changed

+35
-0
lines changed

drivers/gpio/gpio_rts5912.c

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515
#include "zephyr/drivers/gpio/gpio_utils.h"
1616
#include <zephyr/logging/log.h>
1717
#include <zephyr/dt-bindings/gpio/realtek-gpio.h>
18+
#include <zephyr/pm/pm.h>
19+
#include <zephyr/pm/policy.h>
20+
#include <zephyr/sys/atomic.h>
1821

1922
#include <reg/reg_gpio.h>
2023

@@ -33,6 +36,22 @@ struct gpio_rts5912_data {
3336
sys_slist_t callbacks;
3437
};
3538

39+
#if defined(CONFIG_PM)
40+
#define GPIO_EXPIRED_TIMEOUT_MS 1000
41+
static struct k_work_delayable gpio_wake_delay_work;
42+
static atomic_t gpio_wake_hold; /* 0: no hold, 1: holding */
43+
static atomic_t gpio_wake_init_once; /* 0: not inited, 1: inited */
44+
45+
static void gpio_wake_delay_work_handler(struct k_work *work)
46+
{
47+
ARG_UNUSED(work);
48+
49+
if (atomic_cas(&gpio_wake_hold, 1, 0)) {
50+
pm_policy_state_lock_put(PM_STATE_SUSPEND_TO_IDLE, PM_ALL_SUBSTATES);
51+
}
52+
}
53+
#endif /* CONFIG_PM */
54+
3655
static int pin_is_valid(const struct gpio_rts5912_config *config, gpio_pin_t pin)
3756
{
3857
if (pin >= config->num_pins) {
@@ -455,6 +474,14 @@ static void gpio_rts5912_isr(const void *arg)
455474
if (gcr[pin] & GPIO_GCR_INTSTS_Msk) {
456475
gcr[pin] |= GPIO_GCR_INTSTS_Msk;
457476

477+
#if defined(CONFIG_PM)
478+
if (atomic_cas(&gpio_wake_hold, 0, 1)) {
479+
pm_policy_state_lock_get(PM_STATE_SUSPEND_TO_IDLE, PM_ALL_SUBSTATES);
480+
}
481+
k_work_reschedule(&gpio_wake_delay_work,
482+
K_MSEC(GPIO_EXPIRED_TIMEOUT_MS));
483+
#endif
484+
458485
gpio_fire_callbacks(&data->callbacks, port, BIT(pin));
459486
}
460487
irq_unlock(key);
@@ -567,6 +594,14 @@ static DEVICE_API(gpio, gpio_rts5912_driver_api) = {
567594
{ \
568595
if (!(DT_INST_IRQ_HAS_CELL(id, irq))) { \
569596
return 0; \
597+
} \
598+
\
599+
if (IS_ENABLED(CONFIG_PM)) { \
600+
if (atomic_cas(&gpio_wake_init_once, 0, 1)) { \
601+
k_work_init_delayable(&gpio_wake_delay_work, \
602+
gpio_wake_delay_work_handler); \
603+
atomic_clear(&gpio_wake_hold); \
604+
} \
570605
} \
571606
\
572607
RTS5912_GPIO_DTNAMIC_IRQ(id) \

0 commit comments

Comments
 (0)