Merge tag 'u-boot-stm32-20190606' of https://github.com/pchotard/u-boot

- Add Ethernet support for STM32MP1
- Add saveenv support for STM32MP1
- Add STM32MP1 Avenger96 board support
- Add SPI driver suport for STM32MP1
- Add watchdog support for STM32MP1
- Update power supply check via USB TYPE-C for STM32MP1 discovery board
diff --git a/MAINTAINERS b/MAINTAINERS
index 190050c..56bc543 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -313,6 +313,8 @@
 F:	drivers/misc/stm32_rcc.c
 F:	drivers/reset/stm32-reset.c
 F:	drivers/spi/stm32_qspi.c
+F:	drivers/spi/stm32_spi.c
+F:	drivers/watchdog/stm32mp_wdt.c
 
 ARM STM STV0991
 M:	Vikas Manocha <vikas.manocha@st.com>
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index 3d31966..528fb90 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -757,6 +757,7 @@
 
 dtb-$(CONFIG_TARGET_STM32MP1) += \
 	stm32mp157a-dk1.dtb \
+	stm32mp157a-avenger96.dtb \
 	stm32mp157c-dk2.dtb \
 	stm32mp157c-ed1.dtb \
 	stm32mp157c-ev1.dtb
diff --git a/arch/arm/dts/stm32mp157-pinctrl.dtsi b/arch/arm/dts/stm32mp157-pinctrl.dtsi
index 0aae69b..4c424c4 100644
--- a/arch/arm/dts/stm32mp157-pinctrl.dtsi
+++ b/arch/arm/dts/stm32mp157-pinctrl.dtsi
@@ -173,13 +173,18 @@
 						 <STM32_PINMUX('C', 2, AF11)>, /* ETH_RGMII_TXD2 */
 						 <STM32_PINMUX('E', 2, AF11)>, /* ETH_RGMII_TXD3 */
 						 <STM32_PINMUX('B', 11, AF11)>, /* ETH_RGMII_TX_CTL */
-						 <STM32_PINMUX('A', 2, AF11)>, /* ETH_MDIO */
 						 <STM32_PINMUX('C', 1, AF11)>; /* ETH_MDC */
 					bias-disable;
 					drive-push-pull;
-					slew-rate = <3>;
+					slew-rate = <2>;
 				};
 				pins2 {
+					pinmux = <STM32_PINMUX('A', 2, AF11)>; /* ETH_MDIO */
+					bias-disable;
+					drive-push-pull;
+					slew-rate = <0>;
+				};
+				pins3 {
 					pinmux = <STM32_PINMUX('C', 4, AF11)>, /* ETH_RGMII_RXD0 */
 						 <STM32_PINMUX('C', 5, AF11)>, /* ETH_RGMII_RXD1 */
 						 <STM32_PINMUX('B', 0, AF11)>, /* ETH_RGMII_RXD2 */
@@ -210,6 +215,50 @@
 				};
 			};
 
+			fmc_pins_a: fmc-0 {
+				pins1 {
+					pinmux = <STM32_PINMUX('D', 4, AF12)>, /* FMC_NOE */
+						 <STM32_PINMUX('D', 5, AF12)>, /* FMC_NWE */
+						 <STM32_PINMUX('D', 11, AF12)>, /* FMC_A16_FMC_CLE */
+						 <STM32_PINMUX('D', 12, AF12)>, /* FMC_A17_FMC_ALE */
+						 <STM32_PINMUX('D', 14, AF12)>, /* FMC_D0 */
+						 <STM32_PINMUX('D', 15, AF12)>, /* FMC_D1 */
+						 <STM32_PINMUX('D', 0, AF12)>, /* FMC_D2 */
+						 <STM32_PINMUX('D', 1, AF12)>, /* FMC_D3 */
+						 <STM32_PINMUX('E', 7, AF12)>, /* FMC_D4 */
+						 <STM32_PINMUX('E', 8, AF12)>, /* FMC_D5 */
+						 <STM32_PINMUX('E', 9, AF12)>, /* FMC_D6 */
+						 <STM32_PINMUX('E', 10, AF12)>, /* FMC_D7 */
+						 <STM32_PINMUX('G', 9, AF12)>; /* FMC_NE2_FMC_NCE */
+					bias-disable;
+					drive-push-pull;
+					slew-rate = <1>;
+				};
+				pins2 {
+					pinmux = <STM32_PINMUX('D', 6, AF12)>; /* FMC_NWAIT */
+					bias-pull-up;
+				};
+			};
+
+			fmc_sleep_pins_a: fmc-sleep-0 {
+				pins {
+					pinmux = <STM32_PINMUX('D', 4, ANALOG)>, /* FMC_NOE */
+						 <STM32_PINMUX('D', 5, ANALOG)>, /* FMC_NWE */
+						 <STM32_PINMUX('D', 11, ANALOG)>, /* FMC_A16_FMC_CLE */
+						 <STM32_PINMUX('D', 12, ANALOG)>, /* FMC_A17_FMC_ALE */
+						 <STM32_PINMUX('D', 14, ANALOG)>, /* FMC_D0 */
+						 <STM32_PINMUX('D', 15, ANALOG)>, /* FMC_D1 */
+						 <STM32_PINMUX('D', 0, ANALOG)>, /* FMC_D2 */
+						 <STM32_PINMUX('D', 1, ANALOG)>, /* FMC_D3 */
+						 <STM32_PINMUX('E', 7, ANALOG)>, /* FMC_D4 */
+						 <STM32_PINMUX('E', 8, ANALOG)>, /* FMC_D5 */
+						 <STM32_PINMUX('E', 9, ANALOG)>, /* FMC_D6 */
+						 <STM32_PINMUX('E', 10, ANALOG)>, /* FMC_D7 */
+						 <STM32_PINMUX('D', 6, ANALOG)>, /* FMC_NWAIT */
+						 <STM32_PINMUX('G', 9, ANALOG)>; /* FMC_NE2_FMC_NCE */
+				};
+			};
+
 			i2c1_pins_a: i2c1-0 {
 				pins {
 					pinmux = <STM32_PINMUX('D', 12, AF5)>, /* I2C1_SCL */
@@ -220,6 +269,16 @@
 				};
 			};
 
+			i2c1_pins_b: i2c1-1 {
+				pins {
+					pinmux = <STM32_PINMUX('F', 14, AF5)>, /* I2C1_SCL */
+						 <STM32_PINMUX('F', 15, AF5)>; /* I2C1_SDA */
+					bias-disable;
+					drive-open-drain;
+					slew-rate = <0>;
+				};
+			};
+
 			i2c2_pins_a: i2c2-0 {
 				pins {
 					pinmux = <STM32_PINMUX('H', 4, AF4)>, /* I2C2_SCL */
@@ -230,6 +289,16 @@
 				};
 			};
 
+			i2c2_pins_b: i2c2-1 {
+				pins {
+					pinmux = <STM32_PINMUX('Z', 0, AF3)>, /* I2C2_SCL */
+						 <STM32_PINMUX('H', 5, AF4)>; /* I2C2_SDA */
+					bias-disable;
+					drive-open-drain;
+					slew-rate = <0>;
+				};
+			};
+
 			i2c5_pins_a: i2c5-0 {
 				pins {
 					pinmux = <STM32_PINMUX('A', 11, AF4)>, /* I2C5_SCL */
@@ -375,6 +444,21 @@
 				};
 			};
 
+			spi2_pins_a: spi2-0 {
+				pins1 {
+					pinmux = <STM32_PINMUX('B', 10, AF5)>, /* SPI2_SCK */
+						 <STM32_PINMUX('I', 0, AF5)>, /* SPI2_NSS */
+						 <STM32_PINMUX('I', 3, AF5)>; /* SPI2_MOSI */
+					bias-disable;
+					drive-push-pull;
+					slew-rate = <3>;
+				};
+				pins2 {
+					pinmux = <STM32_PINMUX('I', 2, AF5)>; /* SPI2_MISO */
+					bias-disable;
+				};
+			};
+
 			stusb1600_pins_a: stusb1600-0 {
 				pins {
 					pinmux = <STM32_PINMUX('I', 11, ANALOG)>;
@@ -395,6 +479,34 @@
 				};
 			};
 
+			uart4_pins_b: uart4-1 {
+				pins1 {
+					pinmux = <STM32_PINMUX('D', 1, AF8)>; /* UART4_TX */
+					bias-disable;
+					drive-push-pull;
+					slew-rate = <0>;
+				};
+				pins2 {
+					pinmux = <STM32_PINMUX('B', 2, AF8)>; /* UART4_RX */
+					bias-disable;
+				};
+			};
+
+			uart7_pins_a: uart7-0 {
+				pins1 {
+					pinmux = <STM32_PINMUX('E', 8, AF7)>; /* UART4_TX */
+					bias-disable;
+					drive-push-pull;
+					slew-rate = <0>;
+				};
+				pins2 {
+					pinmux = <STM32_PINMUX('E', 7, AF7)>, /* UART4_RX */
+						 <STM32_PINMUX('E', 10, AF7)>, /* UART4_CTS */
+						 <STM32_PINMUX('E', 9, AF7)>; /* UART4_RTS */
+					bias-disable;
+				};
+			};
+
 			usbotg_hs_pins_a: usbotg_hs-0 {
 				pins {
 					pinmux = <STM32_PINMUX('A', 10, ANALOG)>; /* OTG_ID */
diff --git a/arch/arm/dts/stm32mp157-u-boot.dtsi b/arch/arm/dts/stm32mp157-u-boot.dtsi
index ab6f673..09560e2 100644
--- a/arch/arm/dts/stm32mp157-u-boot.dtsi
+++ b/arch/arm/dts/stm32mp157-u-boot.dtsi
@@ -140,3 +140,7 @@
 	compatible = "st,stm32-gpio";
 	u-boot,dm-pre-reloc;
 };
+
+&iwdg2 {
+	u-boot,dm-pre-reloc;
+};
diff --git a/arch/arm/dts/stm32mp157a-avenger96-u-boot.dtsi b/arch/arm/dts/stm32mp157a-avenger96-u-boot.dtsi
new file mode 100644
index 0000000..1ff681a
--- /dev/null
+++ b/arch/arm/dts/stm32mp157a-avenger96-u-boot.dtsi
@@ -0,0 +1,191 @@
+// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
+/*
+ * Copyright : STMicroelectronics 2018
+ *
+ * Copyright (C) Linaro Ltd 2019 - All Rights Reserved
+ * Author: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+ */
+
+#include <dt-bindings/clock/stm32mp1-clksrc.h>
+#include "stm32mp157-u-boot.dtsi"
+#include "stm32mp15-ddr3-2x4Gb-1066-binG.dtsi"
+
+/ {
+	aliases {
+		mmc0 = &sdmmc1;
+		mmc1 = &sdmmc2;
+		usb0 = &usbotg_hs;
+	};
+
+	config {
+		u-boot,boot-led = "led1";
+		u-boot,error-led = "led4";
+	};
+};
+
+&i2c4 {
+	u-boot,dm-pre-reloc;
+};
+
+&i2c4_pins_a {
+	u-boot,dm-pre-reloc;
+	pins {
+		u-boot,dm-pre-reloc;
+	};
+};
+
+&pmic {
+	u-boot,dm-pre-reloc;
+};
+
+&rcc {
+	st,clksrc = <
+		CLK_MPU_PLL1P
+		CLK_AXI_PLL2P
+		CLK_MCU_PLL3P
+		CLK_PLL12_HSE
+		CLK_PLL3_HSE
+		CLK_PLL4_HSE
+		CLK_RTC_LSE
+		CLK_MCO1_DISABLED
+		CLK_MCO2_DISABLED
+	>;
+
+	st,clkdiv = <
+		1 /*MPU*/
+		0 /*AXI*/
+		0 /*MCU*/
+		1 /*APB1*/
+		1 /*APB2*/
+		1 /*APB3*/
+		1 /*APB4*/
+		2 /*APB5*/
+		23 /*RTC*/
+		0 /*MCO1*/
+		0 /*MCO2*/
+	>;
+
+	st,pkcs = <
+		CLK_CKPER_HSE
+		CLK_FMC_ACLK
+		CLK_QSPI_ACLK
+		CLK_ETH_DISABLED
+		CLK_SDMMC12_PLL4P
+		CLK_DSI_DSIPLL
+		CLK_STGEN_HSE
+		CLK_USBPHY_HSE
+		CLK_SPI2S1_PLL3Q
+		CLK_SPI2S23_PLL3Q
+		CLK_SPI45_HSI
+		CLK_SPI6_HSI
+		CLK_I2C46_HSI
+		CLK_SDMMC3_PLL4P
+		CLK_USBO_USBPHY
+		CLK_ADC_CKPER
+		CLK_CEC_LSE
+		CLK_I2C12_HSI
+		CLK_I2C35_HSI
+		CLK_UART1_HSI
+		CLK_UART24_HSI
+		CLK_UART35_HSI
+		CLK_UART6_HSI
+		CLK_UART78_HSI
+		CLK_SPDIF_PLL4P
+		CLK_FDCAN_PLL4Q
+		CLK_SAI1_PLL3Q
+		CLK_SAI2_PLL3Q
+		CLK_SAI3_PLL3Q
+		CLK_SAI4_PLL3Q
+		CLK_RNG1_LSI
+		CLK_RNG2_LSI
+		CLK_LPTIM1_PCLK1
+		CLK_LPTIM23_PCLK3
+		CLK_LPTIM45_LSE
+	>;
+
+	/* VCO = 1300.0 MHz => P = 650 (CPU) */
+	pll1: st,pll@0 {
+		cfg = < 2 80 0 0 0 PQR(1,0,0) >;
+		frac = < 0x800 >;
+		u-boot,dm-pre-reloc;
+	};
+
+	/* VCO = 1066.0 MHz => P = 266 (AXI), Q = 533 (GPU), R = 533 (DDR) */
+	pll2: st,pll@1 {
+		cfg = < 2 65 1 0 0 PQR(1,1,1) >;
+		frac = < 0x1400 >;
+		u-boot,dm-pre-reloc;
+	};
+
+	/* VCO = 417.8 MHz => P = 209, Q = 24, R = 11 */
+	pll3: st,pll@2 {
+		cfg = < 1 33 1 16 36 PQR(1,1,1) >;
+		frac = < 0x1a04 >;
+		u-boot,dm-pre-reloc;
+	};
+
+	/* VCO = 480.0 MHz => P = 120, Q = 40, R = 96 */
+	pll4: st,pll@3 {
+		cfg = < 1 39 3 11 4 PQR(1,1,1) >;
+		u-boot,dm-pre-reloc;
+	};
+};
+
+&sdmmc1 {
+	u-boot,dm-spl;
+};
+
+&sdmmc1_b4_pins_a {
+	u-boot,dm-spl;
+	pins {
+		u-boot,dm-spl;
+	};
+};
+
+&sdmmc1_dir_pins_a {
+	u-boot,dm-spl;
+	pins {
+		u-boot,dm-spl;
+	};
+};
+
+&sdmmc2 {
+	u-boot,dm-spl;
+};
+
+&sdmmc2_b4_pins_a {
+	u-boot,dm-spl;
+	pins {
+		u-boot,dm-spl;
+	};
+};
+
+&sdmmc2_d47_pins_a {
+	u-boot,dm-spl;
+	pins {
+		u-boot,dm-spl;
+	};
+};
+
+&uart4 {
+	u-boot,dm-pre-reloc;
+};
+
+&uart4_pins_b {
+	u-boot,dm-pre-reloc;
+	pins1 {
+		u-boot,dm-pre-reloc;
+	};
+	pins2 {
+		u-boot,dm-pre-reloc;
+	};
+};
+
+&usbotg_hs {
+	u-boot,force-b-session-valid;
+	hnp-srp-disable;
+};
+
+&v3v3 {
+	regulator-always-on;
+};
diff --git a/arch/arm/dts/stm32mp157a-avenger96.dts b/arch/arm/dts/stm32mp157a-avenger96.dts
new file mode 100644
index 0000000..dd08597
--- /dev/null
+++ b/arch/arm/dts/stm32mp157a-avenger96.dts
@@ -0,0 +1,362 @@
+// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
+/*
+ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved
+ * Author: Alexandre Torgue <alexandre.torgue@st.com> for STMicroelectronics.
+ *
+ * Copyright (C) Linaro Ltd 2019 - All Rights Reserved
+ * Author: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+ */
+
+/dts-v1/;
+
+#include "stm32mp157c.dtsi"
+#include "stm32mp157-pinctrl.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/mfd/st,stpmic1.h>
+
+/ {
+	model = "Arrow Electronics STM32MP157A Avenger96 board";
+	compatible = "st,stm32mp157a-avenger96", "st,stm32mp157";
+
+	aliases {
+		ethernet0 = &ethernet0;
+		serial0 = &uart4;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	memory@c0000000 {
+		reg = <0xc0000000 0x40000000>;
+	};
+
+	led {
+		compatible = "gpio-leds";
+		led1 {
+			label = "green:user1";
+			gpios = <&gpioz 7 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "heartbeat";
+			default-state = "off";
+		};
+
+		led2 {
+			label = "green:user2";
+			gpios = <&gpiof 3 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "mmc0";
+			default-state = "off";
+		};
+
+		led3 {
+			label = "green:user3";
+			gpios = <&gpiog 0 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "mmc1";
+			default-state = "off";
+		};
+
+		led4 {
+			label = "green:user3";
+			gpios = <&gpiog 1 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "none";
+			default-state = "off";
+			panic-indicator;
+		};
+
+		led5 {
+			label = "yellow:wifi";
+			gpios = <&gpioz 3 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "phy0tx";
+			default-state = "off";
+		};
+
+		led6 {
+			label = "blue:bt";
+			gpios = <&gpioz 6 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "bluetooth-power";
+			default-state = "off";
+		};
+	};
+};
+
+&ethernet0 {
+	status = "okay";
+	pinctrl-0 = <&ethernet0_rgmii_pins_a>;
+	pinctrl-1 = <&ethernet0_rgmii_pins_sleep_a>;
+	pinctrl-names = "default", "sleep";
+	phy-mode = "rgmii";
+	max-speed = <1000>;
+	phy-handle = <&phy0>;
+
+	mdio0 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "snps,dwmac-mdio";
+		phy0: ethernet-phy@7 {
+			reg = <7>;
+		};
+	};
+};
+
+&i2c1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c1_pins_b>;
+	i2c-scl-rising-time-ns = <185>;
+	i2c-scl-falling-time-ns = <20>;
+	status = "okay";
+	/delete-property/dmas;
+	/delete-property/dma-names;
+};
+
+&i2c2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c2_pins_b>;
+	i2c-scl-rising-time-ns = <185>;
+	i2c-scl-falling-time-ns = <20>;
+	status = "okay";
+	/delete-property/dmas;
+	/delete-property/dma-names;
+};
+
+&i2c4 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c4_pins_a>;
+	i2c-scl-rising-time-ns = <185>;
+	i2c-scl-falling-time-ns = <20>;
+	status = "okay";
+	/delete-property/dmas;
+	/delete-property/dma-names;
+
+	pmic: stpmic@33 {
+		compatible = "st,stpmic1";
+		reg = <0x33>;
+		interrupts-extended = <&exti 55 IRQ_TYPE_EDGE_FALLING>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		status = "okay";
+
+		st,main-control-register = <0x04>;
+		st,vin-control-register = <0xc0>;
+		st,usb-control-register = <0x30>;
+
+		regulators {
+			compatible = "st,stpmic1-regulators";
+
+			ldo1-supply = <&v3v3>;
+			ldo2-supply = <&v3v3>;
+			ldo3-supply = <&vdd_ddr>;
+			ldo5-supply = <&v3v3>;
+			ldo6-supply = <&v3v3>;
+			pwr_sw1-supply = <&bst_out>;
+			pwr_sw2-supply = <&bst_out>;
+
+			vddcore: buck1 {
+				regulator-name = "vddcore";
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <1350000>;
+				regulator-always-on;
+				regulator-initial-mode = <2>;
+				regulator-over-current-protection;
+			};
+
+			vdd_ddr: buck2 {
+				regulator-name = "vdd_ddr";
+				regulator-min-microvolt = <1350000>;
+				regulator-max-microvolt = <1350000>;
+				regulator-always-on;
+				regulator-initial-mode = <2>;
+				regulator-over-current-protection;
+			};
+
+			vdd: buck3 {
+				regulator-name = "vdd";
+				regulator-min-microvolt = <2500000>;
+				regulator-max-microvolt = <2500000>;
+				regulator-always-on;
+				st,mask_reset;
+				regulator-initial-mode = <8>;
+				regulator-over-current-protection;
+			};
+
+			v3v3: buck4 {
+				regulator-name = "v3v3";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+				regulator-over-current-protection;
+				regulator-initial-mode = <8>;
+			};
+
+			vdda: ldo1 {
+				regulator-name = "vdda";
+				regulator-min-microvolt = <2900000>;
+				regulator-max-microvolt = <2900000>;
+				interrupts = <IT_CURLIM_LDO1 0>;
+				interrupt-parent = <&pmic>;
+			};
+
+			v2v8: ldo2 {
+				regulator-name = "v2v8";
+				regulator-min-microvolt = <2800000>;
+				regulator-max-microvolt = <2800000>;
+				interrupts = <IT_CURLIM_LDO2 0>;
+				interrupt-parent = <&pmic>;
+			};
+
+			vtt_ddr: ldo3 {
+				regulator-name = "vtt_ddr";
+				regulator-min-microvolt = <0000000>;
+				regulator-max-microvolt = <1000000>;
+				regulator-always-on;
+				regulator-over-current-protection;
+			};
+
+			vdd_usb: ldo4 {
+				regulator-name = "vdd_usb";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				interrupts = <IT_CURLIM_LDO4 0>;
+				interrupt-parent = <&pmic>;
+			};
+
+			vdd_sd: ldo5 {
+				regulator-name = "vdd_sd";
+				regulator-min-microvolt = <2900000>;
+				regulator-max-microvolt = <2900000>;
+				interrupts = <IT_CURLIM_LDO5 0>;
+				interrupt-parent = <&pmic>;
+				regulator-boot-on;
+			};
+
+			v1v8: ldo6 {
+				regulator-name = "v1v8";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				interrupts = <IT_CURLIM_LDO6 0>;
+				interrupt-parent = <&pmic>;
+			};
+
+			vref_ddr: vref_ddr {
+				regulator-name = "vref_ddr";
+				regulator-always-on;
+				regulator-over-current-protection;
+			};
+
+			bst_out: boost {
+				regulator-name = "bst_out";
+				interrupts = <IT_OCP_BOOST 0>;
+				interrupt-parent = <&pmic>;
+			};
+
+			vbus_otg: pwr_sw1 {
+				regulator-name = "vbus_otg";
+				interrupts = <IT_OCP_OTG 0>;
+				interrupt-parent = <&pmic>;
+				regulator-active-discharge;
+			};
+
+			vbus_sw: pwr_sw2 {
+				regulator-name = "vbus_sw";
+				interrupts = <IT_OCP_SWOUT 0>;
+				interrupt-parent = <&pmic>;
+				regulator-active-discharge;
+			};
+		};
+
+		onkey {
+			compatible = "st,stpmic1-onkey";
+			interrupts = <IT_PONKEY_F 0>, <IT_PONKEY_R 1>;
+			interrupt-names = "onkey-falling", "onkey-rising";
+			status = "okay";
+		};
+
+		watchdog {
+			compatible = "st,stpmic1-wdt";
+			status = "disabled";
+		};
+	};
+};
+
+&iwdg2 {
+	timeout-sec = <32>;
+	status = "okay";
+};
+
+&pwr {
+	pwr-supply = <&vdd>;
+};
+
+&rng1 {
+	status = "okay";
+};
+
+&rtc {
+	status = "okay";
+};
+
+&sdmmc1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&sdmmc1_b4_pins_a &sdmmc1_dir_pins_a>;
+	broken-cd;
+	st,sig-dir;
+	st,neg-edge;
+	st,use-ckin;
+	bus-width = <4>;
+	vmmc-supply = <&vdd_sd>;
+	status = "okay";
+};
+
+&sdmmc2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&sdmmc2_b4_pins_a &sdmmc2_d47_pins_a>;
+	non-removable;
+	no-sd;
+	no-sdio;
+	st,neg-edge;
+	bus-width = <8>;
+	vmmc-supply = <&v3v3>;
+	mmc-ddr-3_3v;
+	status = "okay";
+};
+
+&spi2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&spi2_pins_a>;
+	status = "okay";
+};
+
+&uart4 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart4_pins_b>;
+	status = "okay";
+};
+
+&uart7 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart7_pins_a>;
+	status = "okay";
+};
+
+&usbh_ehci {
+	phys = <&usbphyc_port0>;
+	phy-names = "usb";
+	status = "okay";
+};
+
+&usbotg_hs {
+	dr_mode = "peripheral";
+	phys = <&usbphyc_port1 0>;
+	phy-names = "usb2-phy";
+	status = "okay";
+};
+
+&usbphyc {
+	status = "okay";
+};
+
+&usbphyc_port0 {
+	phy-supply = <&vdd_usb>;
+};
+
+&usbphyc_port1 {
+	phy-supply = <&vdd_usb>;
+};
diff --git a/arch/arm/dts/stm32mp157c-ev1.dts b/arch/arm/dts/stm32mp157c-ev1.dts
index a6ee379..663e52a 100644
--- a/arch/arm/dts/stm32mp157c-ev1.dts
+++ b/arch/arm/dts/stm32mp157c-ev1.dts
@@ -78,7 +78,7 @@
 	pinctrl-0 = <&ethernet0_rgmii_pins_a>;
 	pinctrl-1 = <&ethernet0_rgmii_pins_sleep_a>;
 	pinctrl-names = "default", "sleep";
