From 3c5d455f202476d129e4de7554689c31c9356807 Mon Sep 17 00:00:00 2001 From: Aren Moynihan Date: Wed, 11 Sep 2024 18:51:45 -0400 Subject: [PATCH] gpio: toggle the RESET_N pin before booting the modem to ensure it is actually off --- src/gpio.c | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/src/gpio.c b/src/gpio.c index e4486fd..af61d64 100644 --- a/src/gpio.c +++ b/src/gpio.c @@ -74,11 +74,36 @@ int gpio_line_set_value(struct EG25Manager *manager, int line, enum gpiod_line_v int gpio_sequence_poweron(struct EG25Manager *manager) { + /* + * Force the modem to poweroff using the RESET_N pin before attempting to + * boot in case the it got into a bad state. + * + * If the modem was on, this will cause it to start booting, so press the + * power button while in reset to avoid a (probably only theoretical) race + * condition where it starts booting after reset, and then powers off from + * the power key. + */ + gpio_line_set_value(manager, GPIO_OUT_RESET, GPIOD_LINE_VALUE_ACTIVE); gpio_line_set_value(manager, GPIO_OUT_PWRKEY, GPIOD_LINE_VALUE_ACTIVE); + + /* + * The datasheet says to pull the pin low for between 150 and 460 ms. usleep + * should always sleep for at least the specified amount of time, so use + * 200ms because it's closer to the bottom of that range. + */ + usleep(200000); + + gpio_line_set_value(manager, GPIO_OUT_RESET, GPIOD_LINE_VALUE_INACTIVE); + + /* + * The modem has finished it's reset, now we wait to allow it a chance to + * react to the power key + */ sleep(1); + gpio_line_set_value(manager, GPIO_OUT_PWRKEY, GPIOD_LINE_VALUE_INACTIVE); - g_message("Executed power-on/off sequence"); + g_message("Executed power-on sequence"); return 0; } @@ -86,7 +111,10 @@ int gpio_sequence_poweron(struct EG25Manager *manager) int gpio_sequence_shutdown(struct EG25Manager *manager) { gpio_line_set_value(manager, GPIO_OUT_DISABLE, GPIOD_LINE_VALUE_ACTIVE); - gpio_sequence_poweron(manager); + + gpio_line_set_value(manager, GPIO_OUT_PWRKEY, GPIOD_LINE_VALUE_ACTIVE); + sleep(1); + gpio_line_set_value(manager, GPIO_OUT_PWRKEY, GPIOD_LINE_VALUE_INACTIVE); g_message("Executed power-off sequence");