ec/google/wilco: set diagnostic LEDs on boot failure

On Wilco devices, if any of the coreboot stages fails with a fatal
error, set the diagnostic LEDs with the Wilco EC.  The last saved
post code is used to determine the error code sent to the EC.

BUG=b:124401932
BRANCH=sarien
TEST=build coreboot for sarien and arcada platforms
TEST=Remove DIMM module, confirm diagnostic LED pattern for memory
failure (2 amber, 4 white).
TEST=Forced a fatal error in both bootblock and verstage to confirm
diagnostic LEDs during these stages. This works on cold-boots only. Bug
b:132622888 tracks the mailbox failures on warm boots.

Change-Id: If865ab8203f89e499130f4677fec166b40d80174
Signed-off-by: Keith Short <keithshort@chromium.org>
Signed-off-by: Duncan Laurie <dlaurie@google.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/32777
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Jett Rink <jettrink@chromium.org>
Reviewed-by: Duncan Laurie <dlaurie@chromium.org>
Reviewed-by: Furquan Shaikh <furquan@google.com>
diff --git a/src/ec/google/wilco/commands.c b/src/ec/google/wilco/commands.c
index a97a28e..9d4170f 100644
--- a/src/ec/google/wilco/commands.c
+++ b/src/ec/google/wilco/commands.c
@@ -182,8 +182,45 @@
 	return !!ec_read(EC_RAM_SIGNED_FW);
 }
 
-int wilco_ec_err_code(enum ec_err_code err_code)
+struct err_code_entry {
+	uint8_t post_code;
+	enum ec_err_code ec_err;
+};
+
+/*
+ * Any post codes not listed in the post_code_err_map[] use default.
+ */
+static const enum ec_err_code default_ec_err = DLED_ROM;
+static const struct err_code_entry post_code_err_map[] = {
+	{ .post_code = POST_RAM_FAILURE, .ec_err = DLED_MEMORY, },
+	{ .post_code = POST_VIDEO_FAILURE, .ec_err = DLED_PANEL, },
+};
+
+/* Records the most recent post code during boot */
+static uint8_t wilco_ec_saved_post_code;
+
+void wilco_ec_save_post_code(uint8_t post_code)
 {
-	return wilco_ec_mailbox(WILCO_EC_MSG_DEFAULT, KB_ERR_CODE,
-				&err_code, 1, NULL, 0);
+	wilco_ec_saved_post_code = post_code;
+}
+
+/* Send error code to the EC based on last saved post code */
+void die_notify(void)
+{
+	size_t i;
+	enum ec_err_code err_code = default_ec_err;
+
+	for (i = 0; i < ARRAY_SIZE(post_code_err_map); i++) {
+		if (post_code_err_map[i].post_code ==
+		    wilco_ec_saved_post_code) {
+			err_code = post_code_err_map[i].ec_err;
+			break;
+		}
+	}
+
+	printk(BIOS_EMERG, "Fatal error: post_code 0x%02x, EC err 0x%02x\n",
+	       wilco_ec_saved_post_code, err_code);
+
+	wilco_ec_mailbox(WILCO_EC_MSG_DEFAULT, KB_ERR_CODE,
+			 &err_code, 1, NULL, 0);
 }
diff --git a/src/ec/google/wilco/commands.h b/src/ec/google/wilco/commands.h
index fafb7fd..9b7f2e5 100644
--- a/src/ec/google/wilco/commands.h
+++ b/src/ec/google/wilco/commands.h
@@ -319,16 +319,14 @@
 int wilco_ec_signed_fw(void);
 
 /**
- * wilco_ec_err_code
+ * wilco_ec_save_post_code
  *
- * Send an error code to the EC to indicate a failed boot.  The EC flashes the
- * platform LED amber and white to provide user indication of the failure type.
+ * Save this post code as the most recent progress step.  If the boot fails
+ * and calls die_notify() this post code will be used to send an error code
+ * to the EC indicating the failure.
  *
- * @err_code:		Error code to send to the EC
- *
- * Returns 0 if EC command was successful
- * Returns -1 if EC command failed
+ * @post_code: Post code to save
  */
-int wilco_ec_err_code(enum ec_err_code err_code);
+void wilco_ec_save_post_code(uint8_t post_code);
 
 #endif /* EC_GOOGLE_WILCO_COMMANDS_H */