-	phy-mode = "rgmii";
+	phy-mode = "rgmii-id";
 	max-speed = <1000>;
 	phy-handle = <&phy0>;
 
@@ -92,6 +92,22 @@
 	};
 };
 
+&fmc {
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&fmc_pins_a>;
+	pinctrl-1 = <&fmc_sleep_pins_a>;
+	status = "okay";
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	nand: nand@0 {
+		reg = <0>;
+		nand-on-flash-bbt;
+		#address-cells = <1>;
+		#size-cells = <1>;
+	};
+};
+
 &i2c2 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&i2c2_pins_a>;
diff --git a/arch/arm/dts/stm32mp157c.dtsi b/arch/arm/dts/stm32mp157c.dtsi
index 9463433..7321585 100644
--- a/arch/arm/dts/stm32mp157c.dtsi
+++ b/arch/arm/dts/stm32mp157c.dtsi
@@ -1033,6 +1033,21 @@
 			dma-requests = <48>;
 		};
 
+		fmc: nand-controller@58002000 {
+			compatible = "st,stm32mp15-fmc2";
+			reg = <0x58002000 0x1000>,
+			      <0x80000000 0x1000>,
+			      <0x88010000 0x1000>,
+			      <0x88020000 0x1000>,
+			      <0x81000000 0x1000>,
+			      <0x89010000 0x1000>,
+			      <0x89020000 0x1000>;
+			interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&rcc FMC_K>;
+			resets = <&rcc FMC_R>;
+			status = "disabled";
+		};
+
 		qspi: spi@58003000 {
 			compatible = "st,stm32f469-qspi";
 			reg = <0x58003000 0x1000>, <0x70000000 0x10000000>;
@@ -1087,21 +1102,25 @@
 			compatible = "st,stm32mp1-dwmac", "snps,dwmac-4.20a";
 			reg = <0x5800a000 0x2000>;
 			reg-names = "stmmaceth";
-			interrupts-extended = <&intc GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>;
-			interrupt-names = "macirq";
+			interrupts-extended =
+				<&intc GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>,
+				<&intc GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>,
+				<&exti 70 1>;
+			interrupt-names = "macirq",
+					  "eth_wake_irq",
+					  "stm32_pwr_wakeup";
 			clock-names = "stmmaceth",
 				      "mac-clk-tx",
 				      "mac-clk-rx",
-				      "ethstp",
-				      "syscfg-clk";
+				      "ethstp";
 			clocks = <&rcc ETHMAC>,
 				 <&rcc ETHTX>,
 				 <&rcc ETHRX>,
-				 <&rcc ETHSTP>,
-				 <&rcc SYSCFG>;
+				 <&rcc ETHSTP>;
 			st,syscon = <&syscfg 0x4>;
 			snps,mixed-burst;
 			snps,pbl = <2>;
+			snps,en-tx-lpi-clockgating;
 			snps,axi-config = <&stmmac_axi_config_0>;
 			snps,tso;
 			status = "disabled";
diff --git a/arch/arm/mach-stm32mp/Kconfig b/arch/arm/mach-stm32mp/Kconfig
index 77f66c6..d9ad6b4 100644
--- a/arch/arm/mach-stm32mp/Kconfig
+++ b/arch/arm/mach-stm32mp/Kconfig
@@ -17,6 +17,7 @@
 	select SPL_DM_RESET
 	select SPL_SERIAL_SUPPORT
 	select SPL_SYSCON
+	select SPL_WATCHDOG_SUPPORT
 	imply BOOTSTAGE_STASH if SPL_BOOTSTAGE
 	imply SPL_BOOTSTAGE if BOOTSTAGE
 	imply SPL_DISPLAY_PRINT
@@ -29,7 +30,7 @@
 	default 0x2000000
 
 config ENV_SIZE
-	default 0x1000
+	default 0x2000
 
 config TARGET_STM32MP1
 	bool "Support stm32mp1xx"
diff --git a/arch/arm/mach-stm32mp/cpu.c b/arch/arm/mach-stm32mp/cpu.c
index 7b4431c..e1a0a13 100644
--- a/arch/arm/mach-stm32mp/cpu.c
+++ b/arch/arm/mach-stm32mp/cpu.c
@@ -481,7 +481,7 @@
 		enetaddr[i] = ((uint8_t *)&otp)[i];
 
 	if (!is_valid_ethaddr(enetaddr)) {
-		pr_err("invalid MAC address in OTP %pM", enetaddr);
+		pr_err("invalid MAC address in OTP %pM\n", enetaddr);
 		return -EINVAL;
 	}
 	pr_debug("OTP MAC address = %pM\n", enetaddr);
diff --git a/board/st/stm32mp1/README b/board/st/stm32mp1/README
index 1cd3534..b0c8325 100644
--- a/board/st/stm32mp1/README
+++ b/board/st/stm32mp1/README
@@ -37,6 +37,7 @@
 + stm32mp157c-ed1
 + stm32mp157a-dk1
 + stm32mp157c-dk2
++ stm32mp157a-avenger96
 
 3. Boot Sequences
 =================
@@ -84,6 +85,9 @@
 + dk2: Discovery board = dk1 with a BT/WiFI combo and a DSI panel
   dts: stm32mp157c-dk2
 
++ avenger96: Avenger96 board from Arrow Electronics
+  dts: stm32mp157a-avenger96
+
 5. Build Procedure
 ==================
 
@@ -140,6 +144,11 @@
 	# make stm32mp15_basic_defconfig
 	# make DEVICE_TREE=stm32mp157c-dk2 all
 
+  d) basic boot on avenger96
+	# export KBUILD_OUTPUT=stm32mp15_basic
+	# make stm32mp15_basic_defconfig
+	# make DEVICE_TREE=stm32mp157a-avenger96 all
+
 6. Output files
 
   BootRom and TF-A expect binaries with STM32 image header
@@ -182,6 +191,20 @@
   SD-Card	1      1
   Recovery	0      0
 
+- Boot mode of Avenger96 can be selected using switch S3
+
+ -----------------------------------
+  Boot Mode   BOOT2   BOOT1   BOOT0
+ -----------------------------------
+  Recovery	0	0	0
+  NOR		0	0	1
+  SD-Card	1	0	1
+  eMMC		0	1	0
+  NAND		0	1	1
+  Reserved	1	0	0
+  Recovery	1	1	0
+  SD-Card	1	1	1
+
 Recovery is a boot from serial link (UART/USB) and it is used with
 STM32CubeProgrammer tool to load executable in RAM and to update the flash
 devices available on the board (NOR/NAND/eMMC/SDCARD).
diff --git a/board/st/stm32mp1/stm32mp1.c b/board/st/stm32mp1/stm32mp1.c
index 76917b0..7769293 100644
--- a/board/st/stm32mp1/stm32mp1.c
+++ b/board/st/stm32mp1/stm32mp1.c
@@ -7,6 +7,7 @@
 #include <config.h>
 #include <clk.h>
 #include <dm.h>
+#include <environment.h>
 #include <g_dnl.h>
 #include <generic-phy.h>
 #include <i2c.h>
@@ -19,6 +20,7 @@
 #include <asm/io.h>
 #include <asm/gpio.h>
 #include <asm/arch/stm32.h>
+#include <asm/arch/sys_proto.h>
 #include <power/regulator.h>
 #include <usb/dwc2_udc.h>
 
@@ -51,18 +53,19 @@
 #define SYSCFG_PMCSETR_ETH_SELMII	BIT(20)
 
 #define SYSCFG_PMCSETR_ETH_SEL_MASK	GENMASK(23, 21)
-#define SYSCFG_PMCSETR_ETH_SEL_GMII_MII	(0 << 21)
-#define SYSCFG_PMCSETR_ETH_SEL_RGMII	(1 << 21)
-#define SYSCFG_PMCSETR_ETH_SEL_RMII	(4 << 21)
+#define SYSCFG_PMCSETR_ETH_SEL_GMII_MII	0
+#define SYSCFG_PMCSETR_ETH_SEL_RGMII	BIT(21)
+#define SYSCFG_PMCSETR_ETH_SEL_RMII	BIT(23)
 
 /*
  * Get a global data pointer
  */
 DECLARE_GLOBAL_DATA_PTR;
 
+#define USB_LOW_THRESHOLD_UV		200000
 #define USB_WARNING_LOW_THRESHOLD_UV	660000
 #define USB_START_LOW_THRESHOLD_UV	1230000
