diff options
-rw-r--r-- | board/kukui/board.c | 23 | ||||
-rw-r--r-- | board/kukui/gpio.inc | 6 | ||||
-rw-r--r-- | include/chipset.h | 13 | ||||
-rw-r--r-- | power/mt8183.c | 25 | ||||
-rw-r--r-- | util/ectool.c | 1 |
5 files changed, 41 insertions, 27 deletions
diff --git a/board/kukui/board.c b/board/kukui/board.c index a14b4a6a76..15acdee112 100644 --- a/board/kukui/board.c +++ b/board/kukui/board.c @@ -54,24 +54,6 @@ static void tcpc_alert_event(enum gpio_signal signal) #endif } -static void warm_reset_request_interrupt(enum gpio_signal signal) -{ - CPRINTS("AP wants warm reset"); - chipset_reset(CHIPSET_RESET_AP_REQ); -} - -static void ap_watchdog_interrupt(enum gpio_signal signal) -{ - int level = gpio_get_level(GPIO_AP_EC_WATCHDOG_L); - - CPRINTS("AP watchdog level %d", level); - /* - * TODO(b:109900671): Handle AP watchdog, when necessary, for now, just - * mirror input to output. - */ - gpio_set_level(GPIO_PMIC_WATCHDOG_L, level); -} - #if BOARD_REV >= 1 static void hall_interrupt(enum gpio_signal signal) { @@ -230,11 +212,6 @@ static void board_init(void) /* Enable charger interrupts */ gpio_enable_interrupt(GPIO_CHARGER_INT_ODL); - /* Enable reboot / shutdown / sleep control inputs from AP */ - gpio_enable_interrupt(GPIO_WARM_RESET_REQ); - gpio_enable_interrupt(GPIO_AP_EC_WATCHDOG_L); - gpio_enable_interrupt(GPIO_AP_IN_SLEEP_L); - #ifdef SECTION_IS_RW /* Enable interrupts from BMI160 sensor. */ gpio_enable_interrupt(GPIO_ACCEL_INT_ODL); diff --git a/board/kukui/gpio.inc b/board/kukui/gpio.inc index 362f51f862..53a96f95c8 100644 --- a/board/kukui/gpio.inc +++ b/board/kukui/gpio.inc @@ -25,9 +25,9 @@ GPIO_INT(AP_IN_SLEEP_L, PIN(C, 12), GPIO_INT_BOTH | GPIO_PULL_DOWN, GPIO_INT(PMIC_EC_RESETB, PIN(B, 7), GPIO_INT_BOTH | GPIO_PULL_DOWN, power_signal_interrupt) GPIO_INT(WARM_RESET_REQ, PIN(A, 3), GPIO_INT_RISING | GPIO_PULL_DOWN, - warm_reset_request_interrupt) -GPIO_INT(AP_EC_WATCHDOG_L, PIN(C, 2), GPIO_INT_BOTH, - ap_watchdog_interrupt) + chipset_reset_request_interrupt) +GPIO_INT(AP_EC_WATCHDOG_L, PIN(C, 2), GPIO_INT_FALLING, + chipset_watchdog_interrupt) GPIO_INT_RW(ACCEL_INT_ODL, PIN(A, 4), GPIO_INT_FALLING | GPIO_SEL_1P8V | GPIO_PULL_UP, bmi160_interrupt) diff --git a/include/chipset.h b/include/chipset.h index fae0d4e3da..b4b630f032 100644 --- a/include/chipset.h +++ b/include/chipset.h @@ -68,6 +68,8 @@ enum chipset_reset_reason { CHIPSET_RESET_AP_REQ, /* Reset as side-effect of startup sequence */ CHIPSET_RESET_INIT, + /* EC detected an AP watchdog event. */ + CHIPSET_RESET_AP_WATCHDOG, CHIPSET_RESET_COUNT, }; @@ -183,6 +185,7 @@ static inline void power_interrupt(enum gpio_signal signal) { } static inline void chipset_handle_espi_reset_assert(void) { } static inline void chipset_handle_reboot(void) { } static inline void chipset_reset_request_interrupt(enum gpio_signal signal) { } +static inline void chipset_watchdog_interrupt(enum gpio_signal signal) { } static inline void chipset_power_signal_interrupt(enum gpio_signal signal) { } #endif /* !HAS_TASK_CHIPSET */ @@ -202,10 +205,18 @@ void chipset_handle_reboot(void); /** * GPIO interrupt handler of reset request from AP. * - * It is used in SDM845 chipset power sequence. + * It is used in SDM845/MT8183 chipset power sequence. */ void chipset_reset_request_interrupt(enum gpio_signal signal); +/** + * GPIO interrupt handler of watchdog from AP. + * + * It is used in MT8183 chipset, where it must be setup to trigger on falling + * edge only. + */ +void chipset_watchdog_interrupt(enum gpio_signal signal); + #ifdef CONFIG_CMD_AP_RESET_LOG /** diff --git a/power/mt8183.c b/power/mt8183.c index 48886a488c..631f2f3c7f 100644 --- a/power/mt8183.c +++ b/power/mt8183.c @@ -99,6 +99,25 @@ static const struct power_seq_op s3s5_power_seq[] = { static int forcing_shutdown; +void chipset_reset_request_interrupt(enum gpio_signal signal) +{ + chipset_reset(CHIPSET_RESET_AP_REQ); +} + +/* + * Triggers on falling edge of AP watchdog line only. The falling edge can + * happen in these 2 cases: + * - AP asserts watchdog while the AP is on: this is a real AP-initiated reset. + * - EC asserted GPIO_AP_SYS_RST_L, so the AP is in reset and AP watchdog falls + * as well. This is _not_ a watchdog reset. We mask these cases by disabling + * the interrupt just before shutting down the AP, and re-enabling it just + * after starting the AP. + */ +void chipset_watchdog_interrupt(enum gpio_signal signal) +{ + chipset_reset(CHIPSET_RESET_AP_WATCHDOG); +} + void chipset_force_shutdown(enum chipset_shutdown_reason reason) { CPRINTS("%s(%d)", __func__, reason); @@ -134,6 +153,10 @@ void chipset_reset(enum chipset_reset_reason reason) enum power_state power_chipset_init(void) { + /* Enable reboot / watchdog / sleep control inputs from AP */ + gpio_enable_interrupt(GPIO_WARM_RESET_REQ); + gpio_enable_interrupt(GPIO_AP_IN_SLEEP_L); + if (system_jumped_to_this_image()) { if ((power_get_signals() & IN_ALL_S0) == IN_ALL_S0) { disable_sleep(SLEEP_MASK_AP_RUN); @@ -272,6 +295,7 @@ enum power_state power_handle_state(enum power_state state) booted = 1; /* Enable S3 power supplies, release AP reset. */ power_seq_run(s5s3_power_seq, ARRAY_SIZE(s5s3_power_seq)); + gpio_enable_interrupt(GPIO_AP_EC_WATCHDOG_L); /* Call hooks now that rails are up */ hook_notify(HOOK_CHIPSET_STARTUP); @@ -332,6 +356,7 @@ enum power_state power_handle_state(enum power_state state) /* Call hooks before we remove power rails */ hook_notify(HOOK_CHIPSET_SHUTDOWN); + gpio_disable_interrupt(GPIO_AP_EC_WATCHDOG_L); power_seq_run(s3s5_power_seq, ARRAY_SIZE(s3s5_power_seq)); /* Start shutting down */ diff --git a/util/ectool.c b/util/ectool.c index a053171ac5..bd7725131e 100644 --- a/util/ectool.c +++ b/util/ectool.c @@ -718,6 +718,7 @@ static const char *reset_cause_to_str(uint16_t cause) "reset: debug warm reboot", "reset: at AP's request", "reset: during EC initialization", + "reset: AP watchdog", }; BUILD_ASSERT(ARRAY_SIZE(reset_causes) == CHIPSET_RESET_COUNT); |