Merge tag 'u-boot-stm32-20220520' of https://source.denx.de/u-boot/custodians/u-boot-stm

- spi: fix busy bit check in stm32_qspi driver
- stm32mp15: configure Buck3 voltage per PMIC NVM on Avenger96 board
diff --git a/arch/arm/dts/stm32mp15xx-dhcor-io1v8.dtsi b/arch/arm/dts/stm32mp15xx-dhcor-io1v8.dtsi
index 9937b28..e209178 100644
--- a/arch/arm/dts/stm32mp15xx-dhcor-io1v8.dtsi
+++ b/arch/arm/dts/stm32mp15xx-dhcor-io1v8.dtsi
@@ -19,7 +19,7 @@
 };
 
 &vdd {
-	regulator-min-microvolt = <2900000>;
+	regulator-min-microvolt = <1800000>;
 	regulator-max-microvolt = <2900000>;
 };
 
diff --git a/board/dhelectronics/dh_stm32mp1/board.c b/board/dhelectronics/dh_stm32mp1/board.c
index 67273f9..d407f0b 100644
--- a/board/dhelectronics/dh_stm32mp1/board.c
+++ b/board/dhelectronics/dh_stm32mp1/board.c
@@ -594,14 +594,98 @@
 	setbits_le32(STM32_FMC2_BASE + STM32_FMC2_BCR1, STM32_FMC2_BCRx_FMCEN);
 }
 