-#define USB_START_HIGH_THRESHOLD_UV	2100000
+#define USB_START_HIGH_THRESHOLD_UV	2150000
 
 int checkboard(void)
 {
@@ -263,9 +266,10 @@
 	ofnode node;
 	unsigned int raw;
 	int max_uV = 0;
+	int min_uV = USB_START_HIGH_THRESHOLD_UV;
 	int ret, uV, adc_count;
-	u8 i, nb_blink;
-
+	u32 nb_blink;
+	u8 i;
 	node = ofnode_path("/config");
 	if (!ofnode_valid(node)) {
 		debug("%s: no /config node?\n", __func__);
@@ -317,6 +321,8 @@
 		if (!adc_raw_to_uV(adc, raw, &uV)) {
 			if (uV > max_uV)
 				max_uV = uV;
+			if (uV < min_uV)
+				min_uV = uV;
 			pr_debug("%s: %s[%02d] = %u, %d uV\n", __func__,
 				 adc->name, adc_args.args[0], raw, uV);
 		} else {
@@ -331,27 +337,66 @@
 	 * continue.
 	 */
 	if (max_uV > USB_START_LOW_THRESHOLD_UV &&
-	    max_uV < USB_START_HIGH_THRESHOLD_UV)
+	    max_uV <= USB_START_HIGH_THRESHOLD_UV &&
+	    min_uV <= USB_LOW_THRESHOLD_UV)
 		return 0;
 
-	/* Display warning message and make u-boot,error-led blinking */
-	pr_err("\n*******************************************\n");
+	pr_err("****************************************************\n");
+
+	/*
+	 * If highest and lowest value are either both below
+	 * USB_LOW_THRESHOLD_UV or both above USB_LOW_THRESHOLD_UV, that
+	 * means USB TYPE-C is in unattached mode, this is an issue, make
+	 * u-boot,error-led blinking and stop boot process.
+	 */
+	if ((max_uV > USB_LOW_THRESHOLD_UV &&
+	     min_uV > USB_LOW_THRESHOLD_UV) ||
+	     (max_uV <= USB_LOW_THRESHOLD_UV &&
+	     min_uV <= USB_LOW_THRESHOLD_UV)) {
+		pr_err("* ERROR USB TYPE-C connection in unattached mode   *\n");
+		pr_err("* Check that USB TYPE-C cable is correctly plugged *\n");
+		/* with 125ms interval, led will blink for 17.02 years ....*/
+		nb_blink = U32_MAX;
+	}
 
-	if (max_uV < USB_WARNING_LOW_THRESHOLD_UV) {
-		pr_err("*   WARNING 500mA power supply detected   *\n");
+	if (max_uV > USB_LOW_THRESHOLD_UV &&
+	    max_uV <= USB_WARNING_LOW_THRESHOLD_UV &&
+	    min_uV <= USB_LOW_THRESHOLD_UV) {
+		pr_err("*        WARNING 500mA power supply detected       *\n");
 		nb_blink = 2;
-	} else {
-		pr_err("* WARNING 1.5A power supply detected      *\n");
+	}
+
+	if (max_uV > USB_WARNING_LOW_THRESHOLD_UV &&
+	    max_uV <= USB_START_LOW_THRESHOLD_UV &&
+	    min_uV <= USB_LOW_THRESHOLD_UV) {
+		pr_err("*       WARNING 1.5mA power supply detected        *\n");
 		nb_blink = 3;
 	}
 
-	pr_err("* Current too low, use a 3A power supply! *\n");
-	pr_err("*******************************************\n\n");
+	/*
+	 * If highest value is above 2.15 Volts that means that the USB TypeC
+	 * supplies more than 3 Amp, this is not compliant with TypeC specification
+	 */
+	if (max_uV > USB_START_HIGH_THRESHOLD_UV) {
+		pr_err("*      USB TYPE-C charger not compliant with       *\n");
+		pr_err("*                   specification                  *\n");
+		pr_err("****************************************************\n\n");
+		/* with 125ms interval, led will blink for 17.02 years ....*/
+		nb_blink = U32_MAX;
+	} else {
+		pr_err("*     Current too low, use a 3A power supply!      *\n");
+		pr_err("****************************************************\n\n");
+	}
 
 	ret = get_led(&led, "u-boot,error-led");
-	if (ret)
+	if (ret) {
+		/* in unattached case, the boot process must be stopped */
+		if (nb_blink == U32_MAX)
+			hang();
 		return ret;
+	}
 
+	/* make u-boot,error-led blinking */
 	for (i = 0; i < nb_blink * 2; i++) {
 		led_set_state(led, LEDST_TOGGLE);
 		mdelay(125);
@@ -504,3 +549,199 @@
 {
 	setup_led(LEDST_OFF);
 }
+
+/* board interface eth init */
+/* this is a weak define that we are overriding */
+int board_interface_eth_init(phy_interface_t interface_type,
+			     bool eth_clk_sel_reg, bool eth_ref_clk_sel_reg)
+{
+	u8 *syscfg;
+	u32 value;
+
+	syscfg = (u8 *)syscon_get_first_range(STM32MP_SYSCON_SYSCFG);
+
+	if (!syscfg)
+		return -ENODEV;
+
+	switch (interface_type) {
+	case PHY_INTERFACE_MODE_MII:
+		value = SYSCFG_PMCSETR_ETH_SEL_GMII_MII |
+			SYSCFG_PMCSETR_ETH_REF_CLK_SEL;
+		debug("%s: PHY_INTERFACE_MODE_MII\n", __func__);
+		break;
+	case PHY_INTERFACE_MODE_GMII:
+		if (eth_clk_sel_reg)
+			value = SYSCFG_PMCSETR_ETH_SEL_GMII_MII |
+				SYSCFG_PMCSETR_ETH_CLK_SEL;
+		else
+			value = SYSCFG_PMCSETR_ETH_SEL_GMII_MII;
+		debug("%s: PHY_INTERFACE_MODE_GMII\n", __func__);
+		break;
+	case PHY_INTERFACE_MODE_RMII:
+		if (eth_ref_clk_sel_reg)
+			value = SYSCFG_PMCSETR_ETH_SEL_RMII |
+				SYSCFG_PMCSETR_ETH_REF_CLK_SEL;
+		else
+			value = SYSCFG_PMCSETR_ETH_SEL_RMII;
+		debug("%s: PHY_INTERFACE_MODE_RMII\n", __func__);
+		break;
+	case PHY_INTERFACE_MODE_RGMII:
+	case PHY_INTERFACE_MODE_RGMII_ID:
+	case PHY_INTERFACE_MODE_RGMII_RXID:
+	case PHY_INTERFACE_MODE_RGMII_TXID:
+		if (eth_clk_sel_reg)
+			value = SYSCFG_PMCSETR_ETH_SEL_RGMII |
+				SYSCFG_PMCSETR_ETH_CLK_SEL;
+		else
+			value = SYSCFG_PMCSETR_ETH_SEL_RGMII;
+		debug("%s: PHY_INTERFACE_MODE_RGMII\n", __func__);
+		break;
+	default:
+		debug("%s: Do not manage %d interface\n",
+		      __func__, interface_type);
+		/* Do not manage others interfaces */
+		return -EINVAL;
+	}
+
+	/* clear and set ETH configuration bits */
+	writel(SYSCFG_PMCSETR_ETH_SEL_MASK | SYSCFG_PMCSETR_ETH_SELMII |
+	       SYSCFG_PMCSETR_ETH_REF_CLK_SEL | SYSCFG_PMCSETR_ETH_CLK_SEL,
+	       syscfg + SYSCFG_PMCCLRR);
+	writel(value, syscfg + SYSCFG_PMCSETR);
+
+	return 0;
+}
+
+enum env_location env_get_location(enum env_operation op, int prio)
+{
+	u32 bootmode = get_bootmode();
+
+	if (prio)
+		return ENVL_UNKNOWN;
+
+	switch (bootmode & TAMP_BOOT_DEVICE_MASK) {
+#ifdef CONFIG_ENV_IS_IN_EXT4
+	case BOOT_FLASH_SD:
+	case BOOT_FLASH_EMMC:
+		return ENVL_EXT4;
+#endif
+#ifdef CONFIG_ENV_IS_IN_UBI
+	case BOOT_FLASH_NAND:
+		return ENVL_UBI;
+#endif
+#ifdef CONFIG_ENV_IS_IN_SPI_FLASH
+	case BOOT_FLASH_NOR:
+		return ENVL_SPI_FLASH;
+#endif
+	default:
+		return ENVL_NOWHERE;
+	}
+}
+
+#if defined(CONFIG_ENV_IS_IN_EXT4)
+const char *env_ext4_get_intf(void)
+{
+	u32 bootmode = get_bootmode();
+
+	switch (bootmode & TAMP_BOOT_DEVICE_MASK) {
+	case BOOT_FLASH_SD:
+	case BOOT_FLASH_EMMC:
+		return "mmc";
+	default:
+		return "";
+	}
+}
+
+const char *env_ext4_get_dev_part(void)
+{
+	static char *const dev_part[] = {"0:auto", "1:auto", "2:auto"};
+	u32 bootmode = get_bootmode();
+
+	return dev_part[(bootmode & TAMP_BOOT_INSTANCE_MASK) - 1];
+}
+#endif
+
+#ifdef CONFIG_SYS_MTDPARTS_RUNTIME
+
+#define MTDPARTS_LEN		256
+#define MTDIDS_LEN		128
+
+/**
+ * The mtdparts_nand0 and mtdparts_nor0 variable tends to be long.
+ * If we need to access it before the env is relocated, then we need
+ * to use our own stack buffer. gd->env_buf will be too small.
+ *
+ * @param buf temporary buffer pointer MTDPARTS_LEN long
+ * @return mtdparts variable string, NULL if not found
+ */
+static const char *env_get_mtdparts(const char *str, char *buf)
+{
+	if (gd->flags & GD_FLG_ENV_READY)
+		return env_get(str);
+	if (env_get_f(str, buf, MTDPARTS_LEN) != -1)
+		return buf;
+
+	return NULL;
+}
+
+/**
+ * update the variables "mtdids" and "mtdparts" with content of mtdparts_<dev>
+ */
+static void board_get_mtdparts(const char *dev,
+			       char *mtdids,
+			       char *mtdparts)
+{
+	char env_name[32] = "mtdparts_";
+	char tmp_mtdparts[MTDPARTS_LEN];
+	const char *tmp;
+
+	/* name of env variable to read = mtdparts_<dev> */
+	strcat(env_name, dev);
+	tmp = env_get_mtdparts(env_name, tmp_mtdparts);
+	if (tmp) {
+		/* mtdids: "<dev>=<dev>, ...." */
+		if (mtdids[0] != '\0')
+			strcat(mtdids, ",");
+		strcat(mtdids, dev);
+		strcat(mtdids, "=");
+		strcat(mtdids, dev);
+
+		/* mtdparts: "mtdparts=<dev>:<mtdparts_<dev>>;..." */
+		if (mtdparts[0] != '\0')
+			strncat(mtdparts, ";", MTDPARTS_LEN);
+		else
+			strcat(mtdparts, "mtdparts=");
+		strncat(mtdparts, dev, MTDPARTS_LEN);
+		strncat(mtdparts, ":", MTDPARTS_LEN);
+		strncat(mtdparts, tmp, MTDPARTS_LEN);
+	}
+}
+
+void board_mtdparts_default(const char **mtdids, const char **mtdparts)
+{
+	struct udevice *dev;
+	static char parts[2 * MTDPARTS_LEN + 1];
+	static char ids[MTDIDS_LEN + 1];
+	static bool mtd_initialized;
+
+	if (mtd_initialized) {
+		*mtdids = ids;
+		*mtdparts = parts;
+		return;
+	}
+
+	memset(parts, 0, sizeof(parts));
+	memset(ids, 0, sizeof(ids));
+
+	if (!uclass_get_device(UCLASS_MTD, 0, &dev))
+		board_get_mtdparts("nand0", ids, parts);
+
+	if (!uclass_get_device(UCLASS_SPI_FLASH, 0, &dev))
+		board_get_mtdparts("nor0", ids, parts);
+
+	mtd_initialized = true;
+	*mtdids = ids;
+	*mtdparts = parts;
+	debug("%s:mtdids=%s & mtdparts=%s\n", __func__, ids, parts);
+}
+#endif
diff --git a/cmd/nvedit.c b/cmd/nvedit.c
index 52c242b..49d3b5b 100644
--- a/cmd/nvedit.c
+++ b/cmd/nvedit.c
@@ -39,18 +39,24 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
-#if	!defined(CONFIG_ENV_IS_IN_EEPROM)	&& \
-	!defined(CONFIG_ENV_IS_IN_FLASH)	&& \
-	!defined(CONFIG_ENV_IS_IN_MMC)		&& \
-	!defined(CONFIG_ENV_IS_IN_FAT)		&& \
-	!defined(CONFIG_ENV_IS_IN_EXT4)		&& \
-	!defined(CONFIG_ENV_IS_IN_NAND)		&& \
-	!defined(CONFIG_ENV_IS_IN_NVRAM)	&& \
-	!defined(CONFIG_ENV_IS_IN_ONENAND)	&& \
-	!defined(CONFIG_ENV_IS_IN_SATA)		&& \
-	!defined(CONFIG_ENV_IS_IN_SPI_FLASH)	&& \
-	!defined(CONFIG_ENV_IS_IN_REMOTE)	&& \
-	!defined(CONFIG_ENV_IS_IN_UBI)		&& \
+#if	defined(CONFIG_ENV_IS_IN_EEPROM)	|| \
+	defined(CONFIG_ENV_IS_IN_FLASH)		|| \
+	defined(CONFIG_ENV_IS_IN_MMC)		|| \
+	defined(CONFIG_ENV_IS_IN_FAT)		|| \
+	defined(CONFIG_ENV_IS_IN_EXT4)		|| \
+	defined(CONFIG_ENV_IS_IN_NAND)		|| \
+	defined(CONFIG_ENV_IS_IN_NVRAM)		|| \
+	defined(CONFIG_ENV_IS_IN_ONENAND)	|| \
+	defined(CONFIG_ENV_IS_IN_SATA)		|| \
+	defined(CONFIG_ENV_IS_IN_SPI_FLASH)	|| \
+	defined(CONFIG_ENV_IS_IN_REMOTE)	|| \
+	defined(CONFIG_ENV_IS_IN_UBI)
+
+#define ENV_IS_IN_DEVICE
+
+#endif
+
+#if	!defined(ENV_IS_IN_DEVICE)		&& \
 	!defined(CONFIG_ENV_IS_NOWHERE)
 # error Define one of CONFIG_ENV_IS_IN_{EEPROM|FLASH|MMC|FAT|EXT4|\
 NAND|NVRAM|ONENAND|SATA|SPI_FLASH|REMOTE|UBI} or CONFIG_ENV_IS_NOWHERE
@@ -749,7 +755,7 @@
 }
 
 #ifndef CONFIG_SPL_BUILD
-#if defined(CONFIG_CMD_SAVEENV) && !defined(CONFIG_ENV_IS_NOWHERE)
+#if defined(CONFIG_CMD_SAVEENV) && defined(ENV_IS_IN_DEVICE)
 static int do_env_save(cmd_tbl_t *cmdtp, int flag, int argc,
 		       char * const argv[])
 {
@@ -1205,7 +1211,7 @@
 #if defined(CONFIG_CMD_RUN)
 	U_BOOT_CMD_MKENT(run, CONFIG_SYS_MAXARGS, 1, do_run, "", ""),
 #endif
-#if defined(CONFIG_CMD_SAVEENV) && !defined(CONFIG_ENV_IS_NOWHERE)
+#if defined(CONFIG_CMD_SAVEENV) && defined(ENV_IS_IN_DEVICE)
 	U_BOOT_CMD_MKENT(save, 1, 0, do_env_save, "", ""),
 #endif
 	U_BOOT_CMD_MKENT(set, CONFIG_SYS_MAXARGS, 0, do_env_set, "", ""),
@@ -1280,7 +1286,7 @@
 #if defined(CONFIG_CMD_RUN)
 	"env run var [...] - run commands in an environment variable\n"
 #endif
-#if defined(CONFIG_CMD_SAVEENV) && !defined(CONFIG_ENV_IS_NOWHERE)
+#if defined(CONFIG_CMD_SAVEENV) && defined(ENV_IS_IN_DEVICE)
 	"env save - save environment\n"
 #endif
 #if defined(CONFIG_CMD_NVEDIT_EFI)
diff --git a/configs/stm32mp15_basic_defconfig b/configs/stm32mp15_basic_defconfig
index 0ea9dff..4aa184f 100644
--- a/configs/stm32mp15_basic_defconfig
+++ b/configs/stm32mp15_basic_defconfig
@@ -29,6 +29,8 @@
 CONFIG_CMD_GPT=y
 CONFIG_CMD_I2C=y
 CONFIG_CMD_MMC=y
+CONFIG_CMD_SF=y
+CONFIG_CMD_SPI=y
 CONFIG_CMD_USB=y
 CONFIG_CMD_USB_MASS_STORAGE=y
 CONFIG_CMD_CACHE=y
@@ -37,8 +39,19 @@
 CONFIG_CMD_PMIC=y
 CONFIG_CMD_REGULATOR=y
 CONFIG_CMD_EXT4_WRITE=y
+CONFIG_CMD_MTDPARTS=y
+CONFIG_CMD_UBI=y
 # CONFIG_SPL_DOS_PARTITION is not set
 CONFIG_DEFAULT_DEVICE_TREE="stm32mp157c-ev1"
+CONFIG_ENV_IS_NOWHERE=y
+CONFIG_ENV_IS_IN_EXT4=y
+CONFIG_ENV_IS_IN_SPI_FLASH=y
+CONFIG_ENV_IS_IN_UBI=y
+CONFIG_ENV_EXT4_INTERFACE="mmc"
+CONFIG_ENV_EXT4_DEVICE_AND_PART="0:auto"
+CONFIG_ENV_EXT4_FILE="/uboot.env"
+CONFIG_ENV_UBI_PART="UBI"
+CONFIG_ENV_UBI_VOLUME="uboot_config"
 CONFIG_STM32_ADC=y
 CONFIG_USB_FUNCTION_FASTBOOT=y
 CONFIG_FASTBOOT_BUF_ADDR=0xC0000000
@@ -55,6 +68,20 @@
 CONFIG_DM_MMC=y
 CONFIG_SUPPORT_EMMC_BOOT=y
 CONFIG_STM32_SDMMC2=y
+CONFIG_MTD=y
+CONFIG_NAND=y
+CONFIG_NAND_STM32_FMC2=y
+CONFIG_DM_SPI_FLASH=y
+CONFIG_SPI_FLASH=y
+CONFIG_SPI_FLASH_BAR=y
+CONFIG_SPI_FLASH_MACRONIX=y
+CONFIG_SPI_FLASH_SPANSION=y
+CONFIG_SPI_FLASH_STMICRO=y
+CONFIG_SPI_FLASH_WINBOND=y
+# CONFIG_SPI_FLASH_USE_4K_SECTORS is not set
+CONFIG_SPI_FLASH_MTD=y
+CONFIG_DM_ETH=y
+CONFIG_DWC_ETH_QOS=y
 CONFIG_PHY=y
 CONFIG_PHY_STM32_USBPHYC=y
 CONFIG_PINCONF=y
@@ -69,6 +96,10 @@
 CONFIG_DM_REGULATOR_STPMIC1=y
 CONFIG_SERIAL_RX_BUFFER=y
 CONFIG_STM32_SERIAL=y
+CONFIG_SPI=y
+CONFIG_DM_SPI=y
+CONFIG_STM32_QSPI=y
+CONFIG_STM32_SPI=y
 CONFIG_USB=y
 CONFIG_DM_USB=y
 CONFIG_DM_USB_GADGET=y
@@ -79,3 +110,5 @@
 CONFIG_USB_GADGET_VENDOR_NUM=0x0483
 CONFIG_USB_GADGET_PRODUCT_NUM=0x5720
 CONFIG_USB_GADGET_DWC2_OTG=y
+CONFIG_WDT=y
+CONFIG_WDT_STM32MP=y
diff --git a/configs/stm32mp15_trusted_defconfig b/configs/stm32mp15_trusted_defconfig
index 3c2bb75..66361c8 100644
--- a/configs/stm32mp15_trusted_defconfig
+++ b/configs/stm32mp15_trusted_defconfig
@@ -22,6 +22,8 @@
 CONFIG_CMD_GPT=y
 CONFIG_CMD_I2C=y
 CONFIG_CMD_MMC=y
+CONFIG_CMD_SF=y
+CONFIG_CMD_SPI=y
 CONFIG_CMD_USB=y
 CONFIG_CMD_USB_MASS_STORAGE=y
 CONFIG_CMD_CACHE=y
@@ -30,7 +32,18 @@
 CONFIG_CMD_PMIC=y
 CONFIG_CMD_REGULATOR=y
 CONFIG_CMD_EXT4_WRITE=y
+CONFIG_CMD_MTDPARTS=y
+CONFIG_CMD_UBI=y
 CONFIG_DEFAULT_DEVICE_TREE="stm32mp157c-ev1"
+CONFIG_ENV_IS_NOWHERE=y
+CONFIG_ENV_IS_IN_EXT4=y
+CONFIG_ENV_IS_IN_SPI_FLASH=y
+CONFIG_ENV_IS_IN_UBI=y
+CONFIG_ENV_EXT4_INTERFACE="mmc"
+CONFIG_ENV_EXT4_DEVICE_AND_PART="0:auto"
+CONFIG_ENV_EXT4_FILE="/uboot.env"
+CONFIG_ENV_UBI_PART="UBI"
+CONFIG_ENV_UBI_VOLUME="uboot_config"
 CONFIG_STM32_ADC=y
 CONFIG_USB_FUNCTION_FASTBOOT=y
 CONFIG_FASTBOOT_BUF_ADDR=0xC0000000
@@ -47,6 +60,20 @@
 CONFIG_DM_MMC=y
 CONFIG_SUPPORT_EMMC_BOOT=y
 CONFIG_STM32_SDMMC2=y
+CONFIG_MTD=y
+CONFIG_NAND=y
+CONFIG_NAND_STM32_FMC2=y
+CONFIG_DM_SPI_FLASH=y
+CONFIG_SPI_FLASH=y
+CONFIG_SPI_FLASH_BAR=y
+CONFIG_SPI_FLASH_MACRONIX=y
+CONFIG_SPI_FLASH_SPANSION=y
+CONFIG_SPI_FLASH_STMICRO=y
+CONFIG_SPI_FLASH_WINBOND=y
+# CONFIG_SPI_FLASH_USE_4K_SECTORS is not set
+CONFIG_SPI_FLASH_MTD=y
+CONFIG_DM_ETH=y
+CONFIG_ETH_DESIGNWARE=y
 CONFIG_PHY=y
 CONFIG_PHY_STM32_USBPHYC=y
 CONFIG_PINCONF=y
@@ -59,6 +86,10 @@
 CONFIG_DM_REGULATOR_STPMIC1=y
 CONFIG_SERIAL_RX_BUFFER=y
 CONFIG_STM32_SERIAL=y
+CONFIG_SPI=y
+CONFIG_DM_SPI=y
+CONFIG_STM32_QSPI=y
+CONFIG_STM32_SPI=y
 CONFIG_USB=y
 CONFIG_DM_USB=y
 CONFIG_DM_USB_GADGET=y
@@ -69,3 +100,5 @@
 CONFIG_USB_GADGET_VENDOR_NUM=0x0483
 CONFIG_USB_GADGET_PRODUCT_NUM=0x5720
 CONFIG_USB_GADGET_DWC2_OTG=y
+CONFIG_WDT=y
+CONFIG_WDT_STM32MP=y
diff --git a/drivers/clk/clk_stm32mp1.c b/drivers/clk/clk_stm32mp1.c
index 6272b00..f295e48 100644
--- a/drivers/clk/clk_stm32mp1.c
+++ b/drivers/clk/clk_stm32mp1.c
@@ -90,6 +90,7 @@
 #define RCC_PLL4CSGR		0x8A4
 #define RCC_I2C12CKSELR		0x8C0
 #define RCC_I2C35CKSELR		0x8C4
+#define RCC_SPI2S1CKSELR	0x8D8
 #define RCC_UART6CKSELR		0x8E4
 #define RCC_UART24CKSELR	0x8E8
 #define RCC_UART35CKSELR	0x8EC
@@ -298,6 +299,7 @@
 	_STGEN_SEL,
 	_DSI_SEL,
 	_ADC12_SEL,
+	_SPI1_SEL,
 	_PARENT_SEL_NB,
 	_UNKNOWN_SEL = 0xff,
 };
@@ -519,6 +521,7 @@
 	STM32MP1_CLK_SET_CLR(RCC_MP_APB1ENSETR, 23, I2C3_K, _I2C35_SEL),
 	STM32MP1_CLK_SET_CLR(RCC_MP_APB1ENSETR, 24, I2C5_K, _I2C35_SEL),
 
+	STM32MP1_CLK_SET_CLR(RCC_MP_APB2ENSETR, 8, SPI1_K, _SPI1_SEL),
 	STM32MP1_CLK_SET_CLR(RCC_MP_APB2ENSETR, 13, USART6_K, _UART6_SEL),
 
 	STM32MP1_CLK_SET_CLR_F(RCC_MP_APB3ENSETR, 13, VREF, _PCLK3),
@@ -555,7 +558,7 @@
 
 	STM32MP1_CLK_SET_CLR(RCC_MP_AHB5ENSETR, 0, GPIOZ, _UNKNOWN_SEL),
 
-	STM32MP1_CLK_SET_CLR(RCC_MP_AHB6ENSETR, 7, ETHCK, _ETH_SEL),
+	STM32MP1_CLK_SET_CLR(RCC_MP_AHB6ENSETR, 7, ETHCK_K, _ETH_SEL),
 	STM32MP1_CLK_SET_CLR(RCC_MP_AHB6ENSETR, 8, ETHTX, _UNKNOWN_SEL),
 	STM32MP1_CLK_SET_CLR(RCC_MP_AHB6ENSETR, 9, ETHRX, _UNKNOWN_SEL),
 	STM32MP1_CLK_SET_CLR_F(RCC_MP_AHB6ENSETR, 10, ETHMAC, _ACLK),
@@ -589,6 +592,8 @@
 static const u8 stgen_parents[] = {_HSI_KER, _HSE_KER};
 static const u8 dsi_parents[] = {_DSI_PHY, _PLL4_P};
 static const u8 adc_parents[] = {_PLL4_R, _CK_PER, _PLL3_Q};
+static const u8 spi_parents[] = {_PLL4_P, _PLL3_Q, _I2S_CKIN, _CK_PER,
+				 _PLL3_R};
 
 static const struct stm32mp1_clk_sel stm32mp1_clk_sel[_PARENT_SEL_NB] = {
 	STM32MP1_CLK_PARENT(_I2C12_SEL, RCC_I2C12CKSELR, 0, 0x7, i2c12_parents),
@@ -613,6 +618,7 @@
 	STM32MP1_CLK_PARENT(_STGEN_SEL, RCC_STGENCKSELR, 0, 0x3, stgen_parents),
 	STM32MP1_CLK_PARENT(_DSI_SEL, RCC_DSICKSELR, 0, 0x1, dsi_parents),
 	STM32MP1_CLK_PARENT(_ADC12_SEL, RCC_ADCCKSELR, 0, 0x1, adc_parents),
+	STM32MP1_CLK_PARENT(_SPI1_SEL, RCC_SPI2S1CKSELR, 0, 0x7, spi_parents),
 };
 
 #ifdef STM32MP1_CLOCK_TREE_INIT
@@ -727,6 +733,7 @@
 	[_STGEN_SEL] = "STGEN",
 	[_DSI_SEL] = "DSI",
 	[_ADC12_SEL] = "ADC12",
+	[_SPI1_SEL] = "SPI1",
 };
 
 static const struct stm32mp1_clk_data stm32mp1_data = {
diff --git a/drivers/mtd/mtd_uboot.c b/drivers/mtd/mtd_uboot.c
index d638f70..0a41ed4 100644
--- a/drivers/mtd/mtd_uboot.c
+++ b/drivers/mtd/mtd_uboot.c
@@ -122,7 +122,6 @@
 {
 	__maybe_unused const char *mtdids = NULL;
 	static char tmp_parts[MTDPARTS_MAXLEN];
-	static bool use_defaults = true;
 	const char *mtdparts = NULL;
 
 	if (gd->flags & GD_FLG_ENV_READY)
@@ -130,7 +129,7 @@
 	else if (env_get_f("mtdparts", tmp_parts, sizeof(tmp_parts)) != -1)
 		mtdparts = tmp_parts;
 
-	if (mtdparts || !use_defaults)
+	if (mtdparts)
 		return mtdparts;
 
 #if defined(CONFIG_SYS_MTDPARTS_RUNTIME)
@@ -144,8 +143,6 @@
 	if (mtdparts)
 		env_set("mtdparts", mtdparts);
 
-	use_defaults = false;
-
 	return mtdparts;
 }
 
diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c
index 590e756..07b3667 100644
--- a/drivers/net/dwc_eth_qos.c
+++ b/drivers/net/dwc_eth_qos.c
@@ -26,7 +26,6 @@
  *    supports a single RGMII PHY. This configuration also has SW control over
  *    all clock and reset signals to the HW block.
  */
-
 #include <common.h>
 #include <clk.h>
 #include <dm.h>
@@ -95,6 +94,7 @@
 #define EQOS_MAC_RXQ_CTRL0_RXQ0EN_MASK			3
 #define EQOS_MAC_RXQ_CTRL0_RXQ0EN_NOT_ENABLED		0
 #define EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_DCB		2
+#define EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_AV		1
 
 #define EQOS_MAC_RXQ_CTRL2_PSRQ0_SHIFT			0
 #define EQOS_MAC_RXQ_CTRL2_PSRQ0_MASK			0xff
@@ -108,6 +108,7 @@
 #define EQOS_MAC_MDIO_ADDRESS_RDA_SHIFT			16
 #define EQOS_MAC_MDIO_ADDRESS_CR_SHIFT			8
 #define EQOS_MAC_MDIO_ADDRESS_CR_20_35			2
+#define EQOS_MAC_MDIO_ADDRESS_CR_250_300		5
 #define EQOS_MAC_MDIO_ADDRESS_SKAP			BIT(4)
 #define EQOS_MAC_MDIO_ADDRESS_GOC_SHIFT			2
 #define EQOS_MAC_MDIO_ADDRESS_GOC_READ			3
@@ -260,6 +261,29 @@
 
 struct eqos_config {
 	bool reg_access_always_ok;
+	int mdio_wait;
+	int swr_wait;
+	int config_mac;
+	int config_mac_mdio;
+	phy_interface_t (*interface)(struct udevice *dev);
+	struct eqos_ops *ops;
+};
+
+struct eqos_ops {
+	void (*eqos_inval_desc)(void *desc);
+	void (*eqos_flush_desc)(void *desc);
+	void (*eqos_inval_buffer)(void *buf, size_t size);
+	void (*eqos_flush_buffer)(void *buf, size_t size);
+	int (*eqos_probe_resources)(struct udevice *dev);
+	int (*eqos_remove_resources)(struct udevice *dev);
+	int (*eqos_stop_resets)(struct udevice *dev);
+	int (*eqos_start_resets)(struct udevice *dev);
+	void (*eqos_stop_clks)(struct udevice *dev);
+	int (*eqos_start_clks)(struct udevice *dev);
+	int (*eqos_calibrate_pads)(struct udevice *dev);
+	int (*eqos_disable_calibration)(struct udevice *dev);
+	int (*eqos_set_tx_clk_speed)(struct udevice *dev);
+	ulong (*eqos_get_tick_clk_rate)(struct udevice *dev);
 };
 
 struct eqos_priv {
@@ -276,6 +300,7 @@
 	struct clk clk_rx;
 	struct clk clk_ptp_ref;
 	struct clk clk_tx;
+	struct clk clk_ck;
 	struct clk clk_slave_bus;
 	struct mii_dev *mii;
 	struct phy_device *phy;
@@ -327,7 +352,7 @@
 #endif
 }
 
-static void eqos_inval_desc(void *desc)
+static void eqos_inval_desc_tegra186(void *desc)
 {
 #ifndef CONFIG_SYS_NONCACHED_MEMORY
 	unsigned long start = (unsigned long)desc & ~(ARCH_DMA_MINALIGN - 1);
@@ -338,14 +363,36 @@
 #endif
 }
 
-static void eqos_flush_desc(void *desc)
+static void eqos_inval_desc_stm32(void *desc)
 {
 #ifndef CONFIG_SYS_NONCACHED_MEMORY
+	unsigned long start = rounddown((unsigned long)desc, ARCH_DMA_MINALIGN);
+	unsigned long end = roundup((unsigned long)desc + EQOS_DESCRIPTOR_SIZE,
+				    ARCH_DMA_MINALIGN);
+
+	invalidate_dcache_range(start, end);
+#endif
+}
+
+static void eqos_flush_desc_tegra186(void *desc)
+{
+#ifndef CONFIG_SYS_NONCACHED_MEMORY
 	flush_cache((unsigned long)desc, EQOS_DESCRIPTOR_SIZE);
 #endif
 }
 
-static void eqos_inval_buffer(void *buf, size_t size)
+static void eqos_flush_desc_stm32(void *desc)
+{
+#ifndef CONFIG_SYS_NONCACHED_MEMORY
+	unsigned long start = rounddown((unsigned long)desc, ARCH_DMA_MINALIGN);
+	unsigned long end = roundup((unsigned long)desc + EQOS_DESCRIPTOR_SIZE,
+				    ARCH_DMA_MINALIGN);
+
+	flush_dcache_range(start, end);
+#endif
+}
+
+static void eqos_inval_buffer_tegra186(void *buf, size_t size)
 {
 	unsigned long start = (unsigned long)buf & ~(ARCH_DMA_MINALIGN - 1);
 	unsigned long end = ALIGN(start + size, ARCH_DMA_MINALIGN);
@@ -353,11 +400,29 @@
 	invalidate_dcache_range(start, end);
 }
 
+static void eqos_inval_buffer_stm32(void *buf, size_t size)
+{
+	unsigned long start = rounddown((unsigned long)buf, ARCH_DMA_MINALIGN);
+	unsigned long end = roundup((unsigned long)buf + size,
+				    ARCH_DMA_MINALIGN);
+
+	invalidate_dcache_range(start, end);
+}
+
-static void eqos_flush_buffer(void *buf, size_t size)
+static void eqos_flush_buffer_tegra186(void *buf, size_t size)
 {
 	flush_cache((unsigned long)buf, size);
 }
 
+static void eqos_flush_buffer_stm32(void *buf, size_t size)
+{
+	unsigned long start = rounddown((unsigned long)buf, ARCH_DMA_MINALIGN);
+	unsigned long end = roundup((unsigned long)buf + size,
+				    ARCH_DMA_MINALIGN);
+
+	flush_dcache_range(start, end);
+}
+
 static int eqos_mdio_wait_idle(struct eqos_priv *eqos)
 {
 	return wait_for_bit_le32(&eqos->mac_regs->mdio_address,
@@ -386,14 +451,14 @@
 		EQOS_MAC_MDIO_ADDRESS_C45E;
 	val |= (mdio_addr << EQOS_MAC_MDIO_ADDRESS_PA_SHIFT) |
 		(mdio_reg << EQOS_MAC_MDIO_ADDRESS_RDA_SHIFT) |
-		(EQOS_MAC_MDIO_ADDRESS_CR_20_35 <<
+		(eqos->config->config_mac_mdio <<
 		 EQOS_MAC_MDIO_ADDRESS_CR_SHIFT) |
 		(EQOS_MAC_MDIO_ADDRESS_GOC_READ <<
 		 EQOS_MAC_MDIO_ADDRESS_GOC_SHIFT) |
 		EQOS_MAC_MDIO_ADDRESS_GB;
 	writel(val, &eqos->mac_regs->mdio_address);
 
-	udelay(10);
+	udelay(eqos->config->mdio_wait);
 
 	ret = eqos_mdio_wait_idle(eqos);
 	if (ret) {
@@ -432,14 +497,14 @@
 		EQOS_MAC_MDIO_ADDRESS_C45E;
 	val |= (mdio_addr << EQOS_MAC_MDIO_ADDRESS_PA_SHIFT) |
 		(mdio_reg << EQOS_MAC_MDIO_ADDRESS_RDA_SHIFT) |
-		(EQOS_MAC_MDIO_ADDRESS_CR_20_35 <<
+		(eqos->config->config_mac_mdio <<
 		 EQOS_MAC_MDIO_ADDRESS_CR_SHIFT) |
 		(EQOS_MAC_MDIO_ADDRESS_GOC_WRITE <<
 		 EQOS_MAC_MDIO_ADDRESS_GOC_SHIFT) |
 		EQOS_MAC_MDIO_ADDRESS_GB;
 	writel(val, &eqos->mac_regs->mdio_address);
 
-	udelay(10);
+	udelay(eqos->config->mdio_wait);
 
 	ret = eqos_mdio_wait_idle(eqos);
 	if (ret) {
@@ -509,6 +574,53 @@
 	return ret;
 }
 
+static int eqos_start_clks_stm32(struct udevice *dev)
+{
+	struct eqos_priv *eqos = dev_get_priv(dev);
+	int ret;
+
+	debug("%s(dev=%p):\n", __func__, dev);
+
+	ret = clk_enable(&eqos->clk_master_bus);
+	if (ret < 0) {
+		pr_err("clk_enable(clk_master_bus) failed: %d", ret);
+		goto err;
+	}
+
+	ret = clk_enable(&eqos->clk_rx);
+	if (ret < 0) {
+		pr_err("clk_enable(clk_rx) failed: %d", ret);
+		goto err_disable_clk_master_bus;
+	}
+
+	ret = clk_enable(&eqos->clk_tx);
+	if (ret < 0) {
+		pr_err("clk_enable(clk_tx) failed: %d", ret);
+		goto err_disable_clk_rx;
+	}
+
+	if (clk_valid(&eqos->clk_ck)) {
+		ret = clk_enable(&eqos->clk_ck);
+		if (ret < 0) {
+			pr_err("clk_enable(clk_ck) failed: %d", ret);
+			goto err_disable_clk_tx;
+		}
+	}
+
+	debug("%s: OK\n", __func__);
+	return 0;
+
+err_disable_clk_tx:
+	clk_disable(&eqos->clk_tx);
+err_disable_clk_rx:
+	clk_disable(&eqos->clk_rx);
+err_disable_clk_master_bus:
+	clk_disable(&eqos->clk_master_bus);
+err:
+	debug("%s: FAILED: %d\n", __func__, ret);
+	return ret;
+}
+
 void eqos_stop_clks_tegra186(struct udevice *dev)
 {
 	struct eqos_priv *eqos = dev_get_priv(dev);
@@ -524,6 +636,21 @@
 	debug("%s: OK\n", __func__);
 }
 
+void eqos_stop_clks_stm32(struct udevice *dev)
+{
+	struct eqos_priv *eqos = dev_get_priv(dev);
+
+	debug("%s(dev=%p):\n", __func__, dev);
+
+	clk_disable(&eqos->clk_tx);
+	clk_disable(&eqos->clk_rx);
+	clk_disable(&eqos->clk_master_bus);
+	if (clk_valid(&eqos->clk_ck))
+		clk_disable(&eqos->clk_ck);
+
+	debug("%s: OK\n", __func__);
+}
+
 static int eqos_start_resets_tegra186(struct udevice *dev)
 {
 	struct eqos_priv *eqos = dev_get_priv(dev);
@@ -563,6 +690,11 @@
 	return 0;
 }
 
+static int eqos_start_resets_stm32(struct udevice *dev)
+{
+	return 0;
+}
+
 static int eqos_stop_resets_tegra186(struct udevice *dev)
 {
 	struct eqos_priv *eqos = dev_get_priv(dev);
@@ -570,6 +702,11 @@
 	reset_assert(&eqos->reset_ctl);
 	dm_gpio_set_value(&eqos->phy_reset_gpio, 1);
 
+	return 0;
+}
+
+static int eqos_stop_resets_stm32(struct udevice *dev)
+{
 	return 0;
 }
 
@@ -632,6 +769,23 @@
 	return clk_get_rate(&eqos->clk_slave_bus);
 }
 
+static ulong eqos_get_tick_clk_rate_stm32(struct udevice *dev)
+{
+	struct eqos_priv *eqos = dev_get_priv(dev);
+
+	return clk_get_rate(&eqos->clk_master_bus);
+}
+
+static int eqos_calibrate_pads_stm32(struct udevice *dev)
+{
+	return 0;
+}
+
+static int eqos_disable_calibration_stm32(struct udevice *dev)
+{
+	return 0;
+}
+
 static int eqos_set_full_duplex(struct udevice *dev)
 {
 	struct eqos_priv *eqos = dev_get_priv(dev);
@@ -726,6 +880,11 @@
 	return 0;
 }
 
+static int eqos_set_tx_clk_speed_stm32(struct udevice *dev)
+{
+	return 0;
+}
+
 static int eqos_adjust_link(struct udevice *dev)
 {
 	struct eqos_priv *eqos = dev_get_priv(dev);
@@ -766,23 +925,23 @@
 	}
 
 	if (en_calibration) {
-		ret = eqos_calibrate_pads_tegra186(dev);
+		ret = eqos->config->ops->eqos_calibrate_pads(dev);
 		if (ret < 0) {
-			pr_err("eqos_calibrate_pads_tegra186() failed: %d", ret);
+			pr_err("eqos_calibrate_pads() failed: %d",
+			       ret);
 			return ret;
 		}
 	} else {
-		ret = eqos_disable_calibration_tegra186(dev);
+		ret = eqos->config->ops->eqos_disable_calibration(dev);
 		if (ret < 0) {
-			pr_err("eqos_disable_calibration_tegra186() failed: %d",
-			      ret);
+			pr_err("eqos_disable_calibration() failed: %d",
+			       ret);
 			return ret;
 		}
 	}
-
-	ret = eqos_set_tx_clk_speed_tegra186(dev);
+	ret = eqos->config->ops->eqos_set_tx_clk_speed(dev);
 	if (ret < 0) {
-		pr_err("eqos_set_tx_clk_speed_tegra186() failed: %d", ret);
+		pr_err("eqos_set_tx_clk_speed() failed: %d", ret);
 		return ret;
 	}
 
@@ -846,15 +1005,15 @@
 	eqos->tx_desc_idx = 0;
 	eqos->rx_desc_idx = 0;
 
-	ret = eqos_start_clks_tegra186(dev);
+	ret = eqos->config->ops->eqos_start_clks(dev);
 	if (ret < 0) {
-		pr_err("eqos_start_clks_tegra186() failed: %d", ret);
+		pr_err("eqos_start_clks() failed: %d", ret);
 		goto err;
 	}
 
-	ret = eqos_start_resets_tegra186(dev);
+	ret = eqos->config->ops->eqos_start_resets(dev);
 	if (ret < 0) {
-		pr_err("eqos_start_resets_tegra186() failed: %d", ret);
+		pr_err("eqos_start_resets() failed: %d", ret);
 		goto err_stop_clks;
 	}
 
@@ -863,32 +1022,41 @@
 	eqos->reg_access_ok = true;
 
 	ret = wait_for_bit_le32(&eqos->dma_regs->mode,
-				EQOS_DMA_MODE_SWR, false, 10, false);
+				EQOS_DMA_MODE_SWR, false,
+				eqos->config->swr_wait, false);
 	if (ret) {
 		pr_err("EQOS_DMA_MODE_SWR stuck");
 		goto err_stop_resets;
 	}
 
-	ret = eqos_calibrate_pads_tegra186(dev);
+	ret = eqos->config->ops->eqos_calibrate_pads(dev);
 	if (ret < 0) {
-		pr_err("eqos_calibrate_pads_tegra186() failed: %d", ret);
+		pr_err("eqos_calibrate_pads() failed: %d", ret);
 		goto err_stop_resets;
 	}
+	rate = eqos->config->ops->eqos_get_tick_clk_rate(dev);
 
-	rate = eqos_get_tick_clk_rate_tegra186(dev);
 	val = (rate / 1000000) - 1;
 	writel(val, &eqos->mac_regs->us_tic_counter);
 
-	eqos->phy = phy_connect(eqos->mii, 0, dev, 0);
+	/*
+	 * if PHY was already connected and configured,
+	 * don't need to reconnect/reconfigure again
+	 */
 	if (!eqos->phy) {
-		pr_err("phy_connect() failed");
-		goto err_stop_resets;
-	}
-	ret = phy_config(eqos->phy);
-	if (ret < 0) {
-		pr_err("phy_config() failed: %d", ret);
-		goto err_shutdown_phy;
+		eqos->phy = phy_connect(eqos->mii, 0, dev,
+					eqos->config->interface(dev));
+		if (!eqos->phy) {
+			pr_err("phy_connect() failed");
+			goto err_stop_resets;
+		}
+		ret = phy_config(eqos->phy);
+		if (ret < 0) {
+			pr_err("phy_config() failed: %d", ret);
+			goto err_shutdown_phy;
+		}
 	}
+
 	ret = phy_startup(eqos->phy);
 	if (ret < 0) {
 		pr_err("phy_startup() failed: %d", ret);
@@ -993,7 +1161,7 @@
 	clrsetbits_le32(&eqos->mac_regs->rxq_ctrl0,
 			EQOS_MAC_RXQ_CTRL0_RXQ0EN_MASK <<
 			EQOS_MAC_RXQ_CTRL0_RXQ0EN_SHIFT,
-			EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_DCB <<
+			eqos->config->config_mac <<
 			EQOS_MAC_RXQ_CTRL0_RXQ0EN_SHIFT);
 
 	/* Set TX flow control parameters */
@@ -1074,7 +1242,7 @@
 					     (i * EQOS_MAX_PACKET_SIZE));
 		rx_desc->des3 |= EQOS_DESC3_OWN | EQOS_DESC3_BUF1V;
 	}
-	flush_cache((unsigned long)eqos->descs, EQOS_DESCRIPTORS_SIZE);
+	eqos->config->ops->eqos_flush_desc(eqos->descs);
 
 	writel(0, &eqos->dma_regs->ch0_txdesc_list_haddress);
 	writel((ulong)eqos->tx_descs, &eqos->dma_regs->ch0_txdesc_list_address);
@@ -1113,11 +1281,10 @@
 
 err_shutdown_phy:
 	phy_shutdown(eqos->phy);
-	eqos->phy = NULL;
 err_stop_resets:
-	eqos_stop_resets_tegra186(dev);
+	eqos->config->ops->eqos_stop_resets(dev);
 err_stop_clks:
-	eqos_stop_clks_tegra186(dev);
+	eqos->config->ops->eqos_stop_clks(dev);
 err:
 	pr_err("FAILED: %d", ret);
 	return ret;
@@ -1170,10 +1337,9 @@
 
 	if (eqos->phy) {
 		phy_shutdown(eqos->phy);
-		eqos->phy = NULL;
 	}
-	eqos_stop_resets_tegra186(dev);
-	eqos_stop_clks_tegra186(dev);
+	eqos->config->ops->eqos_stop_resets(dev);
+	eqos->config->ops->eqos_stop_clks(dev);
 
 	debug("%s: OK\n", __func__);
 }
@@ -1188,7 +1354,7 @@
 	      length);
 
 	memcpy(eqos->tx_dma_buf, packet, length);
-	eqos_flush_buffer(eqos->tx_dma_buf, length);
+	eqos->config->ops->eqos_flush_buffer(eqos->tx_dma_buf, length);
 
 	tx_desc = &(eqos->tx_descs[eqos->tx_desc_idx]);
 	eqos->tx_desc_idx++;
@@ -1203,12 +1369,12 @@
 	 */
 	mb();
 	tx_desc->des3 = EQOS_DESC3_OWN | EQOS_DESC3_FD | EQOS_DESC3_LD | length;
-	eqos_flush_desc(tx_desc);
+	eqos->config->ops->eqos_flush_desc(tx_desc);
 
 	writel((ulong)(tx_desc + 1), &eqos->dma_regs->ch0_txdesc_tail_pointer);
 
 	for (i = 0; i < 1000000; i++) {
-		eqos_inval_desc(tx_desc);
+		eqos->config->ops->eqos_inval_desc(tx_desc);
 		if (!(readl(&tx_desc->des3) & EQOS_DESC3_OWN))
 			return 0;
 		udelay(1);
@@ -1238,7 +1404,7 @@
 	length = rx_desc->des3 & 0x7fff;
 	debug("%s: *packetp=%p, length=%d\n", __func__, *packetp, length);
 
-	eqos_inval_buffer(*packetp, length);
+	eqos->config->ops->eqos_inval_buffer(*packetp, length);
 
 	return length;
 }
@@ -1269,7 +1435,7 @@
 	 */
 	mb();
 	rx_desc->des3 |= EQOS_DESC3_OWN | EQOS_DESC3_BUF1V;
-	eqos_flush_desc(rx_desc);
+	eqos->config->ops->eqos_flush_desc(rx_desc);
 
 	writel((ulong)rx_desc, &eqos->dma_regs->ch0_rxdesc_tail_pointer);
 
@@ -1304,7 +1470,7 @@
 		ret = -ENOMEM;
 		goto err_free_descs;
 	}
-	debug("%s: rx_dma_buf=%p\n", __func__, eqos->rx_dma_buf);
+	debug("%s: tx_dma_buf=%p\n", __func__, eqos->tx_dma_buf);
 
 	eqos->rx_dma_buf = memalign(EQOS_BUFFER_ALIGN, EQOS_RX_BUFFER_SIZE);
 	if (!eqos->rx_dma_buf) {
@@ -1312,7 +1478,7 @@
 		ret = -ENOMEM;
 		goto err_free_tx_dma_buf;
 	}
-	debug("%s: tx_dma_buf=%p\n", __func__, eqos->tx_dma_buf);
+	debug("%s: rx_dma_buf=%p\n", __func__, eqos->rx_dma_buf);
 
 	eqos->rx_pkt = malloc(EQOS_MAX_PACKET_SIZE);
 	if (!eqos->rx_pkt) {
@@ -1424,6 +1590,98 @@
 	return ret;
 }
 
+/* board-specific Ethernet Interface initializations. */
+__weak int board_interface_eth_init(int interface_type, bool eth_clk_sel_reg,
+				    bool eth_ref_clk_sel_reg)
+{
+	return 0;
+}
+
+static int eqos_probe_resources_stm32(struct udevice *dev)
+{
+	struct eqos_priv *eqos = dev_get_priv(dev);
+	int ret;
+	phy_interface_t interface;
+	bool eth_clk_sel_reg = false;
+	bool eth_ref_clk_sel_reg = false;
+
+	debug("%s(dev=%p):\n", __func__, dev);
+
+	interface = eqos->config->interface(dev);
+
+	if (interface == PHY_INTERFACE_MODE_NONE) {
+		pr_err("Invalid PHY interface\n");
+		return -EINVAL;
+	}
+
+	/* Gigabit Ethernet 125MHz clock selection. */
+	eth_clk_sel_reg = dev_read_bool(dev, "st,eth_clk_sel");
+
+	/* Ethernet 50Mhz RMII clock selection */
+	eth_ref_clk_sel_reg =
+		dev_read_bool(dev, "st,eth_ref_clk_sel");
+
+	ret = board_interface_eth_init(interface, eth_clk_sel_reg,
+				       eth_ref_clk_sel_reg);
+	if (ret)
+		return -EINVAL;
+
+	ret = clk_get_by_name(dev, "stmmaceth", &eqos->clk_master_bus);
+	if (ret) {
+		pr_err("clk_get_by_name(master_bus) failed: %d", ret);
+		goto err_probe;
+	}
+
+	ret = clk_get_by_name(dev, "mac-clk-rx", &eqos->clk_rx);
+	if (ret) {
+		pr_err("clk_get_by_name(rx) failed: %d", ret);
+		goto err_free_clk_master_bus;
+	}
+
+	ret = clk_get_by_name(dev, "mac-clk-tx", &eqos->clk_tx);
+	if (ret) {
+		pr_err("clk_get_by_name(tx) failed: %d", ret);
+		goto err_free_clk_rx;
+	}
+
+	/*  Get ETH_CLK clocks (optional) */
+	ret = clk_get_by_name(dev, "eth-ck", &eqos->clk_ck);
+	if (ret)
+		pr_warn("No phy clock provided %d", ret);
+
+	debug("%s: OK\n", __func__);
+	return 0;
+
+err_free_clk_rx:
+	clk_free(&eqos->clk_rx);
+err_free_clk_master_bus:
+	clk_free(&eqos->clk_master_bus);
+err_probe:
+
+	debug("%s: returns %d\n", __func__, ret);
+	return ret;
+}
+
+static phy_interface_t eqos_get_interface_stm32(struct udevice *dev)
+{
+	const char *phy_mode;
+	phy_interface_t interface = PHY_INTERFACE_MODE_NONE;
+
+	debug("%s(dev=%p):\n", __func__, dev);
+
+	phy_mode = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "phy-mode",
+			       NULL);
+	if (phy_mode)
+		interface = phy_get_interface_by_name(phy_mode);
+
+	return interface;
+}
+
+static phy_interface_t eqos_get_interface_tegra186(struct udevice *dev)
+{
+	return PHY_INTERFACE_MODE_MII;
+}
+
 static int eqos_remove_resources_tegra186(struct udevice *dev)
 {
 	struct eqos_priv *eqos = dev_get_priv(dev);
@@ -1442,6 +1700,22 @@
 	return 0;
 }
 
