[sherlock] 14.20230831.4.72 u-boot source

GitOrigin-RevId: 982bcd1283ee050f224f0ce8dd59d919cf638f07
Change-Id: I3a7dcb7d1076fbab289308e556dd7aae821d8cd0
Reviewed-on: https://turquoise-internal-review.googlesource.com/c/third_party/u-boot/+/801590
Reviewed-by: David Pursell <dpursell@google.com>
diff --git a/common/ta_helper.c b/common/ta_helper.c
index d1b0eb1..b4886f6 100644
--- a/common/ta_helper.c
+++ b/common/ta_helper.c
@@ -6,6 +6,9 @@
 
 #include <tee/ta_helper.h>
 
+/* Log TA client API error codes. */
+#define LOCAL_DEBUG 1
+
 #ifdef LOCAL_DEBUG
 #define TA_HELPER_DEBUG(...) fprintf(stderr, __VA_ARGS__)
 #else
diff --git a/drivers/usb/gadget/f_fastboot.c b/drivers/usb/gadget/f_fastboot.c
index ef8b348..d8bb0f0 100644
--- a/drivers/usb/gadget/f_fastboot.c
+++ b/drivers/usb/gadget/f_fastboot.c
@@ -672,6 +672,82 @@
 	return getvar_response_buffer;
 }
 
+static const char *get_emmc_wear_eol(const char *arg)
+{
+	struct mmc *mmc = find_mmc_device(CONFIG_FASTBOOT_FLASH_MMC_DEV);
+	if (!mmc || !mmc->ext_csd) {
+		return "no eMMC info";
+	}
+
+	const uint8_t value = mmc->ext_csd[EXT_CSD_PRE_EOL_INFO];
+
+	// Convert raw value into something human-readable.
+	// See eMMC spec v5.1 section 7.4.24.
+	const char *readable;
+	switch (value) {
+	case 0x00:
+		readable = "undefined";
+		break;
+	case 0x01:
+		readable = "normal";
+		break;
+	case 0x02:
+		readable = "warning";
+		break;
+	case 0x03:
+		readable = "urgent";
+		break;
+	default:
+		readable = "unknown";
+		break;
+	}
+
+	snprintf(getvar_response_buffer, GETVAR_RESPONSE_BUFFER_LEN, "%s (%d)",
+		 readable, value);
+	return getvar_response_buffer;
+}
+
+static const char *s_emmc_wear_level_list[] = { "A", "B", NULL };
+static const char *get_emmc_wear_level(const char *arg)
+{
+	if (!arg) {
+		return NULL;
+	}
+
+	struct mmc *mmc = find_mmc_device(CONFIG_FASTBOOT_FLASH_MMC_DEV);
+	if (!mmc || !mmc->ext_csd) {
+		return "no eMMC info";
+	}
+
+	uint value = 0;
+	if (strcmp(arg, "A") == 0) {
+		value = mmc->dev_lifetime_est_typ_a;
+	} else if (strcmp(arg, "B") == 0) {
+		value = mmc->dev_lifetime_est_typ_b;
+	} else {
+		return NULL;
+	}
+
+	// Convert raw value into something human-readable.
+	// See eMMC spec v5.1 sections 7.4.22 and 7.4.23.
+	char readable[16];
+	if (value == 0x00) {
+		strncpy(readable, "undefined", sizeof(readable));
+	} else if (value <= 0x0A) {
+		uint low = value * 10;
+		uint high = low + 10;
+		snprintf(readable, sizeof(readable), "%d%%-%d%%", low, high);
+	} else if (value == 0x0B) {
+		strncpy(readable, "EOL", sizeof(readable));
+	} else {
+		strncpy(readable, "unknown", sizeof(readable));
+	}
+
+	snprintf(getvar_response_buffer, GETVAR_RESPONSE_BUFFER_LEN, "%s (%d)",
+		 readable, value);
+	return getvar_response_buffer;
+}
+
 // Returns the board that the bootloader was compiled for.
 static const char *get_bootloader_board(const char *arg)
 {
@@ -1021,6 +1097,15 @@
 		.func = get_emmc_vendor,
 	},
 	{
+		.name = "emmc-wear-eol",
+		.func = get_emmc_wear_eol,
+	},
+	{
+		.name = "emmc-wear-level",
+		.func = get_emmc_wear_level,
+		.default_args = s_emmc_wear_level_list,
+	},
+	{
 		.name = "hw-revision",
 		.func = get_hw_revision,
 	},
diff --git a/include/mmc.h b/include/mmc.h
index 90a6803..1e3bc66 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -236,6 +236,7 @@
 #define EXT_CSD_HC_WP_GRP_SIZE		221	/* RO */
 #define EXT_CSD_HC_ERASE_GRP_SIZE	224	/* RO */
 #define EXT_CSD_BOOT_MULT		226	/* RO */
+#define EXT_CSD_PRE_EOL_INFO		267	/* RO */
 #define EXT_CSD_DEV_LIFETIME_EST_TYP_A	268	/* RO */
 #define EXT_CSD_DEV_LIFETIME_EST_TYP_B	269	/* RO */
 #define EXT_CSD_BKOPS_SUPPORT		502	/* RO */