Merge "fix(errata): workaround for Neoverse-N2 erratum 2376738" into integration
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 116afda..1b6e96b 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -25,6 +25,7 @@
 static const struct mmc_ops *ops;
 static unsigned int mmc_ocr_value;
 static struct mmc_csd_emmc mmc_csd;
+static struct sd_switch_status sd_switch_func_status;
 static unsigned char mmc_ext_csd[512] __aligned(16);
 static unsigned int mmc_flags;
 static struct mmc_device_info *mmc_dev_info;
@@ -44,6 +45,11 @@
 	return ((mmc_flags & MMC_FLAG_CMD23) != 0U);
 }
 
+static bool is_sd_cmd6_enabled(void)
+{
+	return ((mmc_flags & MMC_FLAG_SD_CMD6) != 0U);
+}
+
 static int mmc_send_cmd(unsigned int idx, unsigned int arg,
 			unsigned int r_type, unsigned int *r_data)
 {
@@ -357,6 +363,33 @@
 	return 0;
 }
 
+static int sd_switch(unsigned int mode, unsigned char group,
+		     unsigned char func)
+{
+	unsigned int group_shift = (group - 1U) * 4U;
+	unsigned int group_mask = GENMASK(group_shift + 3U,  group_shift);
+	unsigned int arg;
+	int ret;
+
+	ret = ops->prepare(0, (uintptr_t)&sd_switch_func_status,
+			   sizeof(sd_switch_func_status));
+	if (ret != 0) {
+		return ret;
+	}
+
+	/* MMC CMD6: SWITCH_FUNC */
+	arg = mode | SD_SWITCH_ALL_GROUPS_MASK;
+	arg &= ~group_mask;
+	arg |= func << group_shift;
+	ret = mmc_send_cmd(MMC_CMD(6), arg, MMC_RESPONSE_R1, NULL);
+	if (ret != 0) {
+		return ret;
+	}
+
+	return ops->read(0, (uintptr_t)&sd_switch_func_status,
+			 sizeof(sd_switch_func_status));
+}
+
 static int sd_send_op_cond(void)
 {
 	int n;
@@ -524,7 +557,39 @@
 		return ret;
 	}
 
-	return mmc_fill_device_info();
+	ret = mmc_fill_device_info();
+	if (ret != 0) {
+		return ret;
+	}
+
+	if (is_sd_cmd6_enabled() &&
+	    (mmc_dev_info->mmc_dev_type == MMC_IS_SD_HC)) {
+		/* Try to switch to High Speed Mode */
+		ret = sd_switch(SD_SWITCH_FUNC_CHECK, 1U, 1U);
+		if (ret != 0) {
+			return ret;
+		}
+
+		if ((sd_switch_func_status.support_g1 & BIT(9)) == 0U) {
+			/* High speed not supported, keep default speed */
+			return 0;
+		}
+
+		ret = sd_switch(SD_SWITCH_FUNC_SWITCH, 1U, 1U);
+		if (ret != 0) {
+			return ret;
+		}
+
+		if ((sd_switch_func_status.sel_g2_g1 & 0x1U) == 0U) {
+			/* Cannot switch to high speed, keep default speed */
+			return 0;
+		}
+
+		mmc_dev_info->max_bus_freq = 50000000U;
+		ret = ops->set_ios(clk, bus_width);
+	}
+
+	return ret;
 }
 
 size_t mmc_read_blocks(int lba, uintptr_t buf, size_t size)