+static int eqos_remove_resources_stm32(struct udevice *dev)
+{
+	struct eqos_priv *eqos = dev_get_priv(dev);
+
+	debug("%s(dev=%p):\n", __func__, dev);
+
+	clk_free(&eqos->clk_tx);
+	clk_free(&eqos->clk_rx);
+	clk_free(&eqos->clk_master_bus);
+	if (clk_valid(&eqos->clk_ck))
+		clk_free(&eqos->clk_ck);
+
+	debug("%s: OK\n", __func__);
+	return 0;
+}
+
 static int eqos_probe(struct udevice *dev)
 {
 	struct eqos_priv *eqos = dev_get_priv(dev);
@@ -1468,15 +1742,16 @@
 		return ret;
 	}
 
-	ret = eqos_probe_resources_tegra186(dev);
+	ret = eqos->config->ops->eqos_probe_resources(dev);
 	if (ret < 0) {
-		pr_err("eqos_probe_resources_tegra186() failed: %d", ret);
+		pr_err("eqos_probe_resources() failed: %d", ret);
 		goto err_remove_resources_core;
 	}
 
 	eqos->mii = mdio_alloc();
 	if (!eqos->mii) {
 		pr_err("mdio_alloc() failed");
+		ret = -ENOMEM;
 		goto err_remove_resources_tegra;
 	}
 	eqos->mii->read = eqos_mdio_read;
