google/chromeos: Support AP watchdog flag from Chrome EC

After ChromiumOS CL:1293132 and CL:1295890, Chrome EC can store the flag
telling if the last reboot was triggered by AP watchdog for some boards
(e.g., Kukui).

This CL adds a new function google_chromeec_get_ap_watchdog_flag(),
which reads the AP watchdog flag from Chrome EC, and updates the tables
of reset causes and reset flags.

A new Kconfig option CHROMEOS_USE_EC_WATCHDOG_FLAG is added for
elog_handle_watchdog_tombstone() to determine if watchdog reset was
triggered by the AP watchdog flag from EC instead of the tombstone in
AP.

BUG=b:109900671,b:118654976
BRANCH=none
TEST=test with https://review.coreboot.org/c/coreboot/+/31843

Change-Id: I7a970666a8c6da32ac1c6af8280e808fe7fc106d
Signed-off-by: You-Cheng Syu <youcheng@google.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/31834
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Hung-Te Lin <hungte@chromium.org>
diff --git a/src/ec/google/chromeec/ec.c b/src/ec/google/chromeec/ec.c
index c34faaa..1b0f7ee 100644
--- a/src/ec/google/chromeec/ec.c
+++ b/src/ec/google/chromeec/ec.c
@@ -704,6 +704,29 @@
 	return cec_cmd.cmd_code;
 }
 
+static uint16_t google_chromeec_get_uptime_info(
+	struct ec_response_uptime_info *rsp)
+{
+	struct chromeec_command cmd = {
+		.cmd_code = EC_CMD_GET_UPTIME_INFO,
+		.cmd_version = 0,
+		.cmd_data_in = NULL,
+		.cmd_size_in = 0,
+		.cmd_data_out = rsp,
+		.cmd_size_out = sizeof(*rsp),
+		.cmd_dev_index = 0,
+	};
+	google_chromeec_command(&cmd);
+	return cmd.cmd_code;
+}
+
+bool google_chromeec_get_ap_watchdog_flag(void)
+{
+	struct ec_response_uptime_info rsp;
+	return (!google_chromeec_get_uptime_info(&rsp) &&
+		(rsp.ec_reset_flags & EC_RESET_FLAG_AP_WATCHDOG));
+}
+
 int google_chromeec_i2c_xfer(uint8_t chip, uint8_t addr, int alen,
 			     uint8_t *buffer, int len, int is_read)
 {
@@ -944,6 +967,7 @@
 		"reset: debug warm reboot",
 		"reset: at AP's request",
 		"reset: during EC initialization",
+		"reset: AP watchdog",
 	};
 
 	static const size_t shutdown_cause_begin = 1 << 15;
@@ -997,22 +1021,13 @@
 		"usb-resume",
 		"rdd",
 		"rbox",
-		"security"
+		"security",
+		"ap-watchdog",
 	};
 	struct ec_response_uptime_info cmd_resp;
 	int i, flag, flag_count;
 
-	struct chromeec_command get_uptime_cmd = {
-		.cmd_code = EC_CMD_GET_UPTIME_INFO,
-		.cmd_version = 0,
-		.cmd_data_in = NULL,
-		.cmd_size_in = 0,
-		.cmd_data_out = &cmd_resp,
-		.cmd_size_out = sizeof(cmd_resp),
-		.cmd_dev_index = 0,
-	};
-	google_chromeec_command(&get_uptime_cmd);
-	if (get_uptime_cmd.cmd_code) {
+	if (google_chromeec_get_uptime_info(&cmd_resp)) {
 		/*
 		 * Deliberately say nothing for EC's that don't support this
 		 * command
diff --git a/src/ec/google/chromeec/ec.h b/src/ec/google/chromeec/ec.h
index d7fe733..019f9c1 100644
--- a/src/ec/google/chromeec/ec.h
+++ b/src/ec/google/chromeec/ec.h
@@ -64,6 +64,7 @@
 void google_chromeec_post(u8 postcode);
 int google_chromeec_vbnv_context(int is_read, uint8_t *data, int len);
 uint8_t google_chromeec_get_switches(void);
+bool google_chromeec_get_ap_watchdog_flag(void);
 
 /* Temporary secure storage commands */
 int google_chromeec_vstore_supported(void);
diff --git a/src/vendorcode/google/chromeos/Kconfig b/src/vendorcode/google/chromeos/Kconfig
index 26ee31e..2ff7ec7 100644
--- a/src/vendorcode/google/chromeos/Kconfig
+++ b/src/vendorcode/google/chromeos/Kconfig
@@ -89,5 +89,11 @@
 	  on normal boot as well as resume and coreboot is only involved
 	  in the resume piece w.r.t. the platform hierarchy.
 
+config CHROMEOS_USE_EC_WATCHDOG_FLAG
+	bool
+	default n
+	help
+	  Use the AP watchdog flag stored in EC.
+
 endif # CHROMEOS
 endmenu
diff --git a/src/vendorcode/google/chromeos/watchdog.c b/src/vendorcode/google/chromeos/watchdog.c
index 4557251..2b2959f 100644
--- a/src/vendorcode/google/chromeos/watchdog.c
+++ b/src/vendorcode/google/chromeos/watchdog.c
@@ -17,6 +17,7 @@
 #include <assert.h>
 #include <bootstate.h>
 #include <console/console.h>
+#include <ec/google/chromeec/ec.h>
 #include <elog.h>
 #include <reset.h>
 #include <symbols.h>
@@ -30,13 +31,19 @@
 
 static void elog_handle_watchdog_tombstone(void *unused)
 {
-	if (!REGION_SIZE(watchdog_tombstone))
-		return;
+	bool flag = false;
 
-	if (read32(_watchdog_tombstone) == WATCHDOG_TOMBSTONE_MAGIC)
+	if (CONFIG(CHROMEOS_USE_EC_WATCHDOG_FLAG))
+		flag |= google_chromeec_get_ap_watchdog_flag();
+
+	if (REGION_SIZE(watchdog_tombstone)) {
+		flag |= (read32(_watchdog_tombstone) ==
+			 WATCHDOG_TOMBSTONE_MAGIC);
+		write32(_watchdog_tombstone, 0);
+	}
+
+	if (flag)
 		elog_add_event(ELOG_TYPE_ASYNC_HW_TIMER_EXPIRED);
-
-	write32(_watchdog_tombstone, 0);
 }
 
 BOOT_STATE_INIT_ENTRY(BS_POST_DEVICE, BS_ON_ENTRY,