diff --git a/drivers/st/etzpc/etzpc.c b/drivers/st/etzpc/etzpc.c
index ff52a22..4c3c26d 100644
--- a/drivers/st/etzpc/etzpc.c
+++ b/drivers/st/etzpc/etzpc.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2020, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2017-2022, STMicroelectronics - All Rights Reserved
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -225,20 +225,8 @@
 int etzpc_init(void)
 {
 	uint32_t hwcfg;
-	int node;
-	struct dt_node_info etzpc_info;
 
-	node = dt_get_node(&etzpc_info, -1, ETZPC_COMPAT);
-	if (node < 0) {
-		return -EIO;
-	}
-
-	/* Check ETZPC is secure only */
-	if (etzpc_info.status != DT_SECURE) {
-		return -EACCES;
-	}
-
-	etzpc_dev.base = etzpc_info.base;
+	etzpc_dev.base = STM32MP1_ETZPC_BASE;
 
 	hwcfg = mmio_read_32(etzpc_dev.base + ETZPC_HWCFGR);
 
diff --git a/drivers/st/mmc/stm32_sdmmc2.c b/drivers/st/mmc/stm32_sdmmc2.c
index 40641b5..6bdd782 100644
--- a/drivers/st/mmc/stm32_sdmmc2.c
+++ b/drivers/st/mmc/stm32_sdmmc2.c
@@ -129,6 +129,8 @@
 #define DT_SDMMC2_COMPAT		"st,stm32-sdmmc2"
 #endif
 
+#define SDMMC_FIFO_SIZE			64U
+
 static void stm32_sdmmc2_init(void);
 static int stm32_sdmmc2_send_cmd_req(struct mmc_cmd *cmd);
 static int stm32_sdmmc2_send_cmd(struct mmc_cmd *cmd);
@@ -148,6 +150,8 @@
 
 static struct stm32_sdmmc2_params sdmmc2_params;
 
+static bool next_cmd_is_acmd;
+
 #pragma weak plat_sdmmc2_use_dma
 bool plat_sdmmc2_use_dma(unsigned int instance, unsigned int memory)
 {
@@ -257,6 +261,20 @@
 	case MMC_CMD(1):
 		arg_reg |= OCR_POWERUP;
 		break;
+	case MMC_CMD(6):
+		if ((sdmmc2_params.device_info->mmc_dev_type == MMC_IS_SD_HC) &&
+		    (!next_cmd_is_acmd)) {
+			cmd_reg |= SDMMC_CMDR_CMDTRANS;
+			if (sdmmc2_params.use_dma) {
+				flags_data |= SDMMC_STAR_DCRCFAIL |
+					SDMMC_STAR_DTIMEOUT |
+					SDMMC_STAR_DATAEND |
+					SDMMC_STAR_RXOVERR |
+					SDMMC_STAR_IDMATE |
+					SDMMC_STAR_DBCKEND;
+			}
+		}
+		break;
 	case MMC_CMD(8):
 		if (sdmmc2_params.device_info->mmc_dev_type == MMC_IS_EMMC) {
 			cmd_reg |= SDMMC_CMDR_CMDTRANS;
@@ -294,6 +312,8 @@
 		break;
 	}
 
+	next_cmd_is_acmd = (cmd->cmd_idx == MMC_CMD(55));
+
 	mmio_write_32(base + SDMMC_ICR, SDMMC_STATIC_FLAGS);
 
 	/*
@@ -301,8 +321,7 @@
 	 * Skip CMD55 as the next command could be data related, and
 	 * the register could have been set in prepare function.
 	 */
-	if (((cmd_reg & SDMMC_CMDR_CMDTRANS) == 0U) &&
-	    (cmd->cmd_idx != MMC_CMD(55))) {
+	if (((cmd_reg & SDMMC_CMDR_CMDTRANS) == 0U) && !next_cmd_is_acmd) {
 		mmio_write_32(base + SDMMC_DCTRLR, 0U);
 	}
 
@@ -627,7 +646,7 @@
 			return -ETIMEDOUT;
 		}
 
-		if (size < (8U * sizeof(uint32_t))) {
+		if (size < (SDMMC_FIFO_SIZE / 2U)) {
 			if ((mmio_read_32(base + SDMMC_DCNTR) > 0U) &&
 			    ((status & SDMMC_STAR_RXFIFOE) == 0U)) {
 				*buffer = mmio_read_32(fifo_reg);
@@ -637,7 +656,8 @@
 			uint32_t count;
 
 			/* Read data from SDMMC Rx FIFO */
-			for (count = 0; count < 8U; count++) {
+			for (count = 0; count < (SDMMC_FIFO_SIZE / 2U);
+			     count += sizeof(uint32_t)) {
 				*buffer = mmio_read_32(fifo_reg);
 				buffer++;
 			}
@@ -737,8 +757,6 @@
 
 int stm32_sdmmc2_mmc_init(struct stm32_sdmmc2_params *params)
 {
-	int rc;
-
 	assert((params != NULL) &&
 	       ((params->reg_base & MMC_BLOCK_MASK) == 0U) &&
 	       ((params->bus_width == MMC_BUS_WIDTH_1) ||
@@ -756,16 +774,20 @@
 
 	clk_enable(sdmmc2_params.clock_id);
 
-	rc = stm32mp_reset_assert(sdmmc2_params.reset_id, TIMEOUT_US_1_MS);
-	if (rc != 0) {
-		panic();
+	if ((int)sdmmc2_params.reset_id >= 0) {
+		int rc;
+
+		rc = stm32mp_reset_assert(sdmmc2_params.reset_id, TIMEOUT_US_1_MS);
+		if (rc != 0) {
+			panic();
+		}
+		udelay(2);
+		rc = stm32mp_reset_deassert(sdmmc2_params.reset_id, TIMEOUT_US_1_MS);
+		if (rc != 0) {
+			panic();
+		}
+		mdelay(1);
 	}
-	udelay(2);
-	rc = stm32mp_reset_deassert(sdmmc2_params.reset_id, TIMEOUT_US_1_MS);
-	if (rc != 0) {
-		panic();
-	}
-	mdelay(1);
 
 	sdmmc2_params.clk_rate = clk_get_rate(sdmmc2_params.clock_id);
 	sdmmc2_params.device_info->ocr_voltage = OCR_3_2_3_3 | OCR_3_3_3_4;
diff --git a/fdts/stm32mp151.dtsi b/fdts/stm32mp151.dtsi
index 575d61e..bb16fda 100644
--- a/fdts/stm32mp151.dtsi
+++ b/fdts/stm32mp151.dtsi
@@ -497,8 +497,6 @@
 			compatible = "st,stm32-etzpc";
 			reg = <0x5C007000 0x400>;
 			clocks = <&rcc TZPC>;
-			status = "disabled";
-			secure-status = "okay";
 		};
 
 		stgen: stgen@5c008000 {
diff --git a/include/drivers/mmc.h b/include/drivers/mmc.h
index c154ea5..e973248 100644
--- a/include/drivers/mmc.h
+++ b/include/drivers/mmc.h
@@ -111,6 +111,7 @@
 #define MMC_STATE_SLP			10
 
 #define MMC_FLAG_CMD23			(U(1) << 0)
+#define MMC_FLAG_SD_CMD6		(U(1) << 1)
 
 #define CMD8_CHECK_PATTERN		U(0xAA)
 #define VHS_2_7_3_6_V			BIT(8)
@@ -118,6 +119,10 @@
 #define SD_SCR_BUS_WIDTH_1		BIT(8)
 #define SD_SCR_BUS_WIDTH_4		BIT(10)
 
+#define SD_SWITCH_FUNC_CHECK		0U
+#define SD_SWITCH_FUNC_SWITCH		BIT(31)
+#define SD_SWITCH_ALL_GROUPS_MASK	GENMASK(23, 0)
+
 struct mmc_cmd {
 	unsigned int	cmd_idx;
 	unsigned int	cmd_arg;
@@ -217,6 +222,27 @@
 	unsigned int		csd_structure:		2;
 };
 
+struct sd_switch_status {
+	unsigned short		max_current;
+	unsigned short		support_g6;
+	unsigned short		support_g5;
+	unsigned short		support_g4;
+	unsigned short		support_g3;
+	unsigned short		support_g2;
+	unsigned short		support_g1;
+	unsigned char		sel_g6_g5;
+	unsigned char		sel_g4_g3;
+	unsigned char		sel_g2_g1;
+	unsigned char		data_struct_ver;
+	unsigned short		busy_g6;
+	unsigned short		busy_g5;
+	unsigned short		busy_g4;
+	unsigned short		busy_g3;
+	unsigned short		busy_g2;
+	unsigned short		busy_g1;
+	unsigned short		reserved[17];
+};
+
 enum mmc_device_type {
 	MMC_IS_EMMC,
 	MMC_IS_SD,
diff --git a/plat/st/common/bl2_io_storage.c b/plat/st/common/bl2_io_storage.c
index 49f6465..8d0bdcc 100644
--- a/plat/st/common/bl2_io_storage.c
+++ b/plat/st/common/bl2_io_storage.c
@@ -221,6 +221,10 @@
 		break;
 	}
 
+	if (mmc_dev_type != MMC_IS_EMMC) {
+		params.flags = MMC_FLAG_SD_CMD6;
+	}
+
 	params.device_info = &mmc_info;
 	if (stm32_sdmmc2_mmc_init(&params) != 0) {
 		ERROR("SDMMC%u init failed\n", boot_interface_instance);