@@ -1496,7 +1771,7 @@
 err_free_mdio:
 	mdio_free(eqos->mii);
 err_remove_resources_tegra:
-	eqos_remove_resources_tegra186(dev);
+	eqos->config->ops->eqos_remove_resources(dev);
 err_remove_resources_core:
 	eqos_remove_resources_core(dev);
 
@@ -1512,7 +1787,8 @@
 
 	mdio_unregister(eqos->mii);
 	mdio_free(eqos->mii);
-	eqos_remove_resources_tegra186(dev);
+	eqos->config->ops->eqos_remove_resources(dev);
+
 	eqos_probe_resources_core(dev);
 
 	debug("%s: OK\n", __func__);
@@ -1528,8 +1804,58 @@
 	.write_hwaddr = eqos_write_hwaddr,
 };
 
+static struct eqos_ops eqos_tegra186_ops = {
+	.eqos_inval_desc = eqos_inval_desc_tegra186,
+	.eqos_flush_desc = eqos_flush_desc_tegra186,
+	.eqos_inval_buffer = eqos_inval_buffer_tegra186,
+	.eqos_flush_buffer = eqos_flush_buffer_tegra186,
+	.eqos_probe_resources = eqos_probe_resources_tegra186,
+	.eqos_remove_resources = eqos_remove_resources_tegra186,
+	.eqos_stop_resets = eqos_stop_resets_tegra186,
+	.eqos_start_resets = eqos_start_resets_tegra186,
+	.eqos_stop_clks = eqos_stop_clks_tegra186,
+	.eqos_start_clks = eqos_start_clks_tegra186,
+	.eqos_calibrate_pads = eqos_calibrate_pads_tegra186,
+	.eqos_disable_calibration = eqos_disable_calibration_tegra186,
+	.eqos_set_tx_clk_speed = eqos_set_tx_clk_speed_tegra186,
+	.eqos_get_tick_clk_rate = eqos_get_tick_clk_rate_tegra186
+};
+
 static const struct eqos_config eqos_tegra186_config = {
 	.reg_access_always_ok = false,
+	.mdio_wait = 10,
+	.swr_wait = 10,
+	.config_mac = EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_DCB,
+	.config_mac_mdio = EQOS_MAC_MDIO_ADDRESS_CR_20_35,
+	.interface = eqos_get_interface_tegra186,
+	.ops = &eqos_tegra186_ops
+};
+
+static struct eqos_ops eqos_stm32_ops = {
+	.eqos_inval_desc = eqos_inval_desc_stm32,
+	.eqos_flush_desc = eqos_flush_desc_stm32,
+	.eqos_inval_buffer = eqos_inval_buffer_stm32,
+	.eqos_flush_buffer = eqos_flush_buffer_stm32,
+	.eqos_probe_resources = eqos_probe_resources_stm32,
+	.eqos_remove_resources = eqos_remove_resources_stm32,
+	.eqos_stop_resets = eqos_stop_resets_stm32,
+	.eqos_start_resets = eqos_start_resets_stm32,
+	.eqos_stop_clks = eqos_stop_clks_stm32,
+	.eqos_start_clks = eqos_start_clks_stm32,
+	.eqos_calibrate_pads = eqos_calibrate_pads_stm32,
+	.eqos_disable_calibration = eqos_disable_calibration_stm32,
+	.eqos_set_tx_clk_speed = eqos_set_tx_clk_speed_stm32,
+	.eqos_get_tick_clk_rate = eqos_get_tick_clk_rate_stm32
+};
+
+static const struct eqos_config eqos_stm32_config = {
+	.reg_access_always_ok = false,
+	.mdio_wait = 10000,
+	.swr_wait = 50,
+	.config_mac = EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_AV,
+	.config_mac_mdio = EQOS_MAC_MDIO_ADDRESS_CR_250_300,
+	.interface = eqos_get_interface_stm32,
+	.ops = &eqos_stm32_ops
 };
 
 static const struct udevice_id eqos_ids[] = {
@@ -1537,6 +1863,11 @@
 		.compatible = "nvidia,tegra186-eqos",
 		.data = (ulong)&eqos_tegra186_config
 	},
