summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--board/kukui/board.c23
-rw-r--r--board/kukui/gpio.inc6
-rw-r--r--include/chipset.h13
-rw-r--r--power/mt8183.c25
-rw-r--r--util/ectool.c1
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);