+#ifdef CONFIG_DM_REGULATOR
+#define STPMIC_NVM_BUCKS_VOUT_SHR			0xfc
+#define STPMIC_NVM_BUCKS_VOUT_SHR_BUCK_1V2		0
+#define STPMIC_NVM_BUCKS_VOUT_SHR_BUCK_1V8		1
+#define STPMIC_NVM_BUCKS_VOUT_SHR_BUCK_3V0		2
+#define STPMIC_NVM_BUCKS_VOUT_SHR_BUCK_3V3		3
+#define STPMIC_NVM_BUCKS_VOUT_SHR_BUCK_MASK		GENMASK(1, 0)
+#define STPMIC_NVM_BUCKS_VOUT_SHR_BUCK_OFFSET(n)	((((n) - 1) & 3) * 2)
+static int board_get_regulator_buck3_nvm_uv_av96(int *uv)
+{
+	const void *fdt = gd->fdt_blob;
+	struct udevice *dev;
+	u8 bucks_vout = 0;
+	const char *prop;
+	int len, ret;
+
+	/* Check whether this is Avenger96 board. */
+	prop = fdt_getprop(fdt, 0, "compatible", &len);
+	if (!prop || !len)
+		return -ENODEV;
+
+	if (!strstr(prop, "avenger96"))
+		return -EINVAL;
+
+	/* Read out STPMIC1 NVM and determine default Buck3 voltage. */
+	ret = uclass_get_device_by_driver(UCLASS_MISC,
+					  DM_DRIVER_GET(stpmic1_nvm),
+					  &dev);
+	if (ret)
+		return ret;
+
+	ret = misc_read(dev, STPMIC_NVM_BUCKS_VOUT_SHR, &bucks_vout, 1);
+	if (ret != 1)
+		return -EINVAL;
+
+	bucks_vout >>= STPMIC_NVM_BUCKS_VOUT_SHR_BUCK_OFFSET(3);
+	bucks_vout &= STPMIC_NVM_BUCKS_VOUT_SHR_BUCK_MASK;
+
+	/*
+	 * Avenger96 board comes in multiple regulator configurations:
+	 * - rev.100 or rev.200 have Buck3 preconfigured to 3V3 operation on
+	 *   boot and contains extra Enpirion EP53A8LQI DCDC converter which
+	 *   supplies the IO. Reduce Buck3 voltage to 2V9 to not waste power.
+	 * - rev.200L have Buck3 preconfigured to 1V8 operation and have no
+	 *   Enpirion EP53A8LQI DCDC anymore, the IO is supplied from Buck3.
+	 */
+	if (bucks_vout == STPMIC_NVM_BUCKS_VOUT_SHR_BUCK_3V3)
+		*uv = 2900000;
+	else
+		*uv = 1800000;
+
+	return 0;
+}
+
+static void board_init_regulator_av96(void)
+{
+	struct udevice *rdev;
+	int ret, uv;
+
+	ret = board_get_regulator_buck3_nvm_uv_av96(&uv);
+	if (ret)	/* Not Avenger96 board. */
+		return;
+
+	ret = regulator_get_by_devname("buck3", &rdev);
+	if (ret)
+		return;
+
+	/* Adjust Buck3 per preconfigured PMIC voltage from NVM. */
+	regulator_set_value(rdev, uv);
+}
+
+static void board_init_regulator(void)
+{
+	board_init_regulator_av96();
+
+	regulators_enable_boot_on(_DEBUG);
+}
+#else
+static inline int board_get_regulator_buck3_nvm_uv_av96(int *uv)
+{
+	return -EINVAL;
+}
+
+static inline void board_init_regulator(void) {}
+#endif
+
 /* board dependent setup after realloc */
 int board_init(void)
 {
 	board_key_check();
 
-#ifdef CONFIG_DM_REGULATOR
-	regulators_enable_boot_on(_DEBUG);
-#endif
+	board_init_regulator();
 
 	sysconf_init();
 
@@ -721,6 +805,25 @@
 #if defined(CONFIG_OF_BOARD_SETUP)
 int ft_board_setup(void *blob, struct bd_info *bd)
 {
+	const char *buck3path = "/soc/i2c@5c002000/stpmic@33/regulators/buck3";
+	int buck3off, ret, uv;
+
+	ret = board_get_regulator_buck3_nvm_uv_av96(&uv);
+	if (ret)	/* Not Avenger96 board, do not patch Buck3 in DT. */
+		return 0;
+
+	buck3off = fdt_path_offset(blob, buck3path);
+	if (buck3off < 0)	/* No Buck3 regulator found. */
+		return 0;
+
+	ret = fdt_setprop_u32(blob, buck3off, "regulator-min-microvolt", uv);
+	if (ret < 0)
+		return ret;
+
+	ret = fdt_setprop_u32(blob, buck3off, "regulator-max-microvolt", uv);
+	if (ret < 0)
+		return ret;
+
 	return 0;
 }
 #endif
diff --git a/drivers/spi/stm32_qspi.c b/drivers/spi/stm32_qspi.c
index 8f4aabc..ceba413 100644
--- a/drivers/spi/stm32_qspi.c
+++ b/drivers/spi/stm32_qspi.c
@@ -150,20 +150,19 @@
 	u32 sr;
 	int ret = 0;
 
-	if (op->data.nbytes) {
-		ret = readl_poll_timeout(&priv->regs->sr, sr,
-					 sr & STM32_QSPI_SR_TCF,
-					 STM32_QSPI_CMD_TIMEOUT_US);
-		if (ret) {
-			log_err("cmd timeout (stat:%#x)\n", sr);
-		} else if (readl(&priv->regs->sr) & STM32_QSPI_SR_TEF) {
-			log_err("transfer error (stat:%#x)\n", sr);
-			ret = -EIO;
-		}
-		/* clear flags */
-		writel(STM32_QSPI_FCR_CTCF | STM32_QSPI_FCR_CTEF, &priv->regs->fcr);
+	ret = readl_poll_timeout(&priv->regs->sr, sr,
+				 sr & STM32_QSPI_SR_TCF,
+				 STM32_QSPI_CMD_TIMEOUT_US);
+	if (ret) {
+		log_err("cmd timeout (stat:%#x)\n", sr);
+	} else if (readl(&priv->regs->sr) & STM32_QSPI_SR_TEF) {
+		log_err("transfer error (stat:%#x)\n", sr);
+		ret = -EIO;
 	}
 
+	/* clear flags */
+	writel(STM32_QSPI_FCR_CTCF | STM32_QSPI_FCR_CTEF, &priv->regs->fcr);
+
 	if (!ret)
 		ret = _stm32_qspi_wait_for_not_busy(priv);
 
@@ -256,10 +255,6 @@
 		op->dummy.buswidth, op->data.buswidth,
 		op->addr.val, op->data.nbytes);
 
-	ret = _stm32_qspi_wait_for_not_busy(priv);
-	if (ret)
-		return ret;
-
 	addr_max = op->addr.val + op->data.nbytes + 1;
 
 	if (op->data.dir == SPI_MEM_DATA_IN && op->data.nbytes) {