+	{
+		.compatible = "snps,dwmac-4.20a",
+		.data = (ulong)&eqos_stm32_config
+	},
+
 	{ }
 };
 
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index eb32f08..04ddb32 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -239,6 +239,14 @@
 	  used to access the SPI NOR flash chips on platforms embedding
 	  this ST IP core.
 
+config STM32_SPI
+	bool "STM32 SPI driver"
+	depends on ARCH_STM32MP
+	help
+	  Enable the STM32 Serial Peripheral Interface (SPI) driver for STM32MP
+	  SoCs. This uses driver model and requires a device tree binding to
+	  operate.
+
 config TEGRA114_SPI
 	bool "nVidia Tegra114 SPI driver"
 	help
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 8be9a4b..3f9f2fa 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -53,6 +53,7 @@
 obj-$(CONFIG_SH_SPI) += sh_spi.o
 obj-$(CONFIG_SH_QSPI) += sh_qspi.o
 obj-$(CONFIG_STM32_QSPI) += stm32_qspi.o
+obj-$(CONFIG_STM32_SPI) += stm32_spi.o
 obj-$(CONFIG_TEGRA114_SPI) += tegra114_spi.o
 obj-$(CONFIG_TEGRA20_SFLASH) += tegra20_sflash.o
 obj-$(CONFIG_TEGRA20_SLINK) += tegra20_slink.o
diff --git a/drivers/spi/stm32_spi.c b/drivers/spi/stm32_spi.c
new file mode 100644
index 0000000..34b2175
--- /dev/null
+++ b/drivers/spi/stm32_spi.c
@@ -0,0 +1,615 @@
+// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
+/*
+ * Copyright (C) 2019, STMicroelectronics - All Rights Reserved
+ *
+ * Driver for STMicroelectronics Serial peripheral interface (SPI)
+ */
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <errno.h>
+#include <reset.h>
+#include <spi.h>
+
+#include <asm/io.h>
+#include <asm/gpio.h>
+#include <linux/bitfield.h>
+#include <linux/iopoll.h>
+
+/* STM32 SPI registers */
+#define STM32_SPI_CR1		0x00
+#define STM32_SPI_CR2		0x04
+#define STM32_SPI_CFG1		0x08
+#define STM32_SPI_CFG2		0x0C
+#define STM32_SPI_SR		0x14
+#define STM32_SPI_IFCR		0x18
+#define STM32_SPI_TXDR		0x20
+#define STM32_SPI_RXDR		0x30
+#define STM32_SPI_I2SCFGR	0x50
+
+/* STM32_SPI_CR1 bit fields */
+#define SPI_CR1_SPE		BIT(0)
+#define SPI_CR1_MASRX		BIT(8)
+#define SPI_CR1_CSTART		BIT(9)
+#define SPI_CR1_CSUSP		BIT(10)
+#define SPI_CR1_HDDIR		BIT(11)
+#define SPI_CR1_SSI		BIT(12)
+
+/* STM32_SPI_CR2 bit fields */
+#define SPI_CR2_TSIZE		GENMASK(15, 0)
+
+/* STM32_SPI_CFG1 bit fields */
+#define SPI_CFG1_DSIZE		GENMASK(4, 0)
+#define SPI_CFG1_DSIZE_MIN	3
+#define SPI_CFG1_FTHLV_SHIFT	5
+#define SPI_CFG1_FTHLV		GENMASK(8, 5)
+#define SPI_CFG1_MBR_SHIFT	28
+#define SPI_CFG1_MBR		GENMASK(30, 28)
+#define SPI_CFG1_MBR_MIN	0
+#define SPI_CFG1_MBR_MAX	FIELD_GET(SPI_CFG1_MBR, SPI_CFG1_MBR)
+
+/* STM32_SPI_CFG2 bit fields */
+#define SPI_CFG2_COMM_SHIFT	17
+#define SPI_CFG2_COMM		GENMASK(18, 17)
+#define SPI_CFG2_MASTER		BIT(22)
+#define SPI_CFG2_LSBFRST	BIT(23)
+#define SPI_CFG2_CPHA		BIT(24)
+#define SPI_CFG2_CPOL		BIT(25)
+#define SPI_CFG2_SSM		BIT(26)
+#define SPI_CFG2_AFCNTR		BIT(31)
+
+/* STM32_SPI_SR bit fields */
+#define SPI_SR_RXP		BIT(0)
+#define SPI_SR_TXP		BIT(1)
+#define SPI_SR_EOT		BIT(3)
+#define SPI_SR_TXTF		BIT(4)
+#define SPI_SR_OVR		BIT(6)
+#define SPI_SR_SUSP		BIT(11)
+#define SPI_SR_RXPLVL_SHIFT	13
+#define SPI_SR_RXPLVL		GENMASK(14, 13)
+#define SPI_SR_RXWNE		BIT(15)
+
+/* STM32_SPI_IFCR bit fields */
+#define SPI_IFCR_ALL		GENMASK(11, 3)
+
+/* STM32_SPI_I2SCFGR bit fields */
+#define SPI_I2SCFGR_I2SMOD	BIT(0)
+
+#define MAX_CS_COUNT	4
+
+/* SPI Master Baud Rate min/max divisor */
+#define STM32_MBR_DIV_MIN	(2 << SPI_CFG1_MBR_MIN)
+#define STM32_MBR_DIV_MAX	(2 << SPI_CFG1_MBR_MAX)
+
+#define STM32_SPI_TIMEOUT_US	100000
+
+/* SPI Communication mode */
+#define SPI_FULL_DUPLEX		0
+#define SPI_SIMPLEX_TX		1
+#define SPI_SIMPLEX_RX		2
+#define SPI_HALF_DUPLEX		3
+
+struct stm32_spi_priv {
+	void __iomem *base;
+	struct clk clk;
+	struct reset_ctl rst_ctl;
+	struct gpio_desc cs_gpios[MAX_CS_COUNT];
+	ulong bus_clk_rate;
+	unsigned int fifo_size;
+	unsigned int cur_bpw;
+	unsigned int cur_hz;
+	unsigned int cur_xferlen; /* current transfer length in bytes */
+	int tx_len;		  /* number of data to be written in bytes */
+	int rx_len;		  /* number of data to be read in bytes */
+	const void *tx_buf;	  /* data to be written, or NULL */
+	void *rx_buf;		  /* data to be read, or NULL */
+	u32 cur_mode;
+	bool cs_high;
+};
+
+static void stm32_spi_write_txfifo(struct stm32_spi_priv *priv)
+{
+	while ((priv->tx_len > 0) &&
+	       (readl(priv->base + STM32_SPI_SR) & SPI_SR_TXP)) {
+		u32 offs = priv->cur_xferlen - priv->tx_len;
+
+		if (priv->tx_len >= sizeof(u32) &&
+		    IS_ALIGNED((uintptr_t)(priv->tx_buf + offs), sizeof(u32))) {
+			const u32 *tx_buf32 = (const u32 *)(priv->tx_buf + offs);
+
+			writel(*tx_buf32, priv->base + STM32_SPI_TXDR);
+			priv->tx_len -= sizeof(u32);
+		} else if (priv->tx_len >= sizeof(u16) &&
+			   IS_ALIGNED((uintptr_t)(priv->tx_buf + offs), sizeof(u16))) {
+			const u16 *tx_buf16 = (const u16 *)(priv->tx_buf + offs);
+
+			writew(*tx_buf16, priv->base + STM32_SPI_TXDR);
+			priv->tx_len -= sizeof(u16);
+		} else {
+			const u8 *tx_buf8 = (const u8 *)(priv->tx_buf + offs);
+
+			writeb(*tx_buf8, priv->base + STM32_SPI_TXDR);
+			priv->tx_len -= sizeof(u8);
+		}
+	}
+
+	debug("%s: %d bytes left\n", __func__, priv->tx_len);
+}
+
+static void stm32_spi_read_rxfifo(struct stm32_spi_priv *priv)
+{
+	u32 sr = readl(priv->base + STM32_SPI_SR);
+	u32 rxplvl = (sr & SPI_SR_RXPLVL) >> SPI_SR_RXPLVL_SHIFT;
+
+	while ((priv->rx_len > 0) &&
+	       ((sr & SPI_SR_RXP) ||
+	       ((sr & SPI_SR_EOT) && ((sr & SPI_SR_RXWNE) || (rxplvl > 0))))) {
+		u32 offs = priv->cur_xferlen - priv->rx_len;
+
+		if (IS_ALIGNED((uintptr_t)(priv->rx_buf + offs), sizeof(u32)) &&
+		    (priv->rx_len >= sizeof(u32) || (sr & SPI_SR_RXWNE))) {
+			u32 *rx_buf32 = (u32 *)(priv->rx_buf + offs);
+
+			*rx_buf32 = readl(priv->base + STM32_SPI_RXDR);
+			priv->rx_len -= sizeof(u32);
+		} else if (IS_ALIGNED((uintptr_t)(priv->rx_buf + offs), sizeof(u16)) &&
+			   (priv->rx_len >= sizeof(u16) ||
+			    (!(sr & SPI_SR_RXWNE) &&
+			    (rxplvl >= 2 || priv->cur_bpw > 8)))) {
+			u16 *rx_buf16 = (u16 *)(priv->rx_buf + offs);
+
+			*rx_buf16 = readw(priv->base + STM32_SPI_RXDR);
+			priv->rx_len -= sizeof(u16);
+		} else {
+			u8 *rx_buf8 = (u8 *)(priv->rx_buf + offs);
+
+			*rx_buf8 = readb(priv->base + STM32_SPI_RXDR);
+			priv->rx_len -= sizeof(u8);
+		}
+
+		sr = readl(priv->base + STM32_SPI_SR);
+		rxplvl = (sr & SPI_SR_RXPLVL) >> SPI_SR_RXPLVL_SHIFT;
+	}
+
+	debug("%s: %d bytes left\n", __func__, priv->rx_len);
+}
+
+static int stm32_spi_enable(struct stm32_spi_priv *priv)
+{
+	debug("%s\n", __func__);
+
+	/* Enable the SPI hardware */
+	setbits_le32(priv->base + STM32_SPI_CR1, SPI_CR1_SPE);
+
+	return 0;
+}
+
+static int stm32_spi_disable(struct stm32_spi_priv *priv)
+{
+	debug("%s\n", __func__);
+
+	/* Disable the SPI hardware */
+	clrbits_le32(priv->base + STM32_SPI_CR1, SPI_CR1_SPE);
+
+	return 0;
+}
+
+static int stm32_spi_claim_bus(struct udevice *slave)
+{
+	struct udevice *bus = dev_get_parent(slave);
+	struct stm32_spi_priv *priv = dev_get_priv(bus);
+
+	debug("%s\n", __func__);
+
+	/* Enable the SPI hardware */
+	return stm32_spi_enable(priv);
+}
+
+static int stm32_spi_release_bus(struct udevice *slave)
+{
+	struct udevice *bus = dev_get_parent(slave);
+	struct stm32_spi_priv *priv = dev_get_priv(bus);
+
+	debug("%s\n", __func__);
+
+	/* Disable the SPI hardware */
+	return stm32_spi_disable(priv);
+}
+
+static void stm32_spi_stopxfer(struct udevice *dev)
+{
+	struct stm32_spi_priv *priv = dev_get_priv(dev);
+	u32 cr1, sr;
+	int ret;
+
+	debug("%s\n", __func__);
+
+	cr1 = readl(priv->base + STM32_SPI_CR1);
+
+	if (!(cr1 & SPI_CR1_SPE))
+		return;
+
+	/* Wait on EOT or suspend the flow */
+	ret = readl_poll_timeout(priv->base + STM32_SPI_SR, sr,
+				 !(sr & SPI_SR_EOT), 100000);
+	if (ret < 0) {
+		if (cr1 & SPI_CR1_CSTART) {
+			writel(cr1 | SPI_CR1_CSUSP, priv->base + STM32_SPI_CR1);
+			if (readl_poll_timeout(priv->base + STM32_SPI_SR,
+					       sr, !(sr & SPI_SR_SUSP),
+					       100000) < 0)
+				dev_err(dev, "Suspend request timeout\n");
+		}
+	}
+
+	/* clear status flags */
+	setbits_le32(priv->base + STM32_SPI_IFCR, SPI_IFCR_ALL);
+}
+
+static int stm32_spi_set_cs(struct udevice *dev, unsigned int cs, bool enable)
+{
+	struct stm32_spi_priv *priv = dev_get_priv(dev);
+
+	debug("%s: cs=%d enable=%d\n", __func__, cs, enable);
+
+	if (cs >= MAX_CS_COUNT)
+		return -ENODEV;
+
+	if (!dm_gpio_is_valid(&priv->cs_gpios[cs]))
+		return -EINVAL;
+
+	if (priv->cs_high)
+		enable = !enable;
+
+	return dm_gpio_set_value(&priv->cs_gpios[cs], enable ? 1 : 0);
+}
+
+static int stm32_spi_set_mode(struct udevice *bus, uint mode)
+{
+	struct stm32_spi_priv *priv = dev_get_priv(bus);
+	u32 cfg2_clrb = 0, cfg2_setb = 0;
+
+	debug("%s: mode=%d\n", __func__, mode);
+
+	if (mode & SPI_CPOL)
+		cfg2_setb |= SPI_CFG2_CPOL;
+	else
+		cfg2_clrb |= SPI_CFG2_CPOL;
+
+	if (mode & SPI_CPHA)
+		cfg2_setb |= SPI_CFG2_CPHA;
+	else
+		cfg2_clrb |= SPI_CFG2_CPHA;
+
+	if (mode & SPI_LSB_FIRST)
+		cfg2_setb |= SPI_CFG2_LSBFRST;
+	else
+		cfg2_clrb |= SPI_CFG2_LSBFRST;
+
+	if (cfg2_clrb || cfg2_setb)
+		clrsetbits_le32(priv->base + STM32_SPI_CFG2,
+				cfg2_clrb, cfg2_setb);
+
+	if (mode & SPI_CS_HIGH)
+		priv->cs_high = true;
+	else
+		priv->cs_high = false;
+	return 0;
+}
+
+static int stm32_spi_set_fthlv(struct udevice *dev, u32 xfer_len)
+{
+	struct stm32_spi_priv *priv = dev_get_priv(dev);
+	u32 fthlv, half_fifo;
+
+	/* data packet should not exceed 1/2 of fifo space */
+	half_fifo = (priv->fifo_size / 2);
+
+	/* data_packet should not exceed transfer length */
+	fthlv = (half_fifo > xfer_len) ? xfer_len : half_fifo;
+
+	/* align packet size with data registers access */
+	fthlv -= (fthlv % 4);
+
+	if (!fthlv)
+		fthlv = 1;
+	clrsetbits_le32(priv->base + STM32_SPI_CFG1, SPI_CFG1_FTHLV,
+			(fthlv - 1) << SPI_CFG1_FTHLV_SHIFT);
+
+	return 0;
+}
+
+static int stm32_spi_set_speed(struct udevice *bus, uint hz)
+{
+	struct stm32_spi_priv *priv = dev_get_priv(bus);
+	u32 div, mbrdiv;
+
+	debug("%s: hz=%d\n", __func__, hz);
+
+	if (priv->cur_hz == hz)
+		return 0;
+
+	div = DIV_ROUND_UP(priv->bus_clk_rate, hz);
+
+	if (div < STM32_MBR_DIV_MIN ||
+	    div > STM32_MBR_DIV_MAX)
+		return -EINVAL;
+
+	/* Determine the first power of 2 greater than or equal to div */
+	if (div & (div - 1))
+		mbrdiv = fls(div);
+	else
+		mbrdiv = fls(div) - 1;
+
+	if ((mbrdiv - 1) < 0)
+		return -EINVAL;
+
+	clrsetbits_le32(priv->base + STM32_SPI_CFG1, SPI_CFG1_MBR,
+			(mbrdiv - 1) << SPI_CFG1_MBR_SHIFT);
+
+	priv->cur_hz = hz;
+
+	return 0;
+}
+
+static int stm32_spi_xfer(struct udevice *slave, unsigned int bitlen,
+			  const void *dout, void *din, unsigned long flags)
+{
+	struct udevice *bus = dev_get_parent(slave);
+	struct dm_spi_slave_platdata *slave_plat;
+	struct stm32_spi_priv *priv = dev_get_priv(bus);
+	u32 sr;
+	u32 ifcr = 0;
+	u32 xferlen;
+	u32 mode;
+	int xfer_status = 0;
+
+	xferlen = bitlen / 8;
+
+	if (xferlen <= SPI_CR2_TSIZE)
+		writel(xferlen, priv->base + STM32_SPI_CR2);
+	else
+		return -EMSGSIZE;
+
+	priv->tx_buf = dout;
+	priv->rx_buf = din;
+	priv->tx_len = priv->tx_buf ? bitlen / 8 : 0;
+	priv->rx_len = priv->rx_buf ? bitlen / 8 : 0;
+
+	mode = SPI_FULL_DUPLEX;
+	if (!priv->tx_buf)
+		mode = SPI_SIMPLEX_RX;
+	else if (!priv->rx_buf)
+		mode = SPI_SIMPLEX_TX;
+
+	if (priv->cur_xferlen != xferlen || priv->cur_mode != mode) {
+		priv->cur_mode = mode;
+		priv->cur_xferlen = xferlen;
+
+		/* Disable the SPI hardware to unlock CFG1/CFG2 registers */
+		stm32_spi_disable(priv);
+
+		clrsetbits_le32(priv->base + STM32_SPI_CFG2, SPI_CFG2_COMM,
+				mode << SPI_CFG2_COMM_SHIFT);
+
+		stm32_spi_set_fthlv(bus, xferlen);
+
+		/* Enable the SPI hardware */
+		stm32_spi_enable(priv);
+	}
+
+	debug("%s: priv->tx_len=%d priv->rx_len=%d\n", __func__,
+	      priv->tx_len, priv->rx_len);
+
+	slave_plat = dev_get_parent_platdata(slave);
+	if (flags & SPI_XFER_BEGIN)
+		stm32_spi_set_cs(bus, slave_plat->cs, false);
+
+	/* Be sure to have data in fifo before starting data transfer */
+	if (priv->tx_buf)
+		stm32_spi_write_txfifo(priv);
+
+	setbits_le32(priv->base + STM32_SPI_CR1, SPI_CR1_CSTART);
+
+	while (1) {
+		sr = readl(priv->base + STM32_SPI_SR);
+
+		if (sr & SPI_SR_OVR) {
+			dev_err(bus, "Overrun: RX data lost\n");
+			xfer_status = -EIO;
+			break;
+		}
+
+		if (sr & SPI_SR_SUSP) {
+			dev_warn(bus, "System too slow is limiting data throughput\n");
+
+			if (priv->rx_buf && priv->rx_len > 0)
+				stm32_spi_read_rxfifo(priv);
+
+			ifcr |= SPI_SR_SUSP;
+		}
+
+		if (sr & SPI_SR_TXTF)
+			ifcr |= SPI_SR_TXTF;
+
+		if (sr & SPI_SR_TXP)
+			if (priv->tx_buf && priv->tx_len > 0)
+				stm32_spi_write_txfifo(priv);
+
+		if (sr & SPI_SR_RXP)
+			if (priv->rx_buf && priv->rx_len > 0)
+				stm32_spi_read_rxfifo(priv);
+
+		if (sr & SPI_SR_EOT) {
+			if (priv->rx_buf && priv->rx_len > 0)
+				stm32_spi_read_rxfifo(priv);
+			break;
+		}
+
+		writel(ifcr, priv->base + STM32_SPI_IFCR);
+	}
+
+	/* clear status flags */
+	setbits_le32(priv->base + STM32_SPI_IFCR, SPI_IFCR_ALL);
+	stm32_spi_stopxfer(bus);
+
+	if (flags & SPI_XFER_END)
+		stm32_spi_set_cs(bus, slave_plat->cs, true);
+
+	return xfer_status;
+}
+
+static int stm32_spi_get_fifo_size(struct udevice *dev)
+{
+	struct stm32_spi_priv *priv = dev_get_priv(dev);
+	u32 count = 0;
+
+	stm32_spi_enable(priv);
+
+	while (readl(priv->base + STM32_SPI_SR) & SPI_SR_TXP)
+		writeb(++count, priv->base + STM32_SPI_TXDR);
+
+	stm32_spi_disable(priv);
+
+	debug("%s %d x 8-bit fifo size\n", __func__, count);
+
+	return count;
+}
+
+static int stm32_spi_probe(struct udevice *dev)
+{
+	struct stm32_spi_priv *priv = dev_get_priv(dev);
+	unsigned long clk_rate;
+	int ret;
+	int i;
+
+	priv->base = dev_remap_addr(dev);
+	if (!priv->base)
+		return -EINVAL;
+
+	/* enable clock */
+	ret = clk_get_by_index(dev, 0, &priv->clk);
+	if (ret < 0)
+		return ret;
+
+	ret = clk_enable(&priv->clk);
+	if (ret < 0)
+		return ret;
+
+	clk_rate = clk_get_rate(&priv->clk);
+	if (!clk_rate) {
+		ret = -EINVAL;
+		goto clk_err;
+	}
+
+	priv->bus_clk_rate = clk_rate;
+
+	/* perform reset */
+	ret = reset_get_by_index(dev, 0, &priv->rst_ctl);
+	if (ret < 0)
+		goto clk_err;
+
+	reset_assert(&priv->rst_ctl);
+	udelay(2);
+	reset_deassert(&priv->rst_ctl);
+
+	ret = gpio_request_list_by_name(dev, "cs-gpios", priv->cs_gpios,
+					ARRAY_SIZE(priv->cs_gpios), 0);
+	if (ret < 0) {
+		pr_err("Can't get %s cs gpios: %d", dev->name, ret);
+		goto reset_err;
+	}
+
+	priv->fifo_size = stm32_spi_get_fifo_size(dev);
+
+	priv->cur_mode = SPI_FULL_DUPLEX;
+	priv->cur_xferlen = 0;
+	priv->cur_bpw = SPI_DEFAULT_WORDLEN;
+	clrsetbits_le32(priv->base + STM32_SPI_CFG1, SPI_CFG1_DSIZE,
+			priv->cur_bpw - 1);
+
+	for (i = 0; i < ARRAY_SIZE(priv->cs_gpios); i++) {
+		if (!dm_gpio_is_valid(&priv->cs_gpios[i]))
+			continue;
+
+		dm_gpio_set_dir_flags(&priv->cs_gpios[i],
+				      GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE);
+	}
+
+	/* Ensure I2SMOD bit is kept cleared */
+	clrbits_le32(priv->base + STM32_SPI_I2SCFGR, SPI_I2SCFGR_I2SMOD);
+
+	/*
+	 * - SS input value high
+	 * - transmitter half duplex direction
+	 * - automatic communication suspend when RX-Fifo is full
+	 */
+	setbits_le32(priv->base + STM32_SPI_CR1,
+		     SPI_CR1_SSI | SPI_CR1_HDDIR | SPI_CR1_MASRX);
+
+	/*
+	 * - Set the master mode (default Motorola mode)
+	 * - Consider 1 master/n slaves configuration and
+	 *   SS input value is determined by the SSI bit
+	 * - keep control of all associated GPIOs
+	 */
+	setbits_le32(priv->base + STM32_SPI_CFG2,
+		     SPI_CFG2_MASTER | SPI_CFG2_SSM | SPI_CFG2_AFCNTR);
+
+	return 0;
+
+reset_err:
+	reset_free(&priv->rst_ctl);
+
+clk_err:
+	clk_disable(&priv->clk);
+	clk_free(&priv->clk);
+
+	return ret;
+};
+
+static int stm32_spi_remove(struct udevice *dev)
+{
+	struct stm32_spi_priv *priv = dev_get_priv(dev);
+	int ret;
+
+	stm32_spi_stopxfer(dev);
+	stm32_spi_disable(priv);
+
+	ret = reset_assert(&priv->rst_ctl);
+	if (ret < 0)
+		return ret;
+
+	reset_free(&priv->rst_ctl);
+
+	ret = clk_disable(&priv->clk);
+	if (ret < 0)
+		return ret;
+
+	clk_free(&priv->clk);
+
+	return ret;
+};
+
+static const struct dm_spi_ops stm32_spi_ops = {
+	.claim_bus	= stm32_spi_claim_bus,
+	.release_bus	= stm32_spi_release_bus,
+	.set_mode	= stm32_spi_set_mode,
+	.set_speed	= stm32_spi_set_speed,
+	.xfer		= stm32_spi_xfer,
+};
+
+static const struct udevice_id stm32_spi_ids[] = {
+	{ .compatible = "st,stm32h7-spi", },
+	{ }
+};
+
+U_BOOT_DRIVER(stm32_spi) = {
+	.name			= "stm32_spi",
+	.id			= UCLASS_SPI,
+	.of_match		= stm32_spi_ids,
+	.ops			= &stm32_spi_ops,
+	.priv_auto_alloc_size	= sizeof(struct stm32_spi_priv),
+	.probe			= stm32_spi_probe,
+	.remove			= stm32_spi_remove,
+};
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index b01dbc4..dbafb74 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -26,6 +26,13 @@
 	  This provides basic infrastructure to support BCM2835/2836 watchdog
 	  hardware, with a max timeout of ~15secs.
 
+config IMX_WATCHDOG
+	bool "Enable Watchdog Timer support for IMX and LSCH2 of NXP"
+	select HW_WATCHDOG
+	help
+	   Select this to enable the IMX and LSCH2 of Layerscape watchdog
+	   driver.
+
 config OMAP_WATCHDOG
 	bool "TI OMAP watchdog driver"
 	depends on ARCH_OMAP2PLUS
@@ -59,14 +66,6 @@
 	  What exactly happens when the timer expires is up to a particular
 	  device/driver.
 
-config WDT_SANDBOX
-	bool "Enable Watchdog Timer support for Sandbox"
-	depends on SANDBOX && WDT
-	help
-	  Enable Watchdog Timer support in Sandbox. This is a dummy device that
-	  can be probed and supports all of the methods of WDT, but does not
-	  really do anything.
-
 config WDT_ARMADA_37XX
 	bool "Marvell Armada 37xx watchdog timer support"
 	depends on WDT && ARMADA_3700
@@ -87,6 +86,13 @@
 	  It currently does not support Boot Flash Addressing Mode Detection or
 	  Second Boot.
 
+config WDT_AT91
+	bool "AT91 watchdog timer support"
+	depends on WDT
+	help
+	   Select this to enable Microchip watchdog timer, which can be found on
+	   some AT91 devices.
+
 config WDT_BCM6345
 	bool "BCM6345 watchdog timer support"
 	depends on WDT && (ARCH_BMIPS || ARCH_BCM6858 || ARCH_BCM63158)
@@ -95,21 +101,6 @@
 	  The watchdog timer is stopped when initialized.
 	  It performs full SoC reset.
 
-config WDT_ORION
-	bool "Orion watchdog timer support"
-	depends on WDT
-	select CLK
-	help
-	   Select this to enable Orion watchdog timer, which can be found on some
-	   Marvell Armada chips.
-
-config WDT_SP805
-	bool "SP805 watchdog timer support"
-	depends on WDT
-	help
-	   Select this to enable SP805 watchdog timer, which can be found on some
-	   nxp layerscape chips.
-
 config WDT_CDNS
 	bool "Cadence watchdog timer support"
 	depends on WDT
@@ -118,6 +109,20 @@
 	   Select this to enable Cadence watchdog timer, which can be found on some
 	   Xilinx Microzed Platform.
 
+config WDT_MPC8xx
+	bool "MPC8xx watchdog timer support"
+	depends on WDT && MPC8xx
+	select CONFIG_MPC8xx_WATCHDOG
+	help
+	   Select this to enable mpc8xx watchdog timer
+
+config WDT_MT7621
+	bool "MediaTek MT7621 watchdog timer support"
+	depends on WDT && SOC_MT7628
+	help
+	   Select this to enable Ralink / Mediatek watchdog timer,
+	   which can be found on some MediaTek chips.
+
 config WDT_MTK
 	bool "MediaTek watchdog timer support"
 	depends on WDT && ARCH_MEDIATEK
@@ -126,39 +131,43 @@
 	  The watchdog timer is stopped when initialized.
 	  It performs full SoC reset.
 
-config XILINX_TB_WATCHDOG
-	bool "Xilinx Axi watchdog timer support"
+config WDT_ORION
+	bool "Orion watchdog timer support"
 	depends on WDT
-	imply WATCHDOG
+	select CLK
 	help
-	   Select this to enable Xilinx Axi watchdog timer, which can be found on some
-	   Xilinx Microblaze Platforms.
+	   Select this to enable Orion watchdog timer, which can be found on some
+	   Marvell Armada chips.
 
-config IMX_WATCHDOG
-	bool "Enable Watchdog Timer support for IMX and LSCH2 of NXP"
-	select HW_WATCHDOG
+config WDT_SANDBOX
+	bool "Enable Watchdog Timer support for Sandbox"
+	depends on SANDBOX && WDT
 	help
-	   Select this to enable the IMX and LSCH2 of Layerscape watchdog
-	   driver.
+	  Enable Watchdog Timer support in Sandbox. This is a dummy device that
+	  can be probed and supports all of the methods of WDT, but does not
+	  really do anything.
 
-config WDT_AT91
-	bool "AT91 watchdog timer support"
+config WDT_SP805
+	bool "SP805 watchdog timer support"
 	depends on WDT
 	help
-	   Select this to enable Microchip watchdog timer, which can be found on
-	   some AT91 devices.
+	   Select this to enable SP805 watchdog timer, which can be found on some
+	   nxp layerscape chips.
 
-config WDT_MT7621
-	bool "MediaTek MT7621 watchdog timer support"
-	depends on WDT && SOC_MT7628
+config WDT_STM32MP
+	bool "IWDG watchdog driver for STM32 MP's family"
+	depends on WDT
+	imply WATCHDOG
 	help
-	   Select this to enable Ralink / Mediatek watchdog timer,
-	   which can be found on some MediaTek chips.
+	  Enable the STM32 watchdog (IWDG) driver. Enable support to
+	  configure STM32's on-SoC watchdog.
 
-config WDT_MPC8xx
-	bool "MPC8xx watchdog timer support"
-	depends on WDT && MPC8xx
+config XILINX_TB_WATCHDOG
+	bool "Xilinx Axi watchdog timer support"
+	depends on WDT
+	imply WATCHDOG
 	help
-	   Select this to enable mpc8xx watchdog timer
+	   Select this to enable Xilinx Axi watchdog timer, which can be found on some
+	   Xilinx Microblaze Platforms.
 
 endmenu
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index 6f20e73..e3f4fdb 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -28,3 +28,4 @@
 obj-$(CONFIG_WDT_MT7621) += mt7621_wdt.o
 obj-$(CONFIG_WDT_MTK) += mtk_wdt.o
 obj-$(CONFIG_WDT_SP805) += sp805_wdt.o
+obj-$(CONFIG_WDT_STM32MP) += stm32mp_wdt.o
diff --git a/drivers/watchdog/stm32mp_wdt.c b/drivers/watchdog/stm32mp_wdt.c
new file mode 100644
index 0000000..8093d0a
--- /dev/null
+++ b/drivers/watchdog/stm32mp_wdt.c
@@ -0,0 +1,135 @@
+// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
+/*
+ * Copyright (C) 2019, STMicroelectronics - All Rights Reserved
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <syscon.h>
+#include <wdt.h>
+#include <asm/io.h>
+#include <linux/iopoll.h>
+
+/* IWDG registers */
+#define IWDG_KR		0x00	/* Key register */
+#define IWDG_PR		0x04	/* Prescaler Register */
+#define IWDG_RLR	0x08	/* ReLoad Register */
+#define IWDG_SR		0x0C	/* Status Register */
+
+/* IWDG_KR register bit mask */
+#define KR_KEY_RELOAD	0xAAAA	/* Reload counter enable */
+#define KR_KEY_ENABLE	0xCCCC	/* Peripheral enable */
+#define KR_KEY_EWA	0x5555	/* Write access enable */
+
+/* IWDG_PR register bit values */
+#define PR_256		0x06	/* Prescaler set to 256 */
+
+/* IWDG_RLR register values */
+#define RLR_MAX		0xFFF	/* Max value supported by reload register */
+
+/* IWDG_SR register bit values */
+#define SR_PVU		BIT(0)	/* Watchdog prescaler value update */
+#define SR_RVU		BIT(1)	/* Watchdog counter reload value update */
+
+struct stm32mp_wdt_priv {
+	fdt_addr_t base;		/* registers addr in physical memory */
+	unsigned long wdt_clk_rate;	/* Watchdog dedicated clock rate */
+};
+
+static int stm32mp_wdt_reset(struct udevice *dev)
+{
+	struct stm32mp_wdt_priv *priv = dev_get_priv(dev);
+
+	writel(KR_KEY_RELOAD, priv->base + IWDG_KR);
+
+	return 0;
+}
+
+static int stm32mp_wdt_start(struct udevice *dev, u64 timeout_ms, ulong flags)
+{
+	struct stm32mp_wdt_priv *priv = dev_get_priv(dev);
+	int reload;
+	u32 val;
+	int ret;
+
+	/* Prescaler fixed to 256 */
+	reload = timeout_ms * priv->wdt_clk_rate / 256;
+	if (reload > RLR_MAX + 1)
+		/* Force to max watchdog counter reload value */
+		reload = RLR_MAX + 1;
+	else if (!reload)
+		/* Force to min watchdog counter reload value */
+		reload = priv->wdt_clk_rate / 256;
+
+	/* Set prescaler & reload registers */
+	writel(KR_KEY_EWA, priv->base + IWDG_KR);
+	writel(PR_256, priv->base + IWDG_PR);
+	writel(reload - 1, priv->base + IWDG_RLR);
+
+	/* Enable watchdog */
+	writel(KR_KEY_ENABLE, priv->base + IWDG_KR);
+
+	/* Wait for the registers to be updated */
+	ret = readl_poll_timeout(priv->base + IWDG_SR, val,
+				 val & (SR_PVU | SR_RVU), CONFIG_SYS_HZ);
+
+	if (ret < 0) {
+		pr_err("Updating IWDG registers timeout");
+		return -ETIMEDOUT;
+	}
+
+	return 0;
+}
+
+static int stm32mp_wdt_probe(struct udevice *dev)
+{
+	struct stm32mp_wdt_priv *priv = dev_get_priv(dev);
+	struct clk clk;
+	int ret;
+
+	debug("IWDG init\n");
+
+	priv->base = devfdt_get_addr(dev);
+	if (priv->base == FDT_ADDR_T_NONE)
+		return -EINVAL;
+
+	/* Enable clock */
+	ret = clk_get_by_name(dev, "pclk", &clk);
+	if (ret)
+		return ret;
+
+	ret = clk_enable(&clk);
+	if (ret)
+		return ret;
+
+	/* Get LSI clock */
+	ret = clk_get_by_name(dev, "lsi", &clk);
+	if (ret)
+		return ret;
+
+	priv->wdt_clk_rate = clk_get_rate(&clk);
+
+	debug("IWDG init done\n");
+
+	return 0;
+}
+
+static const struct wdt_ops stm32mp_wdt_ops = {
+	.start = stm32mp_wdt_start,
+	.reset = stm32mp_wdt_reset,
+};
+
+static const struct udevice_id stm32mp_wdt_match[] = {
+	{ .compatible = "st,stm32mp1-iwdg" },
+	{ /* sentinel */ }
+};
+
+U_BOOT_DRIVER(stm32mp_wdt) = {
+	.name = "stm32mp-wdt",
+	.id = UCLASS_WDT,
+	.of_match = stm32mp_wdt_match,
+	.priv_auto_alloc_size = sizeof(struct stm32mp_wdt_priv),
+	.probe = stm32mp_wdt_probe,
+	.ops = &stm32mp_wdt_ops,
+};
diff --git a/env/Kconfig b/env/Kconfig
index 1e10c7a..5651685 100644
--- a/env/Kconfig
+++ b/env/Kconfig
@@ -2,18 +2,12 @@
 
 config ENV_IS_NOWHERE
 	bool "Environment is not stored"
-	depends on !ENV_IS_IN_EEPROM
-	depends on !ENV_IS_IN_EXT4
-	depends on !ENV_IS_IN_FAT
-	depends on !ENV_IS_IN_FLASH
-	depends on !ENV_IS_IN_MMC
-	depends on !ENV_IS_IN_NAND
-	depends on !ENV_IS_IN_NVRAM
-	depends on !ENV_IS_IN_ONENAND
-	depends on !ENV_IS_IN_REMOTE
-	depends on !ENV_IS_IN_SPI_FLASH
-	depends on !ENV_IS_IN_UBI
-	default y
+	default y if !ENV_IS_IN_EEPROM && !ENV_IS_IN_EXT4 && \
+		     !ENV_IS_IN_FAT && !ENV_IS_IN_FLASH && \
+		     !ENV_IS_IN_MMC && !ENV_IS_IN_NAND && \
+		     !ENV_IS_IN_NVRAM && !ENV_IS_IN_ONENAND && \
+		     !ENV_IS_IN_REMOTE && !ENV_IS_IN_SPI_FLASH && \
+		     !ENV_IS_IN_UBI
 	help
 	  Define this if you don't want to or can't have an environment stored
 	  on a storage medium. In this case the environment will still exist
diff --git a/env/ext4.c b/env/ext4.c
index 388474a..9947381 100644
--- a/env/ext4.c
+++ b/env/ext4.c
@@ -30,6 +30,16 @@
 #include <ext4fs.h>
 #include <mmc.h>
 
+__weak const char *env_ext4_get_intf(void)
+{
+	return (const char *)CONFIG_ENV_EXT4_INTERFACE;
+}
+
+__weak const char *env_ext4_get_dev_part(void)
+{
+	return (const char *)CONFIG_ENV_EXT4_DEVICE_AND_PART;
+}
+
 #ifdef CONFIG_CMD_SAVEENV
 static int env_ext4_save(void)
 {
@@ -38,13 +48,14 @@
 	disk_partition_t info;
 	int dev, part;
 	int err;
+	const char *ifname = env_ext4_get_intf();
+	const char *dev_and_part = env_ext4_get_dev_part();
 
 	err = env_export(&env_new);
 	if (err)
 		return err;
 
-	part = blk_get_device_part_str(CONFIG_ENV_EXT4_INTERFACE,
-				       CONFIG_ENV_EXT4_DEVICE_AND_PART,
+	part = blk_get_device_part_str(ifname, dev_and_part,
 				       &dev_desc, &info, 1);
 	if (part < 0)
 		return 1;
@@ -54,8 +65,7 @@
 
 	if (!ext4fs_mount(info.size)) {
 		printf("\n** Unable to use %s %s for saveenv **\n",
-		       CONFIG_ENV_EXT4_INTERFACE,
-		       CONFIG_ENV_EXT4_DEVICE_AND_PART);
+		       ifname, dev_and_part);
 		return 1;
 	}
 
@@ -65,8 +75,7 @@
 
 	if (err == -1) {
 		printf("\n** Unable to write \"%s\" from %s%d:%d **\n",
-			CONFIG_ENV_EXT4_FILE, CONFIG_ENV_EXT4_INTERFACE, dev,
-			part);
+			CONFIG_ENV_EXT4_FILE, ifname, dev, part);
 		return 1;
 	}
 
@@ -83,14 +92,15 @@
 	int dev, part;
 	int err;
 	loff_t off;
+	const char *ifname = env_ext4_get_intf();
+	const char *dev_and_part = env_ext4_get_dev_part();
 
 #ifdef CONFIG_MMC
-	if (!strcmp(CONFIG_ENV_EXT4_INTERFACE, "mmc"))
+	if (!strcmp(ifname, "mmc"))
 		mmc_initialize(NULL);
 #endif
 
-	part = blk_get_device_part_str(CONFIG_ENV_EXT4_INTERFACE,
-				       CONFIG_ENV_EXT4_DEVICE_AND_PART,
+	part = blk_get_device_part_str(ifname, dev_and_part,
 				       &dev_desc, &info, 1);
 	if (part < 0)
 		goto err_env_relocate;
@@ -100,8 +110,7 @@
 
 	if (!ext4fs_mount(info.size)) {
 		printf("\n** Unable to use %s %s for loading the env **\n",
-		       CONFIG_ENV_EXT4_INTERFACE,
-		       CONFIG_ENV_EXT4_DEVICE_AND_PART);
+		       ifname, dev_and_part);
 		goto err_env_relocate;
 	}
 
@@ -111,8 +120,7 @@
 
 	if (err == -1) {
 		printf("\n** Unable to read \"%s\" from %s%d:%d **\n",
-			CONFIG_ENV_EXT4_FILE, CONFIG_ENV_EXT4_INTERFACE, dev,
-			part);
+			CONFIG_ENV_EXT4_FILE, ifname, dev, part);
 		goto err_env_relocate;
 	}
 
diff --git a/include/configs/stm32mp1.h b/include/configs/stm32mp1.h
index e8be51a..1d385e0 100644
--- a/include/configs/stm32mp1.h
+++ b/include/configs/stm32mp1.h
@@ -38,6 +38,15 @@
  */
 #define CONFIG_SYS_LOAD_ADDR			STM32_DDR_BASE
 
+#if defined(CONFIG_ENV_IS_IN_UBI)
+#define CONFIG_ENV_UBI_VOLUME_REDUND		"uboot_config_r"
+#endif
+
+#if defined(CONFIG_ENV_IS_IN_SPI_FLASH)
+#define	CONFIG_ENV_SECT_SIZE			SZ_256K
+#define	CONFIG_ENV_OFFSET			0x00280000
+#endif
+
 /* ATAGs */
 #define CONFIG_CMDLINE_TAG
 #define CONFIG_SETUP_MEMORY_TAGS
@@ -68,16 +77,29 @@
 /*MMC SD*/
 #define CONFIG_SYS_MMC_MAX_DEVICE	3
 
+/* Ethernet need */
+#ifdef CONFIG_DWC_ETH_QOS
+#define CONFIG_SYS_NONCACHED_MEMORY	(1 * SZ_1M)	/* 1M */
+#define CONFIG_SERVERIP                 192.168.1.1
+#define CONFIG_BOOTP_SERVERIP
+#define CONFIG_SYS_AUTOLOAD		"no"
+#endif
+
 /*****************************************************************************/
 #ifdef CONFIG_DISTRO_DEFAULTS
 /*****************************************************************************/
 
 #if !defined(CONFIG_SPL_BUILD)
 
+/* NAND support */
+#define CONFIG_SYS_NAND_ONFI_DETECTION
+#define CONFIG_SYS_MAX_NAND_DEVICE	1
 #define BOOT_TARGET_DEVICES(func) \
 	func(MMC, mmc, 1) \
 	func(MMC, mmc, 0) \
-	func(MMC, mmc, 2)
+	func(MMC, mmc, 2) \
+	func(PXE, pxe, na)
+
 /*
  * bootcmd for stm32mp1:
  * for serial/usb: execute the stm32prog command
@@ -99,6 +121,14 @@
 
 #include <config_distro_bootcmd.h>
 
+#if defined(CONFIG_STM32_QSPI) || defined(CONFIG_NAND_STM32_FMC)
+#define CONFIG_SYS_MTDPARTS_RUNTIME
+#endif
+
+#define STM32MP_MTDPARTS \
+	"mtdparts_nor0=256k(fsbl1),256k(fsbl2),2m(ssbl),256k(u-boot-env),-(nor_user)\0" \
+	"mtdparts_nand0=2m(fsbl),2m(ssbl1),2m(ssbl2),-(UBI)\0"
+
 /*
  * memory layout for 32M uncompressed/compressed kernel,
  * 1M fdt, 1M script, 1M pxe and 1M for splashimage
@@ -114,6 +144,7 @@
 	"fdt_high=0xffffffff\0" \
 	"initrd_high=0xffffffff\0" \
 	STM32MP_BOOTCMD \
+	STM32MP_MTDPARTS \
 	BOOTENV
 
 #endif /* ifndef CONFIG_SPL_BUILD */