Merge "feat(tc0): add Ivy partition" into integration
diff --git a/Makefile b/Makefile
index e5ab324..2a1d4d8 100644
--- a/Makefile
+++ b/Makefile
@@ -1318,7 +1318,8 @@
 		echo "    with ${CHECKPATCH_OPTS} option(s)";		\
 	fi
 	${Q}COMMON_COMMIT=$$(git merge-base HEAD ${BASE_COMMIT});	\
-	for commit in `git rev-list $$COMMON_COMMIT..HEAD`; do		\
+	for commit in `git rev-list --no-merges $$COMMON_COMMIT..HEAD`;	\
+	do								\
 		printf "\n[*] Checking style of '$$commit'\n\n";	\
 		git log --format=email "$$commit~..$$commit"		\
 			-- ${CHECK_PATHS} |				\
diff --git a/docs/getting_started/prerequisites.rst b/docs/getting_started/prerequisites.rst
index aa1ae67..f45193a 100644
--- a/docs/getting_started/prerequisites.rst
+++ b/docs/getting_started/prerequisites.rst
@@ -26,7 +26,7 @@
 |TF-A| can be built with any of the following *cross-compiler* toolchains that
 target the Armv7-A or Armv8-A architectures:
 
-- GCC >= 10.2-2020.11 (from the `Arm Developer website`_)
+- GCC >= 10.3-2021.07 (from the `Arm Developer website`_)
 - Clang >= 4.0
 - Arm Compiler >= 6.0
 
diff --git a/docs/plat/arm/fvp/index.rst b/docs/plat/arm/fvp/index.rst
index d41982f..2aaf195 100644
--- a/docs/plat/arm/fvp/index.rst
+++ b/docs/plat/arm/fvp/index.rst
@@ -12,51 +12,50 @@
 (64-bit host machine only).
 
 .. note::
-   The FVP models used are Version 11.15 Build 14, unless otherwise stated.
+   The FVP models used are Version 11.16 Build 16, unless otherwise stated.
 
--  ``FVP_Base_AEMvA``
--  ``FVP_Base_AEMv8A-AEMv8A``
+-  ``Foundation_Platform``
 -  ``FVP_Base_AEMv8A-AEMv8A-AEMv8A-AEMv8A-CCN502``
--  ``FVP_Base_RevC-2xAEMvA``
--  ``FVP_Base_Cortex-A32x4`` (Version 11.12 build 38)
+-  ``FVP_Base_AEMv8A-AEMv8A`` (For certain configurations also uses 11.14/21)
+-  ``FVP_Base_AEMv8A-GIC600AE``
+-  ``FVP_Base_AEMvA``         (For certain configurations also uses 0.0/6684)
+-  ``FVP_Base_Cortex-A32x4``  (Version 11.12/38)
 -  ``FVP_Base_Cortex-A35x4``
 -  ``FVP_Base_Cortex-A53x4``
--  ``FVP_Base_Cortex-A55x4+Cortex-A75x4``
 -  ``FVP_Base_Cortex-A55x4``
+-  ``FVP_Base_Cortex-A55x4+Cortex-A75x4``
 -  ``FVP_Base_Cortex-A57x1-A53x1``
 -  ``FVP_Base_Cortex-A57x2-A53x4``
 -  ``FVP_Base_Cortex-A57x4-A53x4``
 -  ``FVP_Base_Cortex-A57x4``
--  ``FVP_Base_Cortex-A65x4``
 -  ``FVP_Base_Cortex-A65AEx8``
+-  ``FVP_Base_Cortex-A65x4``
+-  ``FVP_Base_Cortex-A710x4``
 -  ``FVP_Base_Cortex-A72x4-A53x4``
 -  ``FVP_Base_Cortex-A72x4``
 -  ``FVP_Base_Cortex-A73x4-A53x4``
 -  ``FVP_Base_Cortex-A73x4``
 -  ``FVP_Base_Cortex-A75x4``
--  ``FVP_Base_Cortex-A76x4``
 -  ``FVP_Base_Cortex-A76AEx4``
 -  ``FVP_Base_Cortex-A76AEx8``
+-  ``FVP_Base_Cortex-A76x4``
 -  ``FVP_Base_Cortex-A77x4``
 -  ``FVP_Base_Cortex-A78x4``
--  ``FVP_Base_Cortex-A710x4``
--  ``FVP_Morello``         (Version 0.10 build 542)
 -  ``FVP_Base_Neoverse-E1x1``
 -  ``FVP_Base_Neoverse-E1x2``
 -  ``FVP_Base_Neoverse-E1x4``
 -  ``FVP_Base_Neoverse-N1x4``
 -  ``FVP_Base_Neoverse-N2x4`` (Version 11.12 build 38)
 -  ``FVP_Base_Neoverse-V1x4``
--  ``FVP_CSS_SGI-575``     (Version 11.10 build 36)
--  ``FVP_CSS_SGM-775``
--  ``FVP_RD_E1_edge``      (Version 11.9 build 41)
--  ``FVP_RD_N1_edge``      (Version 11.10 build 36)
--  ``FVP_RD_N1_edge_dual`` (Version 11.10 build 36)
--  ``FVP_RD_Daniel``       (Version 11.13 build 10)
--  ``FVP_RD_N2``           (Version 11.13 build 10)
--  ``FVP_TC0``             (Version 0.0 build 6509)
--  ``FVP_Base_AEMv8A-GIC600AE`` (Version 0.0 build 6415)
--  ``Foundation_Platform``
+-  ``FVP_Base_RevC-2xAEMvA``  (For certain configurations also uses 0.0/6557)
+-  ``FVP_CSS_SGI-575``        (Version 11.15/26)
+-  ``FVP_Morello``            (Version 0.11/19)
+-  ``FVP_RD_E1_edge``         (Version 11.15/26)
+-  ``FVP_RD_N1_edge_dual``    (Version 11.15/26)
+-  ``FVP_RD_N1_edge``         (Version 11.15/26)
+-  ``FVP_RD_V1``              (Version 11.15/26)
+-  ``FVP_TC0``
+-  ``FVP_TC1``
 
 The latest version of the AArch32 build of TF-A has been tested on the
 following Arm FVPs without shifted affinities, and that do not support threaded
diff --git a/drivers/st/usb/stm32mp1_usb.c b/drivers/st/usb/stm32mp1_usb.c
new file mode 100644
index 0000000..9a49690
--- /dev/null
+++ b/drivers/st/usb/stm32mp1_usb.c
@@ -0,0 +1,1091 @@
+/*
+ * Copyright (c) 2021, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdint.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <drivers/st/stm32mp1_usb.h>
+#include <lib/mmio.h>
+
+#include <platform_def.h>
+
+#define USB_OTG_MODE_DEVICE			0U
+#define USB_OTG_MODE_HOST			1U
+#define USB_OTG_MODE_DRD			2U
+
+#define EP_TYPE_CTRL				0U
+#define EP_TYPE_ISOC				1U
+#define EP_TYPE_BULK				2U
+#define EP_TYPE_INTR				3U
+
+#define USBD_FIFO_FLUSH_TIMEOUT_US		1000U
+#define EP0_FIFO_SIZE				64U
+
+/* OTG registers offsets */
+#define OTG_GOTGINT				0x004U
+#define OTG_GAHBCFG				0x008U
+#define OTG_GUSBCFG				0x00CU
+#define OTG_GRSTCTL				0x010U
+#define OTG_GINTSTS				0x014U
+#define OTG_GINTMSK				0x018U
+#define OTG_GRXSTSP				0x020U
+#define OTG_GLPMCFG				0x054U
+#define OTG_DCFG				0x800U
+#define OTG_DCTL				0x804U
+#define OTG_DSTS				0x808U
+#define OTG_DIEPMSK				0x810U
+#define OTG_DOEPMSK				0x814U
+#define OTG_DAINT				0x818U
+#define OTG_DAINTMSK				0x81CU
+#define OTG_DIEPEMPMSK				0x834U
+
+/* Definitions for OTG_DIEPx registers */
+#define OTG_DIEP_BASE				0x900U
+#define OTG_DIEP_SIZE				0x20U
+#define OTG_DIEPCTL				0x00U
+#define OTG_DIEPINT				0x08U
+#define OTG_DIEPTSIZ				0x10U
+#define OTG_DIEPDMA				0x14U
+#define OTG_DTXFSTS				0x18U
+#define OTG_DIEP_MAX_NB				9U
+
+/* Definitions for OTG_DOEPx registers */
+#define OTG_DOEP_BASE				0xB00U
+#define OTG_DOEP_SIZE				0x20U
+#define OTG_DOEPCTL				0x00U
+#define OTG_DOEPINT				0x08U
+#define OTG_DOEPTSIZ				0x10U
+#define OTG_DOEPDMA				0x14U
+#define OTG_D0EP_MAX_NB				9U
+
+/* Definitions for OTG_DAINT registers */
+#define OTG_DAINT_OUT_MASK			GENMASK(31, 16)
+#define OTG_DAINT_OUT_SHIFT			16U
+#define OTG_DAINT_IN_MASK			GENMASK(15, 0)
+#define OTG_DAINT_IN_SHIFT			0U
+
+#define OTG_DAINT_EP0_IN			BIT(16)
+#define OTG_DAINT_EP0_OUT			BIT(0)
+
+/* Definitions for FIFOs */
+#define OTG_FIFO_BASE				0x1000U
+#define OTG_FIFO_SIZE				0x1000U
+
+/* Bit definitions for OTG_GOTGINT register */
+#define OTG_GOTGINT_SEDET			BIT(2)
+
+/* Bit definitions for OTG_GAHBCFG register */
+#define OTG_GAHBCFG_GINT			BIT(0)
+
+/* Bit definitions for OTG_GUSBCFG register */
+#define OTG_GUSBCFG_TRDT			GENMASK(13, 10)
+#define OTG_GUSBCFG_TRDT_SHIFT			10U
+
+#define USBD_HS_TRDT_VALUE			9U
+
+/* Bit definitions for OTG_GRSTCTL register */
+#define OTG_GRSTCTL_RXFFLSH			BIT(4)
+#define OTG_GRSTCTL_TXFFLSH			BIT(5)
+#define OTG_GRSTCTL_TXFNUM_SHIFT		6U
+
+/* Bit definitions for OTG_GINTSTS register */
+#define OTG_GINTSTS_CMOD			BIT(0)
+#define OTG_GINTSTS_MMIS			BIT(1)
+#define OTG_GINTSTS_OTGINT			BIT(2)
+#define OTG_GINTSTS_SOF				BIT(3)
+#define OTG_GINTSTS_RXFLVL			BIT(4)
+#define OTG_GINTSTS_USBSUSP			BIT(11)
+#define OTG_GINTSTS_USBRST			BIT(12)
+#define OTG_GINTSTS_ENUMDNE			BIT(13)
+#define OTG_GINTSTS_IEPINT			BIT(18)
+#define OTG_GINTSTS_OEPINT			BIT(19)
+#define OTG_GINTSTS_IISOIXFR			BIT(20)
+#define OTG_GINTSTS_IPXFR_INCOMPISOOUT		BIT(21)
+#define OTG_GINTSTS_LPMINT			BIT(27)
+#define OTG_GINTSTS_SRQINT			BIT(30)
+#define OTG_GINTSTS_WKUPINT			BIT(31)
+
+/* Bit definitions for OTG_GRXSTSP register */
+#define OTG_GRXSTSP_EPNUM			GENMASK(3, 0)
+#define OTG_GRXSTSP_BCNT			GENMASK(14, 4)
+#define OTG_GRXSTSP_BCNT_SHIFT			4U
+#define OTG_GRXSTSP_PKTSTS			GENMASK(20, 17)
+#define OTG_GRXSTSP_PKTSTS_SHIFT		17U
+
+#define STS_GOUT_NAK				1U
+#define STS_DATA_UPDT				2U
+#define STS_XFER_COMP				3U
+#define STS_SETUP_COMP				4U
+#define STS_SETUP_UPDT				6U
+
+/* Bit definitions for OTG_GLPMCFG register */
+#define OTG_GLPMCFG_BESL			GENMASK(5, 2)
+
+/* Bit definitions for OTG_DCFG register */
+#define OTG_DCFG_DAD				GENMASK(10, 4)
+#define OTG_DCFG_DAD_SHIFT			4U
+
+/* Bit definitions for OTG_DCTL register */
+#define OTG_DCTL_RWUSIG				BIT(0)
+#define OTG_DCTL_SDIS				BIT(1)
+#define OTG_DCTL_CGINAK				BIT(8)
+
+/* Bit definitions for OTG_DSTS register */
+#define OTG_DSTS_SUSPSTS			BIT(0)
+#define OTG_DSTS_ENUMSPD_MASK			GENMASK(2, 1)
+#define OTG_DSTS_FNSOF0				BIT(8)
+
+#define OTG_DSTS_ENUMSPD(val)			((val) << 1)
+#define OTG_DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ	OTG_DSTS_ENUMSPD(0U)
+#define OTG_DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ	OTG_DSTS_ENUMSPD(1U)
+#define OTG_DSTS_ENUMSPD_LS_PHY_6MHZ		OTG_DSTS_ENUMSPD(2U)
+#define OTG_DSTS_ENUMSPD_FS_PHY_48MHZ		OTG_DSTS_ENUMSPD(3U)
+
+/* Bit definitions for OTG_DIEPMSK register */
+#define OTG_DIEPMSK_XFRCM			BIT(0)
+#define OTG_DIEPMSK_EPDM			BIT(1)
+#define OTG_DIEPMSK_TOM				BIT(3)
+
+/* Bit definitions for OTG_DOEPMSK register */
+#define OTG_DOEPMSK_XFRCM			BIT(0)
+#define OTG_DOEPMSK_EPDM			BIT(1)
+#define OTG_DOEPMSK_STUPM			BIT(3)
+
+/* Bit definitions for OTG_DIEPCTLx registers */
+#define OTG_DIEPCTL_MPSIZ			GENMASK(10, 0)
+#define OTG_DIEPCTL_STALL			BIT(21)
+#define OTG_DIEPCTL_CNAK			BIT(26)
+#define OTG_DIEPCTL_SD0PID_SEVNFRM		BIT(28)
+#define OTG_DIEPCTL_SODDFRM			BIT(29)
+#define OTG_DIEPCTL_EPDIS			BIT(30)
+#define OTG_DIEPCTL_EPENA			BIT(31)
+
+/* Bit definitions for OTG_DIEPINTx registers */
+#define OTG_DIEPINT_XFRC			BIT(0)
+#define OTG_DIEPINT_EPDISD			BIT(1)
+#define OTG_DIEPINT_TOC				BIT(3)
+#define OTG_DIEPINT_ITTXFE			BIT(4)
+#define OTG_DIEPINT_INEPNE			BIT(6)
+#define OTG_DIEPINT_TXFE			BIT(7)
+#define OTG_DIEPINT_TXFE_SHIFT			7U
+
+#define OTG_DIEPINT_MASK			(BIT(13) | BIT(11) | GENMASK(9, 0))
+
+/* Bit definitions for OTG_DIEPTSIZx registers */
+#define OTG_DIEPTSIZ_XFRSIZ			GENMASK(18, 0)
+#define OTG_DIEPTSIZ_PKTCNT			GENMASK(28, 19)
+#define OTG_DIEPTSIZ_PKTCNT_SHIFT		19U
+#define OTG_DIEPTSIZ_MCNT_MASK			GENMASK(30, 29)
+#define OTG_DIEPTSIZ_MCNT_DATA0			BIT(29)
+
+#define OTG_DIEPTSIZ_PKTCNT_1			BIT(19)
+
+/* Bit definitions for OTG_DTXFSTSx registers */
+#define OTG_DTXFSTS_INEPTFSAV			GENMASK(15, 0)
+
+/* Bit definitions for OTG_DOEPCTLx registers */
+#define OTG_DOEPCTL_STALL			BIT(21)
+#define OTG_DOEPCTL_CNAK			BIT(26)
+#define OTG_DOEPCTL_SD0PID_SEVNFRM		BIT(28) /* other than endpoint 0 */
+#define OTG_DOEPCTL_SD1PID_SODDFRM		BIT(29) /* other than endpoint 0 */
+#define OTG_DOEPCTL_EPDIS			BIT(30)
+#define OTG_DOEPCTL_EPENA			BIT(31)
+
+/* Bit definitions for OTG_DOEPTSIZx registers */
+#define OTG_DOEPTSIZ_XFRSIZ			GENMASK(18, 0)
+#define OTG_DOEPTSIZ_PKTCNT			GENMASK(28, 19)
+#define OTG_DOEPTSIZ_RXDPID_STUPCNT		GENMASK(30, 29)
+
+/* Bit definitions for OTG_DOEPINTx registers */
+#define OTG_DOEPINT_XFRC			BIT(0)
+#define OTG_DOEPINT_STUP			BIT(3)
+#define OTG_DOEPINT_OTEPDIS			BIT(4)
+
+#define OTG_DOEPINT_MASK			(GENMASK(15, 12) | GENMASK(9, 8) | GENMASK(6, 0))
+
+#define EP_NB					15U
+#define EP_ALL					0x10U
+
+/*
+ * Flush TX FIFO.
+ * handle: PCD handle.
+ * num: FIFO number.
+ *	   This parameter can be a value from 1 to 15 or EP_ALL.
+ *	   EP_ALL= 0x10 means Flush all TX FIFOs
+ * return: USB status.
+ */
+static enum usb_status usb_dwc2_flush_tx_fifo(void *handle, uint32_t num)
+{
+	uintptr_t usb_base_addr = (uintptr_t)handle;
+	uint64_t timeout = timeout_init_us(USBD_FIFO_FLUSH_TIMEOUT_US);
+
+	mmio_write_32(usb_base_addr + OTG_GRSTCTL,
+		      OTG_GRSTCTL_TXFFLSH | (uint32_t)(num << OTG_GRSTCTL_TXFNUM_SHIFT));
+
+	while ((mmio_read_32(usb_base_addr + OTG_GRSTCTL) &
+		OTG_GRSTCTL_TXFFLSH) == OTG_GRSTCTL_TXFFLSH) {
+		if (timeout_elapsed(timeout)) {
+			return USBD_TIMEOUT;
+		}
+	}
+
+	return USBD_OK;
+}
+
+/*
+ * Flush RX FIFO.
+ * handle: PCD handle.
+ * return: USB status.
+ */
+static enum usb_status usb_dwc2_flush_rx_fifo(void *handle)
+{
+	uintptr_t usb_base_addr = (uintptr_t)handle;
+	uint64_t timeout = timeout_init_us(USBD_FIFO_FLUSH_TIMEOUT_US);
+
+	mmio_write_32(usb_base_addr + OTG_GRSTCTL, OTG_GRSTCTL_RXFFLSH);
+
+	while ((mmio_read_32(usb_base_addr + OTG_GRSTCTL) &
+		 OTG_GRSTCTL_RXFFLSH) == OTG_GRSTCTL_RXFFLSH) {
+		if (timeout_elapsed(timeout)) {
+			return USBD_TIMEOUT;
+		}
+	}
+
+	return USBD_OK;
+}
+
+/*
+ * Return the global USB interrupt status.
+ * handle: PCD handle.
+ * return: Interrupt register value.
+ */
+static uint32_t usb_dwc2_read_int(void *handle)
+{
+	uintptr_t usb_base_addr = (uintptr_t)handle;
+
+	return mmio_read_32(usb_base_addr + OTG_GINTSTS) &
+	       mmio_read_32(usb_base_addr + OTG_GINTMSK);
+}
+
+/*
+ * Return the USB device OUT endpoints interrupt.
+ * handle: PCD handle.
+ * return: Device OUT endpoint interrupts.
+ */
+static uint32_t usb_dwc2_all_out_ep_int(void *handle)
+{
+	uintptr_t usb_base_addr = (uintptr_t)handle;
+
+	return ((mmio_read_32(usb_base_addr + OTG_DAINT) &
+		 mmio_read_32(usb_base_addr + OTG_DAINTMSK)) &
+		OTG_DAINT_OUT_MASK) >> OTG_DAINT_OUT_SHIFT;
+}
+
+/*
+ * Return the USB device IN endpoints interrupt.
+ * handle: PCD handle.
+ * return: Device IN endpoint interrupts.
+ */
+static uint32_t usb_dwc2_all_in_ep_int(void *handle)
+{
+	uintptr_t usb_base_addr = (uintptr_t)handle;
+
+	return ((mmio_read_32(usb_base_addr + OTG_DAINT) &
+		 mmio_read_32(usb_base_addr + OTG_DAINTMSK)) &
+		OTG_DAINT_IN_MASK) >> OTG_DAINT_IN_SHIFT;
+}
+
+/*
+ * Return Device OUT EP interrupt register.
+ * handle: PCD handle.
+ * epnum: Endpoint number.
+ *         This parameter can be a value from 0 to 15.
+ * return: Device OUT EP Interrupt register.
+ */
+static uint32_t usb_dwc2_out_ep_int(void *handle, uint8_t epnum)
+{
+	uintptr_t usb_base_addr = (uintptr_t)handle;
+
+	return mmio_read_32(usb_base_addr + OTG_DOEP_BASE +
+			    (epnum * OTG_DOEP_SIZE) + OTG_DOEPINT) &
+	       mmio_read_32(usb_base_addr + OTG_DOEPMSK);
+}
+
+/*
+ * Return Device IN EP interrupt register.
+ * handle: PCD handle.
+ * epnum: Endpoint number.
+ *         This parameter can be a value from 0 to 15.
+ * return: Device IN EP Interrupt register.
+ */
+static uint32_t usb_dwc2_in_ep_int(void *handle, uint8_t epnum)
+{
+	uintptr_t usb_base_addr = (uintptr_t)handle;
+	uint32_t msk;
+	uint32_t emp;
+
+	msk = mmio_read_32(usb_base_addr + OTG_DIEPMSK);
+	emp = mmio_read_32(usb_base_addr + OTG_DIEPEMPMSK);
+	msk |= ((emp >> epnum) << OTG_DIEPINT_TXFE_SHIFT) & OTG_DIEPINT_TXFE;
+
+	return mmio_read_32(usb_base_addr + OTG_DIEP_BASE +
+			    (epnum * OTG_DIEP_SIZE) + OTG_DIEPINT) & msk;
+}
+
+/*
+ * Return USB core mode.
+ * handle: PCD handle.
+ * return: Core mode.
+ *         This parameter can be 0 (host) or 1 (device).
+ */
+static uint32_t usb_dwc2_get_mode(void *handle)
+{
+	uintptr_t usb_base_addr = (uintptr_t)handle;
+
+	return mmio_read_32(usb_base_addr + OTG_GINTSTS) & OTG_GINTSTS_CMOD;
+}
+
+/*
+ * Activate EP0 for detup transactions.
+ * handle: PCD handle.
+ * return: USB status.
+ */
+static enum usb_status usb_dwc2_activate_setup(void *handle)
+{
+	uintptr_t usb_base_addr = (uintptr_t)handle;
+	uintptr_t reg_offset = usb_base_addr + OTG_DIEP_BASE;
+
+	/* Set the MPS of the IN EP based on the enumeration speed */
+	mmio_clrbits_32(reg_offset + OTG_DIEPCTL, OTG_DIEPCTL_MPSIZ);
+
+	if ((mmio_read_32(usb_base_addr + OTG_DSTS) & OTG_DSTS_ENUMSPD_MASK) ==
+	    OTG_DSTS_ENUMSPD_LS_PHY_6MHZ) {
+		mmio_setbits_32(reg_offset + OTG_DIEPCTL, 3U);
+	}
+
+	mmio_setbits_32(usb_base_addr + OTG_DCTL, OTG_DCTL_CGINAK);
+
+	return USBD_OK;
+}
+
+/*
+ * Prepare the EP0 to start the first control setup.
+ * handle: Selected device.
+ * return: USB status.
+ */
+static enum usb_status usb_dwc2_ep0_out_start(void *handle)
+{
+	uintptr_t usb_base_addr = (uintptr_t)handle;
+	uintptr_t reg_offset = usb_base_addr + OTG_DIEP_BASE + OTG_DIEPTSIZ;
+	uint32_t reg_value = 0U;
+
+	/* PKTCNT = 1 and XFRSIZ = 24 bytes for endpoint 0 */
+	reg_value |= OTG_DIEPTSIZ_PKTCNT_1;
+	reg_value |= (EP0_FIFO_SIZE & OTG_DIEPTSIZ_XFRSIZ);
+	reg_value |= OTG_DOEPTSIZ_RXDPID_STUPCNT;
+
+	mmio_write_32(reg_offset, reg_value);
+
+	return USBD_OK;
+}
+
+/*
+ * Write a packet into the TX FIFO associated with the EP/channel.
+ * handle: Selected device.
+ * src: Pointer to source buffer.
+ * ch_ep_num: Endpoint or host channel number.
+ * len: Number of bytes to write.
+ * return: USB status.
+ */
+static enum usb_status usb_dwc2_write_packet(void *handle, uint8_t *src,
+					  uint8_t ch_ep_num, uint16_t len)
+{
+	uint32_t reg_offset;
+	uint32_t count32b = (len + 3U) / 4U;
+	uint32_t i;
+
+	reg_offset = (uintptr_t)handle + OTG_FIFO_BASE +
+		     (ch_ep_num * OTG_FIFO_SIZE);
+
+	for (i = 0U; i < count32b; i++) {
+		uint32_t src_copy = 0U;
+		uint32_t j;
+
+		/* Data written to FIFO need to be 4 bytes aligned */
+		for (j = 0U; j < 4U; j++) {
+			src_copy += (*(src + j)) << (8U * j);
+		}
+
+		mmio_write_32(reg_offset, src_copy);
+		src += 4U;
+	}
+
+	return USBD_OK;
+}
+
+/*
+ * Read a packet from the RX FIFO associated with the EP/channel.
+ * handle: Selected device.
+ * dst: Destination pointer.
+ * len: Number of bytes to read.
+ * return: Pointer to destination buffer.
+ */
+static void *usb_dwc2_read_packet(void *handle, uint8_t *dest, uint16_t len)
+{
+	uint32_t reg_offset;
+	uint32_t count32b = (len + 3U) / 4U;
+	uint32_t i;
+
+	VERBOSE("read packet length %i to 0x%lx\n", len, (uintptr_t)dest);
+
+	reg_offset = (uintptr_t)handle + OTG_FIFO_BASE;
+
+	for (i = 0U; i < count32b; i++) {
+		*(uint32_t *)dest = mmio_read_32(reg_offset);
+		dest += 4U;
+		dsb();
+	}
+
+	return (void *)dest;
+}
+
+/*
+ * Setup and start a transfer over an EP.
+ * handle: Selected device
+ * ep: Pointer to endpoint structure.
+ * return: USB status.
+ */
+static enum usb_status usb_dwc2_ep_start_xfer(void *handle, struct usbd_ep *ep)
+{
+	uintptr_t usb_base_addr = (uintptr_t)handle;
+	uint32_t reg_offset;
+	uint32_t reg_value;
+	uint32_t clear_value;
+
+	if (ep->is_in) {
+		reg_offset = usb_base_addr + OTG_DIEP_BASE + (ep->num * OTG_DIEP_SIZE);
+		clear_value = OTG_DIEPTSIZ_PKTCNT | OTG_DIEPTSIZ_XFRSIZ;
+		if (ep->xfer_len == 0U) {
+			reg_value = OTG_DIEPTSIZ_PKTCNT_1;
+		} else {
+			/*
+			 * Program the transfer size and packet count
+			 * as follows:
+			 * xfersize = N * maxpacket + short_packet
+			 * pktcnt = N + (short_packet exist ? 1 : 0)
+			 */
+			reg_value = (OTG_DIEPTSIZ_PKTCNT &
+				     (((ep->xfer_len + ep->maxpacket - 1U) /
+				       ep->maxpacket) << OTG_DIEPTSIZ_PKTCNT_SHIFT))
+				    | ep->xfer_len;
+
+			if (ep->type == EP_TYPE_ISOC) {
+				clear_value |= OTG_DIEPTSIZ_MCNT_MASK;
+				reg_value |= OTG_DIEPTSIZ_MCNT_DATA0;
+			}
+		}
+
+		mmio_clrsetbits_32(reg_offset + OTG_DIEPTSIZ, clear_value, reg_value);
+
+		if ((ep->type != EP_TYPE_ISOC) && (ep->xfer_len > 0U)) {
+			/* Enable the TX FIFO empty interrupt for this EP */
+			mmio_setbits_32(usb_base_addr + OTG_DIEPEMPMSK, BIT(ep->num));
+		}
+
+		/* EP enable, IN data in FIFO */
+		reg_value = OTG_DIEPCTL_CNAK | OTG_DIEPCTL_EPENA;
+
+		if (ep->type == EP_TYPE_ISOC) {
+			if ((mmio_read_32(usb_base_addr + OTG_DSTS) & OTG_DSTS_FNSOF0) == 0U) {
+				reg_value |= OTG_DIEPCTL_SODDFRM;
+			} else {
+				reg_value |= OTG_DIEPCTL_SD0PID_SEVNFRM;
+			}
+		}
+
+		mmio_setbits_32(reg_offset + OTG_DIEPCTL, reg_value);
+
+		if (ep->type == EP_TYPE_ISOC) {
+			usb_dwc2_write_packet(handle, ep->xfer_buff, ep->num, ep->xfer_len);
+		}
+	} else {
+		reg_offset = usb_base_addr + OTG_DOEP_BASE + (ep->num * OTG_DOEP_SIZE);
+		/*
+		 * Program the transfer size and packet count as follows:
+		 * pktcnt = N
+		 * xfersize = N * maxpacket
+		 */
+		if (ep->xfer_len == 0U) {
+			reg_value = ep->maxpacket | OTG_DIEPTSIZ_PKTCNT_1;
+		} else {
+			uint16_t pktcnt = (ep->xfer_len + ep->maxpacket - 1U) / ep->maxpacket;
+
+			reg_value = (pktcnt << OTG_DIEPTSIZ_PKTCNT_SHIFT) |
+				    (ep->maxpacket * pktcnt);
+		}
+
+		mmio_clrsetbits_32(reg_offset + OTG_DOEPTSIZ,
+				   OTG_DOEPTSIZ_XFRSIZ & OTG_DOEPTSIZ_PKTCNT,
+				   reg_value);
+
+		/* EP enable */
+		reg_value = OTG_DOEPCTL_CNAK | OTG_DOEPCTL_EPENA;
+
+		if (ep->type == EP_TYPE_ISOC) {
+			if ((mmio_read_32(usb_base_addr + OTG_DSTS) & OTG_DSTS_FNSOF0) == 0U) {
+				reg_value |= OTG_DOEPCTL_SD1PID_SODDFRM;
+			} else {
+				reg_value |= OTG_DOEPCTL_SD0PID_SEVNFRM;
+			}
+		}
+
+		mmio_setbits_32(reg_offset + OTG_DOEPCTL, reg_value);
+	}
+
+	return USBD_OK;
+}
+
+/*
+ * Setup and start a transfer over the EP0.
+ * handle: Selected device.
+ * ep: Pointer to endpoint structure.
+ * return: USB status.
+ */
+static enum usb_status usb_dwc2_ep0_start_xfer(void *handle, struct usbd_ep *ep)
+{
+	uintptr_t usb_base_addr = (uintptr_t)handle;
+	uint32_t reg_offset;
+	uint32_t reg_value;
+
+	if (ep->is_in) {
+		reg_offset = usb_base_addr + OTG_DIEP_BASE +
+			     (ep->num * OTG_DIEP_SIZE);
+
+		if (ep->xfer_len == 0U) {
+			reg_value = OTG_DIEPTSIZ_PKTCNT_1;
+		} else {
+			/*
+			 * Program the transfer size and packet count
+			 * as follows:
+			 * xfersize = N * maxpacket + short_packet
+			 * pktcnt = N + (short_packet exist ? 1 : 0)
+			 */
+
+			if (ep->xfer_len > ep->maxpacket) {
+				ep->xfer_len = ep->maxpacket;
+			}
+
+			reg_value = OTG_DIEPTSIZ_PKTCNT_1 | ep->xfer_len;
+		}
+
+		mmio_clrsetbits_32(reg_offset + OTG_DIEPTSIZ,
+				   OTG_DIEPTSIZ_XFRSIZ | OTG_DIEPTSIZ_PKTCNT,
+				   reg_value);
+
+		/* Enable the TX FIFO empty interrupt for this EP */
+		if (ep->xfer_len > 0U) {
+			mmio_setbits_32(usb_base_addr +	OTG_DIEPEMPMSK,
+					BIT(ep->num));
+		}
+
+		/* EP enable, IN data in FIFO */
+		mmio_setbits_32(reg_offset + OTG_DIEPCTL,
+				OTG_DIEPCTL_CNAK | OTG_DIEPCTL_EPENA);
+	} else {
+		reg_offset = usb_base_addr + OTG_DOEP_BASE +
+			     (ep->num * OTG_DOEP_SIZE);
+
+		/*
+		 * Program the transfer size and packet count as follows:
+		 * pktcnt = N
+		 * xfersize = N * maxpacket
+		 */
+		if (ep->xfer_len > 0U) {
+			ep->xfer_len = ep->maxpacket;
+		}
+
+		reg_value = OTG_DIEPTSIZ_PKTCNT_1 | ep->maxpacket;
+
+		mmio_clrsetbits_32(reg_offset + OTG_DIEPTSIZ,
+				   OTG_DIEPTSIZ_XFRSIZ | OTG_DIEPTSIZ_PKTCNT,
+				   reg_value);
+
+		/* EP enable */
+		mmio_setbits_32(reg_offset + OTG_DOEPCTL,
+				OTG_DOEPCTL_CNAK | OTG_DOEPCTL_EPENA);
+	}
+
+	return USBD_OK;
+}
+
+/*
+ * Set a stall condition over an EP.
+ * handle: Selected device.
+ * ep: Pointer to endpoint structure.
+ * return: USB status.
+ */
+static enum usb_status usb_dwc2_ep_set_stall(void *handle, struct usbd_ep *ep)
+{
+	uintptr_t usb_base_addr = (uintptr_t)handle;
+	uint32_t reg_offset;
+	uint32_t reg_value;
+
+	if (ep->is_in) {
+		reg_offset = usb_base_addr + OTG_DIEP_BASE +
+			     (ep->num * OTG_DIEP_SIZE);
+		reg_value = mmio_read_32(reg_offset + OTG_DIEPCTL);
+
+		if ((reg_value & OTG_DIEPCTL_EPENA) == 0U) {
+			reg_value &= ~OTG_DIEPCTL_EPDIS;
+		}
+
+		reg_value |= OTG_DIEPCTL_STALL;
+
+		mmio_write_32(reg_offset + OTG_DIEPCTL, reg_value);
+	} else {
+		reg_offset = usb_base_addr + OTG_DOEP_BASE +
+			     (ep->num * OTG_DOEP_SIZE);
+		reg_value = mmio_read_32(reg_offset + OTG_DOEPCTL);
+
+		if ((reg_value & OTG_DOEPCTL_EPENA) == 0U) {
+			reg_value &= ~OTG_DOEPCTL_EPDIS;
+		}
+
+		reg_value |= OTG_DOEPCTL_STALL;
+
+		mmio_write_32(reg_offset + OTG_DOEPCTL, reg_value);
+	}
+
+	return USBD_OK;
+}
+
+/*
+ * Stop the USB device mode.
+ * handle: Selected device.
+ * return: USB status.
+ */
+static enum usb_status usb_dwc2_stop_device(void *handle)
+{
+	uintptr_t usb_base_addr = (uintptr_t)handle;
+	uint32_t i;
+
+	/* Disable Int */
+	mmio_clrbits_32(usb_base_addr + OTG_GAHBCFG, OTG_GAHBCFG_GINT);
+
+	/* Clear pending interrupts */
+	for (i = 0U; i < EP_NB; i++) {
+		mmio_write_32(usb_base_addr + OTG_DIEP_BASE + (i * OTG_DIEP_SIZE) + OTG_DIEPINT,
+			      OTG_DIEPINT_MASK);
+		mmio_write_32(usb_base_addr + OTG_DOEP_BASE + (i * OTG_DOEP_SIZE) + OTG_DOEPINT,
+			      OTG_DOEPINT_MASK);
+	}
+
+	mmio_write_32(usb_base_addr + OTG_DAINT, OTG_DAINT_IN_MASK | OTG_DAINT_OUT_MASK);
+
+	/* Clear interrupt masks */
+	mmio_write_32(usb_base_addr + OTG_DIEPMSK, 0U);
+	mmio_write_32(usb_base_addr + OTG_DOEPMSK, 0U);
+	mmio_write_32(usb_base_addr + OTG_DAINTMSK, 0U);
+
+	/* Flush the FIFO */
+	usb_dwc2_flush_rx_fifo(handle);
+	usb_dwc2_flush_tx_fifo(handle, EP_ALL);
+
+	/* Disconnect the USB device by disabling the pull-up/pull-down */
+	mmio_setbits_32((uintptr_t)handle + OTG_DCTL, OTG_DCTL_SDIS);
+
+	return USBD_OK;
+}
+
+/*
+ * Stop the USB device mode.
+ * handle: Selected device.
+ * address: New device address to be assigned.
+ *         This parameter can be a value from 0 to 255.
+ * return: USB status.
+ */
+static enum usb_status usb_dwc2_set_address(void *handle, uint8_t address)
+{
+	uintptr_t usb_base_addr = (uintptr_t)handle;
+
+	mmio_clrsetbits_32(usb_base_addr + OTG_DCFG,
+			   OTG_DCFG_DAD,
+			   address << OTG_DCFG_DAD_SHIFT);
+
+	return USBD_OK;
+}
+
+/*
+ * Check FIFO for the next packet to be loaded.
+ * handle: Selected device.
+ * epnum : Endpoint number.
+ * xfer_len: Block length.
+ * xfer_count: Number of blocks.
+ * maxpacket: Max packet length.
+ * xfer_buff: Buffer pointer.
+ * return: USB status.
+ */
+static enum usb_status usb_dwc2_write_empty_tx_fifo(void *handle,
+						    uint32_t epnum,
+						    uint32_t xfer_len,
+						    uint32_t *xfer_count,
+						    uint32_t maxpacket,
+						    uint8_t **xfer_buff)
+{
+	uintptr_t usb_base_addr = (uintptr_t)handle;
+	uint32_t reg_offset;
+	int32_t len;
+	uint32_t len32b;
+	enum usb_status ret;
+
+	len = xfer_len - *xfer_count;
+
+	if ((len > 0) && ((uint32_t)len > maxpacket)) {
+		len = maxpacket;
+	}
+
+	len32b = (len + 3U) / 4U;
+
+	reg_offset = usb_base_addr + OTG_DIEP_BASE + (epnum * OTG_DIEP_SIZE);
+
+	while (((mmio_read_32(reg_offset + OTG_DTXFSTS) &
+		OTG_DTXFSTS_INEPTFSAV) > len32b) &&
+	       (*xfer_count < xfer_len) && (xfer_len != 0U)) {
+		/* Write the FIFO */
+		len = xfer_len - *xfer_count;
+
+		if ((len > 0) && ((uint32_t)len > maxpacket)) {
+			len = maxpacket;
+		}
+
+		len32b = (len + 3U) / 4U;
+
+		ret = usb_dwc2_write_packet(handle, *xfer_buff, epnum, len);
+		if (ret != USBD_OK) {
+			return ret;
+		}
+
+		*xfer_buff  += len;
+		*xfer_count += len;
+	}
+
+	if (len <= 0) {
+		mmio_clrbits_32(usb_base_addr + OTG_DIEPEMPMSK, BIT(epnum));
+	}
+
+	return USBD_OK;
+}
+
+/*
+ * Handle PCD interrupt request.
+ * handle: PCD handle.
+ * param: Pointer to information updated by the IT handling.
+ * return: Action to do after IT handling.
+ */
+static enum usb_action usb_dwc2_it_handler(void *handle, uint32_t *param)
+{
+	uintptr_t usb_base_addr = (uintptr_t)handle;
+	uint32_t ep_intr;
+	uint32_t epint;
+	uint32_t epnum;
+	uint32_t temp;
+	enum usb_status ret;
+
+	if (usb_dwc2_get_mode(handle) != USB_OTG_MODE_DEVICE) {
+		return USB_NOTHING;
+	}
+
+	/* Avoid spurious interrupt */
+	if (usb_dwc2_read_int(handle) == 0U) {
+		return USB_NOTHING;
+	}
+
+	if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_MMIS) != 0U) {
+		/* Incorrect mode, acknowledge the interrupt */
+		mmio_write_32(usb_base_addr + OTG_GINTSTS, OTG_GINTSTS_MMIS);
+	}
+
+	if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_OEPINT) != 0U) {
+		uint32_t reg_offset;
+
+		/* Read in the device interrupt bits */
+		ep_intr = usb_dwc2_all_out_ep_int(handle);
+		epnum = 0U;
+		while ((ep_intr & BIT(0)) != BIT(0)) {
+			epnum++;
+			ep_intr >>= 1;
+		}
+
+		reg_offset = usb_base_addr + OTG_DOEP_BASE + (epnum * OTG_DOEP_SIZE) + OTG_DOEPINT;
+
+		epint = usb_dwc2_out_ep_int(handle, epnum);
+
+		if ((epint & OTG_DOEPINT_XFRC) == OTG_DOEPINT_XFRC) {
+			mmio_write_32(reg_offset, OTG_DOEPINT_XFRC);
+			*param = epnum;
+
+			return USB_DATA_OUT;
+		}
+
+		if ((epint & OTG_DOEPINT_STUP) == OTG_DOEPINT_STUP) {
+			/* Inform  that a setup packet is available */
+			mmio_write_32(reg_offset, OTG_DOEPINT_STUP);
+
+			return USB_SETUP;
+		}
+
+		if ((epint & OTG_DOEPINT_OTEPDIS) == OTG_DOEPINT_OTEPDIS) {
+			mmio_write_32(reg_offset, OTG_DOEPINT_OTEPDIS);
+		}
+	}
+
+	if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_IEPINT) != 0U) {
+		uint32_t reg_offset;
+
+		/* Read in the device interrupt bits */
+		ep_intr = usb_dwc2_all_in_ep_int(handle);
+		epnum = 0U;
+		while ((ep_intr & BIT(0)) != BIT(0)) {
+			epnum++;
+			ep_intr >>= 1;
+		}
+
+		reg_offset = usb_base_addr + OTG_DIEP_BASE + (epnum * OTG_DIEP_SIZE) + OTG_DIEPINT;
+
+		epint = usb_dwc2_in_ep_int(handle, epnum);
+
+		if ((epint & OTG_DIEPINT_XFRC) == OTG_DIEPINT_XFRC) {
+			mmio_clrbits_32(usb_base_addr + OTG_DIEPEMPMSK, BIT(epnum));
+			mmio_write_32(reg_offset, OTG_DIEPINT_XFRC);
+			*param = epnum;
+
+			return USB_DATA_IN;
+		}
+
+		if ((epint & OTG_DIEPINT_TOC) == OTG_DIEPINT_TOC) {
+			mmio_write_32(reg_offset, OTG_DIEPINT_TOC);
+		}
+
+		if ((epint & OTG_DIEPINT_ITTXFE) == OTG_DIEPINT_ITTXFE) {
+			mmio_write_32(reg_offset, OTG_DIEPINT_ITTXFE);
+		}
+
+		if ((epint & OTG_DIEPINT_INEPNE) == OTG_DIEPINT_INEPNE) {
+			mmio_write_32(reg_offset, OTG_DIEPINT_INEPNE);
+		}
+
+		if ((epint & OTG_DIEPINT_EPDISD) == OTG_DIEPINT_EPDISD) {
+			mmio_write_32(reg_offset, OTG_DIEPINT_EPDISD);
+		}
+
+		if ((epint & OTG_DIEPINT_TXFE) == OTG_DIEPINT_TXFE) {
+			*param = epnum;
+
+			return USB_WRITE_EMPTY;
+		}
+	}
+
+	/* Handle resume interrupt */
+	if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_WKUPINT) != 0U) {
+		INFO("handle USB : Resume\n");
+
+		/* Clear the remote wake-up signaling */
+		mmio_clrbits_32(usb_base_addr + OTG_DCTL, OTG_DCTL_RWUSIG);
+		mmio_write_32(usb_base_addr + OTG_GINTSTS, OTG_GINTSTS_WKUPINT);
+
+		return USB_RESUME;
+	}
+
+	/* Handle suspend interrupt */
+	if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_USBSUSP) != 0U) {
+		INFO("handle USB : Suspend int\n");
+
+		mmio_write_32(usb_base_addr + OTG_GINTSTS, OTG_GINTSTS_USBSUSP);
+
+		if ((mmio_read_32(usb_base_addr + OTG_DSTS) &
+		     OTG_DSTS_SUSPSTS) == OTG_DSTS_SUSPSTS) {
+			return USB_SUSPEND;
+		}
+	}
+
+	/* Handle LPM interrupt */
+	if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_LPMINT) != 0U) {
+		INFO("handle USB : LPM int enter in suspend\n");
+
+		mmio_write_32(usb_base_addr + OTG_GINTSTS, OTG_GINTSTS_LPMINT);
+		*param = (mmio_read_32(usb_base_addr + OTG_GLPMCFG) &
+			  OTG_GLPMCFG_BESL) >> 2;
+
+		return USB_LPM;
+	}
+
+	/* Handle reset interrupt */
+	if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_USBRST) != 0U) {
+		INFO("handle USB : Reset\n");
+
+		mmio_clrbits_32(usb_base_addr + OTG_DCTL, OTG_DCTL_RWUSIG);
+
+		usb_dwc2_flush_tx_fifo(handle, 0U);
+
+		mmio_write_32(usb_base_addr + OTG_DAINT, OTG_DAINT_IN_MASK | OTG_DAINT_OUT_MASK);
+		mmio_setbits_32(usb_base_addr + OTG_DAINTMSK, OTG_DAINT_EP0_IN | OTG_DAINT_EP0_OUT);
+
+		mmio_setbits_32(usb_base_addr + OTG_DOEPMSK, OTG_DOEPMSK_STUPM |
+							     OTG_DOEPMSK_XFRCM |
+							     OTG_DOEPMSK_EPDM);
+		mmio_setbits_32(usb_base_addr + OTG_DIEPMSK, OTG_DIEPMSK_TOM |
+							     OTG_DIEPMSK_XFRCM |
+							     OTG_DIEPMSK_EPDM);
+
+		/* Set default address to 0 */
+		mmio_clrbits_32(usb_base_addr + OTG_DCFG, OTG_DCFG_DAD);
+
+		/* Setup EP0 to receive SETUP packets */
+		ret = usb_dwc2_ep0_out_start(handle);
+		if (ret != USBD_OK) {
+			return ret;
+		}
+
+		mmio_write_32(usb_base_addr + OTG_GINTSTS, OTG_GINTSTS_USBRST);
+
+		return USB_RESET;
+	}
+
+	/* Handle enumeration done interrupt */
+	if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_ENUMDNE) != 0U) {
+		ret = usb_dwc2_activate_setup(handle);
+		if (ret != USBD_OK) {
+			return ret;
+		}
+
+		mmio_clrbits_32(usb_base_addr + OTG_GUSBCFG, OTG_GUSBCFG_TRDT);
+
+		mmio_setbits_32(usb_base_addr + OTG_GUSBCFG,
+				(USBD_HS_TRDT_VALUE << OTG_GUSBCFG_TRDT_SHIFT) & OTG_GUSBCFG_TRDT);
+
+		mmio_write_32(usb_base_addr + OTG_GINTSTS, OTG_GINTSTS_ENUMDNE);
+
+		return USB_ENUM_DONE;
+	}
+
+	/* Handle RXQLevel interrupt */
+	if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_RXFLVL) != 0U) {
+		mmio_clrbits_32(usb_base_addr + OTG_GINTMSK,
+				OTG_GINTSTS_RXFLVL);
+
+		temp = mmio_read_32(usb_base_addr + OTG_GRXSTSP);
+
+		*param = temp & OTG_GRXSTSP_EPNUM;
+		*param |= (temp & OTG_GRXSTSP_BCNT) << (USBD_OUT_COUNT_SHIFT -
+							OTG_GRXSTSP_BCNT_SHIFT);
+
+		if (((temp & OTG_GRXSTSP_PKTSTS) >> OTG_GRXSTSP_PKTSTS_SHIFT) == STS_DATA_UPDT) {
+			if ((temp & OTG_GRXSTSP_BCNT) != 0U) {
+				mmio_setbits_32(usb_base_addr + OTG_GINTMSK, OTG_GINTSTS_RXFLVL);
+
+				return USB_READ_DATA_PACKET;
+			}
+		} else if (((temp & OTG_GRXSTSP_PKTSTS) >> OTG_GRXSTSP_PKTSTS_SHIFT) ==
+			    STS_SETUP_UPDT) {
+			mmio_setbits_32(usb_base_addr + OTG_GINTMSK, OTG_GINTSTS_RXFLVL);
+
+			return USB_READ_SETUP_PACKET;
+		}
+
+		mmio_setbits_32(usb_base_addr + OTG_GINTMSK, OTG_GINTSTS_RXFLVL);
+	}
+
+	/* Handle SOF interrupt */
+	if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_SOF) != 0U) {
+		INFO("handle USB : SOF\n");
+
+		mmio_write_32(usb_base_addr + OTG_GINTSTS, OTG_GINTSTS_SOF);
+
+		return USB_SOF;
+	}
+
+	/* Handle incomplete ISO IN interrupt */
+	if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_IISOIXFR) != 0U) {
+		INFO("handle USB : ISO IN\n");
+
+		mmio_write_32(usb_base_addr + OTG_GINTSTS,
+			      OTG_GINTSTS_IISOIXFR);
+	}
+
+	/* Handle incomplete ISO OUT interrupt */
+	if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_IPXFR_INCOMPISOOUT) !=
+	    0U) {
+		INFO("handle USB : ISO OUT\n");
+
+		mmio_write_32(usb_base_addr + OTG_GINTSTS,
+			      OTG_GINTSTS_IPXFR_INCOMPISOOUT);
+	}
+
+	/* Handle connection event interrupt */
+	if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_SRQINT) != 0U) {
+		INFO("handle USB : Connect\n");
+
+		mmio_write_32(usb_base_addr + OTG_GINTSTS, OTG_GINTSTS_SRQINT);
+	}
+
+	/* Handle disconnection event interrupt */
+	if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_OTGINT) != 0U) {
+		INFO("handle USB : Disconnect\n");
+
+		temp = mmio_read_32(usb_base_addr + OTG_GOTGINT);
+
+		if ((temp & OTG_GOTGINT_SEDET) == OTG_GOTGINT_SEDET) {
+			return USB_DISCONNECT;
+		}
+	}
+
+	return USB_NOTHING;
+}
+
+/*
+ * Start the usb device mode
+ * usb_core_handle: USB core driver handle.
+ * return  USB status.
+ */
+static enum usb_status usb_dwc2_start_device(void *handle)
+{
+	uintptr_t usb_base_addr = (uintptr_t)handle;
+
+	mmio_clrbits_32(usb_base_addr + OTG_DCTL, OTG_DCTL_SDIS);
+	mmio_setbits_32(usb_base_addr + OTG_GAHBCFG, OTG_GAHBCFG_GINT);
+
+	return USBD_OK;
+}
+
+static const struct usb_driver usb_dwc2driver = {
+	.ep0_out_start = usb_dwc2_ep0_out_start,
+	.ep_start_xfer = usb_dwc2_ep_start_xfer,
+	.ep0_start_xfer = usb_dwc2_ep0_start_xfer,
+	.write_packet = usb_dwc2_write_packet,
+	.read_packet = usb_dwc2_read_packet,
+	.ep_set_stall = usb_dwc2_ep_set_stall,
+	.start_device = usb_dwc2_start_device,
+	.stop_device = usb_dwc2_stop_device,
+	.set_address = usb_dwc2_set_address,
+	.write_empty_tx_fifo = usb_dwc2_write_empty_tx_fifo,
+	.it_handler = usb_dwc2_it_handler
+};
+
+/*
+ * Initialize USB DWC2 driver.
+ * usb_core_handle: USB core driver handle.
+ * pcd_handle: PCD handle.
+ * base_register: USB global register base address.
+ */
+void stm32mp1_usb_init_driver(struct usb_handle *usb_core_handle,
+			      struct pcd_handle *pcd_handle,
+			      void *base_register)
+{
+	register_usb_driver(usb_core_handle, pcd_handle, &usb_dwc2driver,
+			    base_register);
+}
diff --git a/drivers/usb/usb_device.c b/drivers/usb/usb_device.c
new file mode 100644
index 0000000..8f73a6b
--- /dev/null
+++ b/drivers/usb/usb_device.c
@@ -0,0 +1,843 @@
+/*
+ * Copyright (c) 2021, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <stdint.h>
+
+#include <common/debug.h>
+#include <drivers/usb_device.h>
+
+/* Define for EP address */
+#define EP_DIR_MASK		BIT(7)
+#define EP_DIR_IN		BIT(7)
+#define EP_NUM_MASK		GENMASK(3, 0)
+
+#define EP0_IN			(0U | EP_DIR_IN)
+#define EP0_OUT			0U
+
+/* USB address between 1 through 127 = 0x7F mask */
+#define ADDRESS_MASK		GENMASK(6, 0)
+
+/*
+ * Set a STALL condition over an endpoint
+ * pdev: USB handle
+ * ep_addr: endpoint address
+ * return : status
+ */
+static enum usb_status usb_core_set_stall(struct usb_handle *pdev, uint8_t ep_addr)
+{
+	struct usbd_ep *ep;
+	struct pcd_handle *hpcd = (struct pcd_handle *)pdev->data;
+	uint8_t num;
+
+	num = ep_addr & EP_NUM_MASK;
+	if (num >= USBD_EP_NB) {
+		return USBD_FAIL;
+	}
+	if ((EP_DIR_MASK & ep_addr) == EP_DIR_IN) {
+		ep = &hpcd->in_ep[num];
+		ep->is_in = true;
+	} else {
+		ep = &hpcd->out_ep[num];
+		ep->is_in = false;
+	}
+	ep->num = num;
+
+	pdev->driver->ep_set_stall(hpcd->instance, ep);
+	if (num == 0U) {
+		pdev->driver->ep0_out_start(hpcd->instance);
+	}
+
+	return USBD_OK;
+}
+
+/*
+ * usb_core_get_desc
+ *         Handle Get Descriptor requests
+ * pdev : device instance
+ * req : usb request
+ */
+static void usb_core_get_desc(struct usb_handle *pdev, struct usb_setup_req *req)
+{
+	uint16_t len;
+	uint8_t *pbuf;
+	uint8_t desc_type = HIBYTE(req->value);
+	uint8_t desc_idx = LOBYTE(req->value);
+
+	switch (desc_type) {
+	case USB_DESC_TYPE_DEVICE:
+		pbuf = pdev->desc->get_device_desc(&len);
+		break;
+
+	case USB_DESC_TYPE_CONFIGURATION:
+		pbuf = (uint8_t *)pdev->desc->get_config_desc(&len);
+		pbuf[1] = USB_DESC_TYPE_CONFIGURATION;
+		break;
+
+	case USB_DESC_TYPE_STRING:
+		switch (desc_idx) {
+		case USBD_IDX_LANGID_STR:
+			pbuf = pdev->desc->get_lang_id_desc(&len);
+			break;
+
+		case USBD_IDX_MFC_STR:
+			pbuf = pdev->desc->get_manufacturer_desc(&len);
+			break;
+
+		case USBD_IDX_PRODUCT_STR:
+			pbuf = pdev->desc->get_product_desc(&len);
+			break;
+
+		case USBD_IDX_SERIAL_STR:
+			pbuf = pdev->desc->get_serial_desc(&len);
+			break;
+
+		case USBD_IDX_CONFIG_STR:
+			pbuf = pdev->desc->get_configuration_desc(&len);
+			break;
+
+		case USBD_IDX_INTERFACE_STR:
+			pbuf = pdev->desc->get_interface_desc(&len);
+			break;
+
+		/* For all USER string */
+		case USBD_IDX_USER0_STR:
+		default:
+			pbuf = pdev->desc->get_usr_desc(desc_idx - USBD_IDX_USER0_STR, &len);
+			break;
+		}
+		break;
+
+	case USB_DESC_TYPE_DEVICE_QUALIFIER:
+		pbuf = (uint8_t *)pdev->desc->get_device_qualifier_desc(&len);
+		break;
+
+	case USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION:
+		pbuf = (uint8_t *)pdev->desc->get_config_desc(&len);
+		pbuf[1] = USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION;
+		break;
+
+	default:
+		ERROR("Unknown request %i\n", desc_type);
+		usb_core_ctl_error(pdev);
+		return;
+	}
+
+	if ((len != 0U) && (req->length != 0U)) {
+		len = MIN(len, req->length);
+
+		/* Start the transfer */
+		usb_core_transmit_ep0(pdev, pbuf, len);
+	}
+}
+
+/*
+ * usb_core_set_config
+ *         Handle Set device configuration request
+ * pdev : device instance
+ * req : usb request
+ */
+static void usb_core_set_config(struct usb_handle *pdev, struct usb_setup_req *req)
+{
+	static uint8_t cfgidx;
+
+	cfgidx = LOBYTE(req->value);
+
+	if (cfgidx > USBD_MAX_NUM_CONFIGURATION) {
+		usb_core_ctl_error(pdev);
+		return;
+	}
+
+	switch (pdev->dev_state) {
+	case USBD_STATE_ADDRESSED:
+		if (cfgidx != 0U) {
+			pdev->dev_config = cfgidx;
+			pdev->dev_state = USBD_STATE_CONFIGURED;
+			if (!pdev->class) {
+				usb_core_ctl_error(pdev);
+				return;
+			}
+			/* Set configuration and Start the Class */
+			if (pdev->class->init(pdev, cfgidx) != 0U) {
+				usb_core_ctl_error(pdev);
+				return;
+			}
+		}
+		break;
+
+	case USBD_STATE_CONFIGURED:
+		if (cfgidx == 0U) {
+			pdev->dev_state = USBD_STATE_ADDRESSED;
+			pdev->dev_config = cfgidx;
+			pdev->class->de_init(pdev, cfgidx);
+		} else if (cfgidx != pdev->dev_config) {
+			if (pdev->class == NULL) {
+				usb_core_ctl_error(pdev);
+				return;
+			}
+			/* Clear old configuration */
+			pdev->class->de_init(pdev, pdev->dev_config);
+			/* Set new configuration */
+			pdev->dev_config = cfgidx;
+			/* Set configuration and start the USB class */
+			if (pdev->class->init(pdev, cfgidx) != 0U) {
+				usb_core_ctl_error(pdev);
+				return;
+			}
+		}
+		break;
+
+	default:
+		usb_core_ctl_error(pdev);
+		return;
+	}
+
+	/* Send status */
+	usb_core_transmit_ep0(pdev, NULL, 0U);
+}
+
+/*
+ * usb_core_get_status
+ *         Handle Get Status request
+ * pdev : device instance
+ * req : usb request
+ */
+static void usb_core_get_status(struct usb_handle *pdev,
+				struct usb_setup_req *req)
+{
+	if ((pdev->dev_state != USBD_STATE_ADDRESSED) &&
+	    (pdev->dev_state != USBD_STATE_CONFIGURED)) {
+		usb_core_ctl_error(pdev);
+		return;
+	}
+
+	pdev->dev_config_status = USB_CONFIG_SELF_POWERED;
+
+	if (pdev->dev_remote_wakeup != 0U) {
+		pdev->dev_config_status |= USB_CONFIG_REMOTE_WAKEUP;
+	}
+
+	/* Start the transfer */
+	usb_core_transmit_ep0(pdev, (uint8_t *)&pdev->dev_config_status, 2U);
+}
+
+/*
+ * usb_core_set_address
+ *         Set device address
+ * pdev : device instance
+ * req : usb request
+ */
+static void usb_core_set_address(struct usb_handle *pdev,
+				 struct usb_setup_req *req)
+{
+	uint8_t dev_addr;
+
+	if ((req->index != 0U) || (req->length != 0U)) {
+		usb_core_ctl_error(pdev);
+		return;
+	}
+
+	dev_addr = req->value & ADDRESS_MASK;
+	if (pdev->dev_state != USBD_STATE_DEFAULT) {
+		usb_core_ctl_error(pdev);
+		return;
+	}
+
+	pdev->dev_address = dev_addr;
+	pdev->driver->set_address(((struct pcd_handle *)(pdev->data))->instance, dev_addr);
+
+	/* Send status */
+	usb_core_transmit_ep0(pdev, NULL, 0U);
+
+	if (dev_addr != 0U) {
+		pdev->dev_state  = USBD_STATE_ADDRESSED;
+	} else {
+		pdev->dev_state  = USBD_STATE_DEFAULT;
+	}
+}
+
+/*
+ * usb_core_dev_req
+ *         Handle standard usb device requests
+ * pdev : device instance
+ * req : usb request
+ * return : status
+ */
+static enum usb_status usb_core_dev_req(struct usb_handle *pdev,
+					struct usb_setup_req *req)
+{
+	VERBOSE("receive request %i\n", req->b_request);
+	switch (req->b_request) {
+	case USB_REQ_GET_DESCRIPTOR:
+		usb_core_get_desc(pdev, req);
+		break;
+
+	case USB_REQ_SET_CONFIGURATION:
+		usb_core_set_config(pdev, req);
+		break;
+
+	case USB_REQ_GET_STATUS:
+		usb_core_get_status(pdev, req);
+		break;
+
+	case USB_REQ_SET_ADDRESS:
+		usb_core_set_address(pdev, req);
+		break;
+
+	case USB_REQ_GET_CONFIGURATION:
+	case USB_REQ_SET_FEATURE:
+	case USB_REQ_CLEAR_FEATURE:
+	default:
+		ERROR("NOT SUPPORTED %i\n", req->b_request);
+		usb_core_ctl_error(pdev);
+		break;
+	}
+
+	return USBD_OK;
+}
+
+/*
+ * usb_core_itf_req
+ *         Handle standard usb interface requests
+ * pdev : device instance
+ * req : usb request
+ * return : status
+ */
+static enum usb_status usb_core_itf_req(struct usb_handle *pdev,
+					struct usb_setup_req *req)
+{
+	if (pdev->dev_state != USBD_STATE_CONFIGURED) {
+		usb_core_ctl_error(pdev);
+		return USBD_OK;
+	}
+
+	if (LOBYTE(req->index) <= USBD_MAX_NUM_INTERFACES) {
+		pdev->class->setup(pdev, req);
+
+		if (req->length == 0U) {
+			usb_core_transmit_ep0(pdev, NULL, 0U);
+		}
+	} else {
+		usb_core_ctl_error(pdev);
+	}
+
+	return USBD_OK;
+}
+
+/*
+ * usb_core_setup_stage
+ *         Handle the setup stage
+ * pdev: device instance
+ * psetup : setup buffer
+ * return : status
+ */
+static enum usb_status usb_core_setup_stage(struct usb_handle *pdev,
+					    uint8_t *psetup)
+{
+	struct usb_setup_req *req = &pdev->request;
+
+	/* Copy setup buffer into req structure */
+	req->bm_request = psetup[0];
+	req->b_request = psetup[1];
+	req->value = psetup[2] + (psetup[3] << 8);
+	req->index = psetup[4] + (psetup[5] << 8);
+	req->length = psetup[6] + (psetup[7] << 8);
+
+	pdev->ep0_state = USBD_EP0_SETUP;
+	pdev->ep0_data_len = pdev->request.length;
+
+	switch (pdev->request.bm_request & USB_REQ_RECIPIENT_MASK) {
+	case USB_REQ_RECIPIENT_DEVICE:
+		usb_core_dev_req(pdev, &pdev->request);
+		break;
+
+	case USB_REQ_RECIPIENT_INTERFACE:
+		usb_core_itf_req(pdev, &pdev->request);
+		break;
+
+	case USB_REQ_RECIPIENT_ENDPOINT:
+	default:
+		ERROR("receive unsupported request %i",
+		      pdev->request.bm_request & USB_REQ_RECIPIENT_MASK);
+		usb_core_set_stall(pdev, pdev->request.bm_request & USB_REQ_DIRECTION);
+		return USBD_FAIL;
+	}
+
+	return USBD_OK;
+}
+
+/*
+ * usb_core_data_out
+ *         Handle data OUT stage
+ * pdev: device instance
+ * epnum: endpoint index
+ * pdata: buffer to sent
+ * return : status
+ */
+static enum usb_status usb_core_data_out(struct usb_handle *pdev, uint8_t epnum,
+					 uint8_t *pdata)
+{
+	struct usb_endpoint *pep;
+
+	if (epnum == 0U) {
+		pep = &pdev->ep_out[0];
+		if (pdev->ep0_state == USBD_EP0_DATA_OUT) {
+			if (pep->rem_length > pep->maxpacket) {
+				pep->rem_length -= pep->maxpacket;
+
+				usb_core_receive(pdev, 0U, pdata,
+						 MIN(pep->rem_length,
+						     pep->maxpacket));
+			} else {
+				if (pdev->class->ep0_rx_ready &&
+				    (pdev->dev_state == USBD_STATE_CONFIGURED)) {
+					pdev->class->ep0_rx_ready(pdev);
+				}
+
+				usb_core_transmit_ep0(pdev, NULL, 0U);
+			}
+		}
+	} else if (pdev->class->data_out != NULL &&
+		   (pdev->dev_state == USBD_STATE_CONFIGURED)) {
+		pdev->class->data_out(pdev, epnum);
+	}
+
+	return USBD_OK;
+}
+
+/*
+ * usb_core_data_in
+ *         Handle data in stage
+ * pdev: device instance
+ * epnum: endpoint index
+ * pdata: buffer to fill
+ * return : status
+ */
+static enum usb_status usb_core_data_in(struct usb_handle *pdev, uint8_t epnum,
+					uint8_t *pdata)
+{
+	if (epnum == 0U) {
+		struct usb_endpoint *pep = &pdev->ep_in[0];
+
+		if (pdev->ep0_state == USBD_EP0_DATA_IN) {
+			if (pep->rem_length > pep->maxpacket) {
+				pep->rem_length -= pep->maxpacket;
+
+				usb_core_transmit(pdev, 0U, pdata,
+						  pep->rem_length);
+
+				/* Prepare EP for premature end of transfer */
+				usb_core_receive(pdev, 0U, NULL, 0U);
+			} else {
+				/* Last packet is MPS multiple, send ZLP packet */
+				if ((pep->total_length % pep->maxpacket == 0U) &&
+				    (pep->total_length >= pep->maxpacket) &&
+				    (pep->total_length < pdev->ep0_data_len)) {
+					usb_core_transmit(pdev, 0U, NULL, 0U);
+
+					pdev->ep0_data_len = 0U;
+
+					/* Prepare endpoint for premature end of transfer */
+					usb_core_receive(pdev, 0U, NULL, 0U);
+				} else {
+					if (pdev->class->ep0_tx_sent != NULL &&
+					    (pdev->dev_state ==
+					     USBD_STATE_CONFIGURED)) {
+						pdev->class->ep0_tx_sent(pdev);
+					}
+					/* Start the transfer */
+					usb_core_receive_ep0(pdev, NULL, 0U);
+				}
+			}
+		}
+	} else if ((pdev->class->data_in != NULL) &&
+		  (pdev->dev_state == USBD_STATE_CONFIGURED)) {
+		pdev->class->data_in(pdev, epnum);
+	}
+
+	return USBD_OK;
+}
+
+/*
+ * usb_core_suspend
+ *         Handle suspend event
+ * pdev : device instance
+ * return : status
+ */
+static enum usb_status usb_core_suspend(struct usb_handle  *pdev)
+{
+	INFO("USB Suspend mode\n");
+	pdev->dev_old_state =  pdev->dev_state;
+	pdev->dev_state  = USBD_STATE_SUSPENDED;
+
+	return USBD_OK;
+}
+
+/*
+ * usb_core_resume
+ *         Handle resume event
+ * pdev : device instance
+ * return : status
+ */
+static enum usb_status usb_core_resume(struct usb_handle *pdev)
+{
+	INFO("USB Resume\n");
+	pdev->dev_state = pdev->dev_old_state;
+
+	return USBD_OK;
+}
+
+/*
+ * usb_core_sof
+ *         Handle SOF event
+ * pdev : device instance
+ * return : status
+ */
+static enum usb_status usb_core_sof(struct usb_handle *pdev)
+{
+	if (pdev->dev_state == USBD_STATE_CONFIGURED) {
+		if (pdev->class->sof != NULL) {
+			pdev->class->sof(pdev);
+		}
+	}
+
+	return USBD_OK;
+}
+
+/*
+ * usb_core_disconnect
+ *         Handle device disconnection event
+ * pdev : device instance
+ * return : status
+ */
+static enum usb_status usb_core_disconnect(struct usb_handle *pdev)
+{
+	/* Free class resources */
+	pdev->dev_state = USBD_STATE_DEFAULT;
+	pdev->class->de_init(pdev, pdev->dev_config);
+
+	return USBD_OK;
+}
+
+enum usb_status usb_core_handle_it(struct usb_handle *pdev)
+{
+	uint32_t param = 0U;
+	uint32_t len = 0U;
+	struct usbd_ep *ep;
+
+	switch (pdev->driver->it_handler(pdev->data->instance, &param)) {
+	case USB_DATA_OUT:
+		usb_core_data_out(pdev, param,
+				  pdev->data->out_ep[param].xfer_buff);
+		break;
+
+	case USB_DATA_IN:
+		usb_core_data_in(pdev, param,
+				 pdev->data->in_ep[param].xfer_buff);
+		break;
+
+	case USB_SETUP:
+		usb_core_setup_stage(pdev, (uint8_t *)pdev->data->setup);
+		break;
+
+	case USB_ENUM_DONE:
+		break;
+
+	case USB_READ_DATA_PACKET:
+		ep = &pdev->data->out_ep[param &  USBD_OUT_EPNUM_MASK];
+		len = (param &  USBD_OUT_COUNT_MASK) >> USBD_OUT_COUNT_SHIFT;
+		pdev->driver->read_packet(pdev->data->instance,
+					  ep->xfer_buff, len);
+		ep->xfer_buff += len;
+		ep->xfer_count += len;
+		break;
+
+	case USB_READ_SETUP_PACKET:
+		ep = &pdev->data->out_ep[param &  USBD_OUT_EPNUM_MASK];
+		len = (param &  USBD_OUT_COUNT_MASK) >> 0x10;
+		pdev->driver->read_packet(pdev->data->instance,
+					  (uint8_t *)pdev->data->setup, 8);
+		ep->xfer_count += len;
+		break;
+
+	case USB_RESET:
+		pdev->dev_state = USBD_STATE_DEFAULT;
+		break;
+
+	case USB_RESUME:
+		if (pdev->data->lpm_state == LPM_L1) {
+			pdev->data->lpm_state = LPM_L0;
+		} else {
+			usb_core_resume(pdev);
+		}
+		break;
+
+	case USB_SUSPEND:
+		usb_core_suspend(pdev);
+		break;
+
+	case USB_LPM:
+		if (pdev->data->lpm_state == LPM_L0) {
+			pdev->data->lpm_state = LPM_L1;
+		} else {
+			usb_core_suspend(pdev);
+		}
+		break;
+
+	case USB_SOF:
+		usb_core_sof(pdev);
+		break;
+
+	case USB_DISCONNECT:
+		usb_core_disconnect(pdev);
+		break;
+
+	case USB_WRITE_EMPTY:
+		pdev->driver->write_empty_tx_fifo(pdev->data->instance, param,
+				     pdev->data->in_ep[param].xfer_len,
+				     (uint32_t *)&pdev->data->in_ep[param].xfer_count,
+				     pdev->data->in_ep[param].maxpacket,
+				     &pdev->data->in_ep[param].xfer_buff);
+		break;
+
+	case USB_NOTHING:
+	default:
+		break;
+	}
+
+	return USBD_OK;
+}
+
+static void usb_core_start_xfer(struct usb_handle *pdev,
+				void *handle,
+				struct usbd_ep *ep)
+{
+	if (ep->num == 0U) {
+		pdev->driver->ep0_start_xfer(handle, ep);
+	} else {
+		pdev->driver->ep_start_xfer(handle, ep);
+	}
+}
+
+/*
+ * usb_core_receive
+ *          Receive an amount of data
+ * pdev: USB handle
+ * ep_addr: endpoint address
+ * buf: pointer to the reception buffer
+ * len: amount of data to be received
+ * return : status
+ */
+enum usb_status usb_core_receive(struct usb_handle *pdev, uint8_t ep_addr,
+				 uint8_t *buf, uint32_t len)
+{
+	struct usbd_ep *ep;
+	struct pcd_handle *hpcd = (struct pcd_handle *)pdev->data;
+	uint8_t num;
+
+	num = ep_addr & EP_NUM_MASK;
+	if (num >= USBD_EP_NB) {
+		return USBD_FAIL;
+	}
+	ep = &hpcd->out_ep[num];
+
+	/* Setup and start the Xfer */
+	ep->xfer_buff = buf;
+	ep->xfer_len = len;
+	ep->xfer_count = 0U;
+	ep->is_in = false;
+	ep->num = num;
+
+	usb_core_start_xfer(pdev, hpcd->instance, ep);
+
+	return USBD_OK;
+}
+
+/*
+ * usb_core_transmit
+ *          Send an amount of data
+ * pdev: USB handle
+ * ep_addr: endpoint address
+ * buf: pointer to the transmission buffer
+ * len: amount of data to be sent
+ * return : status
+ */
+enum usb_status usb_core_transmit(struct usb_handle *pdev, uint8_t ep_addr,
+				  uint8_t *buf, uint32_t len)
+{
+	struct usbd_ep *ep;
+	struct pcd_handle *hpcd = (struct pcd_handle *)pdev->data;
+	uint8_t num;
+
+	num = ep_addr & EP_NUM_MASK;
+	if (num >= USBD_EP_NB) {
+		return USBD_FAIL;
+	}
+	ep = &hpcd->in_ep[num];
+
+	/* Setup and start the Xfer */
+	ep->xfer_buff = buf;
+	ep->xfer_len = len;
+	ep->xfer_count = 0U;
+	ep->is_in = true;
+	ep->num = num;
+
+	usb_core_start_xfer(pdev, hpcd->instance, ep);
+
+	return USBD_OK;
+}
+
+/*
+ * usb_core_receive_ep0
+ *          Receive an amount of data on ep0
+ * pdev: USB handle
+ * buf: pointer to the reception buffer
+ * len: amount of data to be received
+ * return : status
+ */
+enum usb_status usb_core_receive_ep0(struct usb_handle *pdev, uint8_t *buf,
+				     uint32_t len)
+{
+	/* Prepare the reception of the buffer over EP0 */
+	if (len != 0U) {
+		pdev->ep0_state = USBD_EP0_DATA_OUT;
+	} else {
+		pdev->ep0_state = USBD_EP0_STATUS_OUT;
+	}
+
+	pdev->ep_out[0].total_length = len;
+	pdev->ep_out[0].rem_length = len;
+
+	/* Start the transfer */
+	return usb_core_receive(pdev, 0U, buf, len);
+}
+
+/*
+ * usb_core_transmit_ep0
+ *          Send an amount of data on ep0
+ * pdev: USB handle
+ * buf: pointer to the transmission buffer
+ * len: amount of data to be sent
+ * return : status
+ */
+enum usb_status usb_core_transmit_ep0(struct usb_handle *pdev, uint8_t *buf,
+				      uint32_t len)
+{
+	/* Set EP0 State */
+	if (len != 0U) {
+		pdev->ep0_state = USBD_EP0_DATA_IN;
+	} else {
+		pdev->ep0_state = USBD_EP0_STATUS_IN;
+	}
+
+	pdev->ep_in[0].total_length = len;
+	pdev->ep_in[0].rem_length = len;
+
+	/* Start the transfer */
+	return usb_core_transmit(pdev, 0U, buf, len);
+}
+
+/*
+ * usb_core_ctl_error
+ *         Handle USB low level error
+ * pdev: device instance
+ * req: usb request
+ * return : None
+ */
+
+void usb_core_ctl_error(struct usb_handle *pdev)
+{
+	ERROR("%s : Send an ERROR\n", __func__);
+	usb_core_set_stall(pdev, EP0_IN);
+	usb_core_set_stall(pdev, EP0_OUT);
+}
+
+/*
+ * usb_core_start
+ *         Start the USB device core.
+ * pdev: Device Handle
+ * return : USBD Status
+ */
+enum usb_status usb_core_start(struct usb_handle *pdev)
+{
+	/* Start the low level driver */
+	pdev->driver->start_device(pdev->data->instance);
+
+	return USBD_OK;
+}
+
+/*
+ * usb_core_stop
+ *         Stop the USB device core.
+ * pdev: Device Handle
+ * return : USBD Status
+ */
+enum usb_status usb_core_stop(struct usb_handle *pdev)
+{
+	/* Free class resources */
+	pdev->class->de_init(pdev, pdev->dev_config);
+
+	/* Stop the low level driver */
+	pdev->driver->stop_device(pdev->data->instance);
+
+	return USBD_OK;
+}
+
+/*
+ * register_usb_driver
+ *         Stop the USB device core.
+ * pdev: Device Handle
+ * pcd_handle: PCD handle
+ * driver: USB driver
+ * driver_handle: USB driver handle
+ * return : USBD Status
+ */
+enum usb_status register_usb_driver(struct usb_handle *pdev,
+				    struct pcd_handle *pcd_handle,
+				    const struct usb_driver *driver,
+				    void *driver_handle)
+{
+	uint8_t i;
+
+	assert(pdev != NULL);
+	assert(pcd_handle != NULL);
+	assert(driver != NULL);
+	assert(driver_handle != NULL);
+
+	/* Free class resources */
+	pdev->driver = driver;
+	pdev->data = pcd_handle;
+	pdev->data->instance = driver_handle;
+	pdev->dev_state = USBD_STATE_DEFAULT;
+	pdev->ep0_state = USBD_EP0_IDLE;
+
+	/* Copy endpoint information */
+	for (i = 0U; i < USBD_EP_NB; i++) {
+		pdev->ep_in[i].maxpacket = pdev->data->in_ep[i].maxpacket;
+		pdev->ep_out[i].maxpacket = pdev->data->out_ep[i].maxpacket;
+	}
+
+	return USBD_OK;
+}
+
+/*
+ * register_platform
+ *         Register the USB device core.
+ * pdev: Device Handle
+ * plat_call_back: callback
+ * return : USBD Status
+ */
+enum usb_status register_platform(struct usb_handle *pdev,
+			       const struct usb_desc *plat_call_back)
+{
+	assert(pdev != NULL);
+	assert(plat_call_back != NULL);
+
+	/* Save platform info in class resources */
+	pdev->desc = plat_call_back;
+
+	return USBD_OK;
+}
diff --git a/fdts/stm32mp15-bl2.dtsi b/fdts/stm32mp15-bl2.dtsi
index da95b25..074414b 100644
--- a/fdts/stm32mp15-bl2.dtsi
+++ b/fdts/stm32mp15-bl2.dtsi
@@ -4,6 +4,12 @@
  */
 
 / {
+#if !STM32MP_EMMC && !STM32MP_SDMMC
+	aliases {
+		/delete-property/ mmc0;
+	};
+#endif
+
 	cpus {
 		/delete-node/ cpu@1;
 	};
@@ -13,9 +19,25 @@
 	soc {
 		/delete-node/ timer@40006000;
 		/delete-node/ timer@44006000;
+#if !STM32MP_USB_PROGRAMMER
+		/delete-node/ usb-otg@49000000;
+#endif
 		/delete-node/ pwr_mcu@50001014;
 		/delete-node/ cryp@54001000;
 		/delete-node/ rng@54003000;
+#if !STM32MP_RAW_NAND
+		/delete-node/ memory-controller@58002000;
+#endif
+#if !STM32MP_SPI_NAND && !STM32MP_SPI_NOR
+		/delete-node/ spi@58003000;
+#endif
+#if !STM32MP_EMMC && !STM32MP_SDMMC
+		/delete-node/ mmc@58005000;
+		/delete-node/ mmc@58007000;
+#endif
+#if !STM32MP_USB_PROGRAMMER
+		/delete-node/ usbphyc@5a006000;
+#endif
 		/delete-node/ spi@5c001000;
 		/delete-node/ rtc@5c004000;
 		/delete-node/ etzpc@5c007000;
@@ -24,7 +46,25 @@
 		/delete-node/ tamp@5c00a000;
 
 		pin-controller@50002000 {
-			/delete-node/ rtc-out2-rmp-pins-0;
+#if !STM32MP_RAW_NAND
+			/delete-node/ fmc-0;
+#endif
+#if !STM32MP_SPI_NAND && !STM32MP_SPI_NOR
+			/delete-node/ qspi-clk-0;
+			/delete-node/ qspi-bk1-0;
+			/delete-node/ qspi-bk2-0;
+#endif
+#if !STM32MP_EMMC && !STM32MP_SDMMC
+			/delete-node/ sdmmc1-b4-0;
+			/delete-node/ sdmmc1-dir-0;
+			/delete-node/ sdmmc2-b4-0;
+			/delete-node/ sdmmc2-b4-1;
+			/delete-node/ sdmmc2-d47-0;
+#endif
+#if !STM32MP_USB_PROGRAMMER
+			/delete-node/ usbotg_hs-0;
+			/delete-node/ usbotg-fs-dp-dm-0;
+#endif
 		};
 	};
 
diff --git a/fdts/stm32mp15-bl32.dtsi b/fdts/stm32mp15-bl32.dtsi
index f005d56..ca4bb3e 100644
--- a/fdts/stm32mp15-bl32.dtsi
+++ b/fdts/stm32mp15-bl32.dtsi
@@ -20,8 +20,8 @@
 		/delete-node/ hash@54002000;
 		/delete-node/ memory-controller@58002000;
 		/delete-node/ spi@58003000;
-		/delete-node/ sdmmc@58005000;
-		/delete-node/ sdmmc@58007000;
+		/delete-node/ mmc@58005000;
+		/delete-node/ mmc@58007000;
 		/delete-node/ usbphyc@5a006000;
 		/delete-node/ spi@5c001000;
 		/delete-node/ stgen@5c008000;
@@ -37,6 +37,8 @@
 			/delete-node/ sdmmc2-b4-0;
 			/delete-node/ sdmmc2-b4-1;
 			/delete-node/ sdmmc2-d47-0;
+			/delete-node/ sdmmc2-d47-1;
+			/delete-node/ sdmmc2-d47-3;
 			/delete-node/ usbotg_hs-0;
 			/delete-node/ usbotg-fs-dp-dm-0;
 		};
diff --git a/fdts/stm32mp15-ddr.dtsi b/fdts/stm32mp15-ddr.dtsi
index 4825691..e5efd92 100644
--- a/fdts/stm32mp15-ddr.dtsi
+++ b/fdts/stm32mp15-ddr.dtsi
@@ -1,153 +1,127 @@
 // SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
 /*
- * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
+ * Copyright (C) 2018-2021, STMicroelectronics - All Rights Reserved
  */
 
-/ {
-	soc {
-		ddr: ddr@5a003000{
+&ddr {
+	st,mem-name = DDR_MEM_NAME;
+	st,mem-speed = <DDR_MEM_SPEED>;
+	st,mem-size = <DDR_MEM_SIZE>;
 
-			compatible = "st,stm32mp1-ddr";
+	st,ctl-reg = <
+		DDR_MSTR
+		DDR_MRCTRL0
+		DDR_MRCTRL1
+		DDR_DERATEEN
+		DDR_DERATEINT
+		DDR_PWRCTL
+		DDR_PWRTMG
+		DDR_HWLPCTL
+		DDR_RFSHCTL0
+		DDR_RFSHCTL3
+		DDR_CRCPARCTL0
+		DDR_ZQCTL0
+		DDR_DFITMG0
+		DDR_DFITMG1
+		DDR_DFILPCFG0
+		DDR_DFIUPD0
+		DDR_DFIUPD1
+		DDR_DFIUPD2
+		DDR_DFIPHYMSTR
+		DDR_ODTMAP
+		DDR_DBG0
+		DDR_DBG1
+		DDR_DBGCMD
+		DDR_POISONCFG
+		DDR_PCCFG
+	>;
 
-			reg = <0x5A003000 0x550
-			       0x5A004000 0x234>;
+	st,ctl-timing = <
+		DDR_RFSHTMG
+		DDR_DRAMTMG0
+		DDR_DRAMTMG1
+		DDR_DRAMTMG2
+		DDR_DRAMTMG3
+		DDR_DRAMTMG4
+		DDR_DRAMTMG5
+		DDR_DRAMTMG6
+		DDR_DRAMTMG7
+		DDR_DRAMTMG8
+		DDR_DRAMTMG14
+		DDR_ODTCFG
+	>;
 
-			clocks = <&rcc AXIDCG>,
-				 <&rcc DDRC1>,
-				 <&rcc DDRC2>,
-				 <&rcc DDRPHYC>,
-				 <&rcc DDRCAPB>,
-				 <&rcc DDRPHYCAPB>;
+	st,ctl-map = <
+		DDR_ADDRMAP1
+		DDR_ADDRMAP2
+		DDR_ADDRMAP3
+		DDR_ADDRMAP4
+		DDR_ADDRMAP5
+		DDR_ADDRMAP6
+		DDR_ADDRMAP9
+		DDR_ADDRMAP10
+		DDR_ADDRMAP11
+	>;
 
-			clock-names = "axidcg",
-				      "ddrc1",
-				      "ddrc2",
-				      "ddrphyc",
-				      "ddrcapb",
-				      "ddrphycapb";
+	st,ctl-perf = <
+		DDR_SCHED
+		DDR_SCHED1
+		DDR_PERFHPR1
+		DDR_PERFLPR1
+		DDR_PERFWR1
+		DDR_PCFGR_0
+		DDR_PCFGW_0
+		DDR_PCFGQOS0_0
+		DDR_PCFGQOS1_0
+		DDR_PCFGWQOS0_0
+		DDR_PCFGWQOS1_0
+		DDR_PCFGR_1
+		DDR_PCFGW_1
+		DDR_PCFGQOS0_1
+		DDR_PCFGQOS1_1
+		DDR_PCFGWQOS0_1
+		DDR_PCFGWQOS1_1
+	>;
 
-			st,mem-name = DDR_MEM_NAME;
-			st,mem-speed = <DDR_MEM_SPEED>;
-			st,mem-size = <DDR_MEM_SIZE>;
+	st,phy-reg = <
+		DDR_PGCR
+		DDR_ACIOCR
+		DDR_DXCCR
+		DDR_DSGCR
+		DDR_DCR
+		DDR_ODTCR
+		DDR_ZQ0CR1
+		DDR_DX0GCR
+		DDR_DX1GCR
+		DDR_DX2GCR
+		DDR_DX3GCR
+	>;
 
-			st,ctl-reg = <
-				DDR_MSTR
-				DDR_MRCTRL0
-				DDR_MRCTRL1
-				DDR_DERATEEN
-				DDR_DERATEINT
-				DDR_PWRCTL
-				DDR_PWRTMG
-				DDR_HWLPCTL
-				DDR_RFSHCTL0
-				DDR_RFSHCTL3
-				DDR_CRCPARCTL0
-				DDR_ZQCTL0
-				DDR_DFITMG0
-				DDR_DFITMG1
-				DDR_DFILPCFG0
-				DDR_DFIUPD0
-				DDR_DFIUPD1
-				DDR_DFIUPD2
-				DDR_DFIPHYMSTR
-				DDR_ODTMAP
-				DDR_DBG0
-				DDR_DBG1
-				DDR_DBGCMD
-				DDR_POISONCFG
-				DDR_PCCFG
-			>;
+	st,phy-timing = <
+		DDR_PTR0
+		DDR_PTR1
+		DDR_PTR2
+		DDR_DTPR0
+		DDR_DTPR1
+		DDR_DTPR2
+		DDR_MR0
+		DDR_MR1
+		DDR_MR2
+		DDR_MR3
+	>;
 
-			st,ctl-timing = <
-				DDR_RFSHTMG
-				DDR_DRAMTMG0
-				DDR_DRAMTMG1
-				DDR_DRAMTMG2
-				DDR_DRAMTMG3
-				DDR_DRAMTMG4
-				DDR_DRAMTMG5
-				DDR_DRAMTMG6
-				DDR_DRAMTMG7
-				DDR_DRAMTMG8
-				DDR_DRAMTMG14
-				DDR_ODTCFG
-			>;
-
-			st,ctl-map = <
-				DDR_ADDRMAP1
-				DDR_ADDRMAP2
-				DDR_ADDRMAP3
-				DDR_ADDRMAP4
-				DDR_ADDRMAP5
-				DDR_ADDRMAP6
-				DDR_ADDRMAP9
-				DDR_ADDRMAP10
-				DDR_ADDRMAP11
-			>;
-
-			st,ctl-perf = <
-				DDR_SCHED
-				DDR_SCHED1
-				DDR_PERFHPR1
-				DDR_PERFLPR1
-				DDR_PERFWR1
-				DDR_PCFGR_0
-				DDR_PCFGW_0
-				DDR_PCFGQOS0_0
-				DDR_PCFGQOS1_0
-				DDR_PCFGWQOS0_0
-				DDR_PCFGWQOS1_0
-				DDR_PCFGR_1
-				DDR_PCFGW_1
-				DDR_PCFGQOS0_1
-				DDR_PCFGQOS1_1
-				DDR_PCFGWQOS0_1
-				DDR_PCFGWQOS1_1
-			>;
-
-			st,phy-reg = <
-				DDR_PGCR
-				DDR_ACIOCR
-				DDR_DXCCR
-				DDR_DSGCR
-				DDR_DCR
-				DDR_ODTCR
-				DDR_ZQ0CR1
-				DDR_DX0GCR
-				DDR_DX1GCR
-				DDR_DX2GCR
-				DDR_DX3GCR
-			>;
-
-			st,phy-timing = <
-				DDR_PTR0
-				DDR_PTR1
-				DDR_PTR2
-				DDR_DTPR0
-				DDR_DTPR1
-				DDR_DTPR2
-				DDR_MR0
-				DDR_MR1
-				DDR_MR2
-				DDR_MR3
-			>;
-
-			st,phy-cal = <
-				DDR_DX0DLLCR
-				DDR_DX0DQTR
-				DDR_DX0DQSTR
-				DDR_DX1DLLCR
-				DDR_DX1DQTR
-				DDR_DX1DQSTR
-				DDR_DX2DLLCR
-				DDR_DX2DQTR
-				DDR_DX2DQSTR
-				DDR_DX3DLLCR
-				DDR_DX3DQTR
-				DDR_DX3DQSTR
-			>;
-
-			status = "okay";
-		};
-	};
+	st,phy-cal = <
+		DDR_DX0DLLCR
+		DDR_DX0DQTR
+		DDR_DX0DQSTR
+		DDR_DX1DLLCR
+		DDR_DX1DQTR
+		DDR_DX1DQSTR
+		DDR_DX2DLLCR
+		DDR_DX2DQTR
+		DDR_DX2DQSTR
+		DDR_DX3DLLCR
+		DDR_DX3DQTR
+		DDR_DX3DQSTR
+	>;
 };
diff --git a/fdts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi b/fdts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi
index c0fc1f7..c6d6434 100644
--- a/fdts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi
+++ b/fdts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
 /*
- * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2018-2021, STMicroelectronics - All Rights Reserved
  */
 
 /*
@@ -15,7 +15,7 @@
  * Save Date: 2020.02.20, save Time: 18:45:20
  */
 
-#define DDR_MEM_NAME	"DDR3-DDR3L 16bits 533000Khz"
+#define DDR_MEM_NAME	"DDR3-DDR3L 16bits 533000kHz"
 #define DDR_MEM_SPEED	533000
 #define DDR_MEM_SIZE	0x20000000
 
diff --git a/fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi b/fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi
index fc226d2..9614ab4 100644
--- a/fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi
+++ b/fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
 /*
- * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2018-2021, STMicroelectronics - All Rights Reserved
  */
 
 /*
@@ -15,7 +15,7 @@
  * Save Date: 2020.02.20, save Time: 18:49:33
  */
 
-#define DDR_MEM_NAME	"DDR3-DDR3L 32bits 533000Khz"
+#define DDR_MEM_NAME	"DDR3-DDR3L 32bits 533000kHz"
 #define DDR_MEM_SPEED	533000
 #define DDR_MEM_SIZE	0x40000000
 
diff --git a/fdts/stm32mp15-pinctrl.dtsi b/fdts/stm32mp15-pinctrl.dtsi
index 058cde2..d74dc2b 100644
--- a/fdts/stm32mp15-pinctrl.dtsi
+++ b/fdts/stm32mp15-pinctrl.dtsi
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
 /*
- * Copyright (C) STMicroelectronics 2017 - All Rights Reserved
+ * Copyright (c) 2017-2021, STMicroelectronics - All Rights Reserved
  * Author: Ludovic Barre <ludovic.barre@st.com> for STMicroelectronics.
  */
 #include <dt-bindings/pinctrl/stm32-pinfunc.h>
@@ -86,12 +86,6 @@
 		};
 	};
 
-	rtc_out2_rmp_pins_a: rtc-out2-rmp-pins-0 {
-		pins {
-			pinmux = <STM32_PINMUX('I', 8, ANALOG)>; /* RTC_OUT2_RMP */
-		};
-	};
-
 	sdmmc1_b4_pins_a: sdmmc1-b4-0 {
 		pins1 {
 			pinmux = <STM32_PINMUX('C', 8, AF12)>, /* SDMMC1_D0 */
@@ -176,6 +170,18 @@
 		};
 	};
 
+	sdmmc2_d47_pins_b: sdmmc2-d47-1 {
+		pins {
+			pinmux = <STM32_PINMUX('A', 8, AF9)>,  /* SDMMC2_D4 */
+				 <STM32_PINMUX('A', 9, AF10)>, /* SDMMC2_D5 */
+				 <STM32_PINMUX('C', 6, AF10)>, /* SDMMC2_D6 */
+				 <STM32_PINMUX('C', 7, AF10)>; /* SDMMC2_D7 */
+			slew-rate = <1>;
+			drive-push-pull;
+			bias-disable;
+		};
+	};
+
 	sdmmc2_d47_pins_d: sdmmc2-d47-3 {
 		pins {
 			pinmux = <STM32_PINMUX('A', 8, AF9)>, /* SDMMC2_D4 */
@@ -213,34 +219,90 @@
 
 	uart7_pins_a: uart7-0 {
 		pins1 {
-			pinmux = <STM32_PINMUX('E', 8, AF7)>; /* UART4_TX */
+			pinmux = <STM32_PINMUX('E', 8, AF7)>; /* UART7_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 */
+			pinmux = <STM32_PINMUX('E', 7, AF7)>, /* UART7_RX */
+				 <STM32_PINMUX('E', 10, AF7)>, /* UART7_CTS */
+				 <STM32_PINMUX('E', 9, AF7)>; /* UART7_RTS */
 			bias-disable;
 		};
 	};
 
 	uart7_pins_b: uart7-1 {
 		pins1 {
-			pinmux = <STM32_PINMUX('E', 8, AF7)>; /* USART7_TX */
+			pinmux = <STM32_PINMUX('F', 7, AF7)>; /* UART7_TX */
 			bias-disable;
 			drive-push-pull;
 			slew-rate = <0>;
 		};
 		pins2 {
-			pinmux = <STM32_PINMUX('E', 7, AF7)>; /* USART7_RX */
+			pinmux = <STM32_PINMUX('F', 6, AF7)>; /* UART7_RX */
+			bias-disable;
+		};
+	};
+
+	uart7_pins_c: uart7-2 {
+		pins1 {
+			pinmux = <STM32_PINMUX('E', 8, AF7)>; /* UART7_TX */
+			bias-disable;
+			drive-push-pull;
+			slew-rate = <0>;
+		};
+		pins2 {
+			pinmux = <STM32_PINMUX('E', 7, AF7)>; /* UART7_RX */
+			bias-disable;
+		};
+	};
+
+	uart8_pins_a: uart8-0 {
+		pins1 {
+			pinmux = <STM32_PINMUX('E', 1, AF8)>; /* UART8_TX */
+			bias-disable;
+			drive-push-pull;
+			slew-rate = <0>;
+		};
+		pins2 {
+			pinmux = <STM32_PINMUX('E', 0, AF8)>; /* UART8_RX */
 			bias-disable;
 		};
 	};
 
 	usart2_pins_a: usart2-0 {
 		pins1 {
+			pinmux = <STM32_PINMUX('F', 5, AF7)>, /* USART2_TX */
+				 <STM32_PINMUX('D', 4, AF7)>; /* USART2_RTS */
+			bias-disable;
+			drive-push-pull;
+			slew-rate = <0>;
+		};
+		pins2 {
+			pinmux = <STM32_PINMUX('D', 6, AF7)>, /* USART2_RX */
+				 <STM32_PINMUX('D', 3, AF7)>; /* USART2_CTS_NSS */
+			bias-disable;
+		};
+	};
+
+	usart2_pins_b: usart2-1 {
+		pins1 {
+			pinmux = <STM32_PINMUX('F', 5, AF7)>, /* USART2_TX */
+				 <STM32_PINMUX('A', 1, AF7)>; /* USART2_RTS */
+			bias-disable;
+			drive-push-pull;
+			slew-rate = <0>;
+		};
+		pins2 {
+			pinmux = <STM32_PINMUX('F', 4, AF7)>, /* USART2_RX */
+				 <STM32_PINMUX('E', 15, AF7)>; /* USART2_CTS_NSS */
+			bias-disable;
+		};
+	};
+
+	usart2_pins_c: usart2-2 {
+		pins1 {
 			pinmux = <STM32_PINMUX('D', 5, AF7)>, /* USART2_TX */
 				 <STM32_PINMUX('D', 4, AF7)>; /* USART2_RTS */
 			bias-disable;
@@ -256,15 +318,13 @@
 
 	usart3_pins_a: usart3-0 {
 		pins1 {
-			pinmux = <STM32_PINMUX('B', 10, AF7)>, /* USART3_TX */
-				 <STM32_PINMUX('G', 8, AF8)>; /* USART3_RTS */
+			pinmux = <STM32_PINMUX('B', 10, AF7)>; /* USART3_TX */
 			bias-disable;
 			drive-push-pull;
 			slew-rate = <0>;
 		};
 		pins2 {
-			pinmux = <STM32_PINMUX('B', 12, AF8)>, /* USART3_RX */
-				 <STM32_PINMUX('I', 10, AF8)>; /* USART3_CTS_NSS */
+			pinmux = <STM32_PINMUX('B', 12, AF8)>; /* USART3_RX */
 			bias-disable;
 		};
 	};
@@ -279,12 +339,27 @@
 		};
 		pins2 {
 			pinmux = <STM32_PINMUX('B', 12, AF8)>, /* USART3_RX */
+				 <STM32_PINMUX('I', 10, AF8)>; /* USART3_CTS_NSS */
+			bias-disable;
+		};
+	};
+
+	usart3_pins_c: usart3-2 {
+		pins1 {
+			pinmux = <STM32_PINMUX('B', 10, AF7)>, /* USART3_TX */
+				 <STM32_PINMUX('G', 8, AF8)>; /* USART3_RTS */
+			bias-disable;
+			drive-push-pull;
+			slew-rate = <0>;
+		};
+		pins2 {
+			pinmux = <STM32_PINMUX('B', 12, AF8)>, /* USART3_RX */
 				 <STM32_PINMUX('B', 13, AF7)>; /* USART3_CTS_NSS */
 			bias-disable;
 		};
 	};
 
-	usbotg_hs_pins_a: usbotg_hs-0 {
+	usbotg_hs_pins_a: usbotg-hs-0 {
 		pins {
 			pinmux = <STM32_PINMUX('A', 10, ANALOG)>; /* OTG_ID */
 		};
diff --git a/fdts/stm32mp151.dtsi b/fdts/stm32mp151.dtsi
index c350c66..ca93f0c 100644
--- a/fdts/stm32mp151.dtsi
+++ b/fdts/stm32mp151.dtsi
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
 /*
- * Copyright (C) STMicroelectronics 2017 - All Rights Reserved
+ * Copyright (c) 2017-2021, STMicroelectronics - All Rights Reserved
  * Author: Ludovic Barre <ludovic.barre@st.com> for STMicroelectronics.
  */
 #include <dt-bindings/interrupt-controller/arm-gic.h>
@@ -174,7 +174,7 @@
 		};
 
 		usbotg_hs: usb-otg@49000000 {
-			compatible = "st,stm32mp1-hsotg", "snps,dwc2";
+			compatible = "st,stm32mp15-hsotg", "snps,dwc2";
 			reg = <0x49000000 0x10000>;
 			clocks = <&rcc USBO_K>;
 			clock-names = "otg";
@@ -319,7 +319,7 @@
 			status = "disabled";
 		};
 
-		sdmmc1: sdmmc@58005000 {
+		sdmmc1: mmc@58005000 {
 			compatible = "st,stm32-sdmmc2", "arm,pl18x", "arm,primecell";
 			arm,primecell-periphid = <0x00253180>;
 			reg = <0x58005000 0x1000>, <0x58006000 0x1000>;
@@ -334,7 +334,7 @@
 			status = "disabled";
 		};
 
-		sdmmc2: sdmmc@58007000 {
+		sdmmc2: mmc@58007000 {
 			compatible = "st,stm32-sdmmc2", "arm,pl18x", "arm,primecell";
 			arm,primecell-periphid = <0x00253180>;
 			reg = <0x58007000 0x1000>, <0x58008000 0x1000>;
@@ -358,6 +358,24 @@
 			status = "disabled";
 		};
 
+		ddr: ddr@5a003000{
+			compatible = "st,stm32mp1-ddr";
+			reg = <0x5A003000 0x550 0x5A004000 0x234>;
+			clocks = <&rcc AXIDCG>,
+				 <&rcc DDRC1>,
+				 <&rcc DDRC2>,
+				 <&rcc DDRPHYC>,
+				 <&rcc DDRCAPB>,
+				 <&rcc DDRPHYCAPB>;
+			clock-names = "axidcg",
+				      "ddrc1",
+				      "ddrc2",
+				      "ddrphyc",
+				      "ddrcapb",
+				      "ddrphycapb";
+			status = "okay";
+		};
+
 		usbphyc: usbphyc@5a006000 {
 			#address-cells = <1>;
 			#size-cells = <0>;
@@ -434,7 +452,7 @@
 			status = "disabled";
 		};
 
-		bsec: nvmem@5c005000 {
+		bsec: efuse@5c005000 {
 			compatible = "st,stm32mp15-bsec";
 			reg = <0x5c005000 0x400>;
 			#address-cells = <1>;
diff --git a/fdts/stm32mp157c-ed1.dts b/fdts/stm32mp157c-ed1.dts
index a6b98b7..11e0a61 100644
--- a/fdts/stm32mp157c-ed1.dts
+++ b/fdts/stm32mp157c-ed1.dts
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
 /*
- * Copyright (C) STMicroelectronics 2017-2019 - All Rights Reserved
+ * Copyright (c) 2017-2021, STMicroelectronics - All Rights Reserved
  * Author: Ludovic Barre <ludovic.barre@st.com> for STMicroelectronics.
  */
 /dts-v1/;
@@ -20,7 +20,6 @@
 		stdout-path = "serial0:115200n8";
 	};
 
-
 	memory@c0000000 {
 		device_type = "memory";
 		reg = <0xC0000000 0x40000000>;
@@ -52,7 +51,7 @@
 };
 
 &cryp1 {
-	status="okay";
+	status = "okay";
 };
 
 &hash1 {
@@ -233,7 +232,7 @@
 		CLK_CKPER_HSE
 		CLK_FMC_ACLK
 		CLK_QSPI_ACLK
-		CLK_ETH_DISABLED
+		CLK_ETH_PLL4P
 		CLK_SDMMC12_PLL4P
 		CLK_DSI_DSIPLL
 		CLK_STGEN_HSE
@@ -269,25 +268,33 @@
 
 	/* VCO = 1300.0 MHz => P = 650 (CPU) */
 	pll1: st,pll@0 {
-		cfg = < 2 80 0 0 0 PQR(1,0,0) >;
-		frac = < 0x800 >;
+		compatible = "st,stm32mp1-pll";
+		reg = <0>;
+		cfg = <2 80 0 0 0 PQR(1,0,0)>;
+		frac = <0x800>;
 	};
 
 	/* 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 >;
+		compatible = "st,stm32mp1-pll";
+		reg = <1>;
+		cfg = <2 65 1 0 0 PQR(1,1,1)>;
+		frac = <0x1400>;
 	};
 
 	/* 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 >;
+		compatible = "st,stm32mp1-pll";
+		reg = <2>;
+		cfg = <1 33 1 16 36 PQR(1,1,1)>;
+		frac = <0x1a04>;
 	};
 
 	/* VCO = 594.0 MHz => P = 99, Q = 74, R = 74 */
 	pll4: st,pll@3 {
-		cfg = < 3 98 5 7 7 PQR(1,1,1) >;
+		compatible = "st,stm32mp1-pll";
+		reg = <3>;
+		cfg = <3 98 5 7 7 PQR(1,1,1)>;
 	};
 };
 
diff --git a/fdts/stm32mp157c-ev1.dts b/fdts/stm32mp157c-ev1.dts
index c5d12e3..02840a2 100644
--- a/fdts/stm32mp157c-ev1.dts
+++ b/fdts/stm32mp157c-ev1.dts
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
 /*
- * Copyright (C) STMicroelectronics 2017-2019 - All Rights Reserved
+ * Copyright (c) 2017-2021, STMicroelectronics - All Rights Reserved
  * Author: Ludovic Barre <ludovic.barre@st.com> for STMicroelectronics.
  */
 /dts-v1/;
@@ -57,6 +57,7 @@
 
 &usart3 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&usart3_pins_a>;
+	pinctrl-0 = <&usart3_pins_b>;
+	uart-has-rtscts;
 	status = "disabled";
 };
diff --git a/fdts/stm32mp157c-lxa-mc1.dts b/fdts/stm32mp157c-lxa-mc1.dts
index 7b8e481..6f67712 100644
--- a/fdts/stm32mp157c-lxa-mc1.dts
+++ b/fdts/stm32mp157c-lxa-mc1.dts
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-3-Clause) */
 /*
- * Copyright (C) 2020 STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2020-2021, STMicroelectronics - All Rights Reserved
  * Copyright (C) 2020 Ahmad Fatoum, Pengutronix
  */
 
@@ -75,7 +75,7 @@
 
 &sdmmc2 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&sdmmc2_b4_pins_a &mc1_sdmmc2_d47_pins_b>;
+	pinctrl-0 = <&sdmmc2_b4_pins_a &sdmmc2_d47_pins_b>;
 	bus-width = <8>;
 	no-1-8-v;
 	no-sd;
@@ -91,17 +91,3 @@
 	pinctrl-0 = <&uart4_pins_a>;
 	status = "okay";
 };
-
-&pinctrl {
-	mc1_sdmmc2_d47_pins_b: mc1-sdmmc2-d47-1 {
-		pins {
-			pinmux = <STM32_PINMUX('A', 8, AF9)>,  /* SDMMC2_D4 */
-				 <STM32_PINMUX('A', 9, AF10)>, /* SDMMC2_D5 */
-				 <STM32_PINMUX('C', 6, AF10)>, /* SDMMC2_D6 */
-				 <STM32_PINMUX('C', 7, AF10)>; /* SDMMC2_D7 */
-			slew-rate = <1>;
-			drive-push-pull;
-			bias-disable;
-		};
-	};
-};
diff --git a/fdts/stm32mp15xx-dkx.dtsi b/fdts/stm32mp15xx-dkx.dtsi
index 52b914b..9cc5368 100644
--- a/fdts/stm32mp15xx-dkx.dtsi
+++ b/fdts/stm32mp15xx-dkx.dtsi
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
 /*
- * Copyright (C) STMicroelectronics 2019 - All Rights Reserved
+ * Copyright (c) 2019-2021, STMicroelectronics - All Rights Reserved
  * Author: Alexandre Torgue <alexandre.torgue@st.com> for STMicroelectronics.
  */
 
@@ -141,7 +141,6 @@
 				regulator-name = "vdd_usb";
 				regulator-min-microvolt = <3300000>;
 				regulator-max-microvolt = <3300000>;
-				regulator-always-on;
 			};
 
 			vdda: ldo5 {
@@ -223,7 +222,7 @@
 		CLK_CKPER_HSE
 		CLK_FMC_ACLK
 		CLK_QSPI_ACLK
-		CLK_ETH_DISABLED
+		CLK_ETH_PLL4P
 		CLK_SDMMC12_PLL4P
 		CLK_DSI_DSIPLL
 		CLK_STGEN_HSE
@@ -319,13 +318,13 @@
 
 &uart7 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&uart7_pins_b>;
+	pinctrl-0 = <&uart7_pins_c>;
 	status = "disabled";
 };
 
 &usart3 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&usart3_pins_b>;
+	pinctrl-0 = <&usart3_pins_c>;
 	uart-has-rtscts;
 	status = "disabled";
 };
diff --git a/fdts/stm32mp15xxaa-pinctrl.dtsi b/fdts/stm32mp15xxaa-pinctrl.dtsi
index 64e566b..f1d540a 100644
--- a/fdts/stm32mp15xxaa-pinctrl.dtsi
+++ b/fdts/stm32mp15xxaa-pinctrl.dtsi
@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
 /*
- * Copyright (C) STMicroelectronics 2019 - All Rights Reserved
- * Author: Alexandre Torgue <alexandre.torgue@st.com>
+ * Copyright (c) 2019-2021, STMicroelectronics - All Rights Reserved
+ * Author: Alexandre Torgue <alexandre.torgue@st.com> for STMicroelectronics.
  */
 
 &pinctrl {
diff --git a/fdts/stm32mp15xxab-pinctrl.dtsi b/fdts/stm32mp15xxab-pinctrl.dtsi
index d29af89..b58c7e2 100644
--- a/fdts/stm32mp15xxab-pinctrl.dtsi
+++ b/fdts/stm32mp15xxab-pinctrl.dtsi
@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
 /*
- * Copyright (C) STMicroelectronics 2019 - All Rights Reserved
- * Author: Alexandre Torgue <alexandre.torgue@st.com>
+ * Copyright (c) 2019-2021, STMicroelectronics - All Rights Reserved
+ * Author: Alexandre Torgue <alexandre.torgue@st.com> for STMicroelectronics.
  */
 
 &pinctrl {
diff --git a/fdts/stm32mp15xxac-pinctrl.dtsi b/fdts/stm32mp15xxac-pinctrl.dtsi
index 5d8199f..11e7e03 100644
--- a/fdts/stm32mp15xxac-pinctrl.dtsi
+++ b/fdts/stm32mp15xxac-pinctrl.dtsi
@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
 /*
- * Copyright (C) STMicroelectronics 2019 - All Rights Reserved
- * Author: Alexandre Torgue <alexandre.torgue@st.com>
+ * Copyright (c) 2019-2021, STMicroelectronics - All Rights Reserved
+ * Author: Alexandre Torgue <alexandre.torgue@st.com> for STMicroelectronics.
  */
 
 &pinctrl {
diff --git a/fdts/stm32mp15xxad-pinctrl.dtsi b/fdts/stm32mp15xxad-pinctrl.dtsi
index 023f540..52806d6 100644
--- a/fdts/stm32mp15xxad-pinctrl.dtsi
+++ b/fdts/stm32mp15xxad-pinctrl.dtsi
@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
 /*
- * Copyright (C) STMicroelectronics 2019 - All Rights Reserved
- * Author: Alexandre Torgue <alexandre.torgue@st.com>
+ * Copyright (c) 2019-2021, STMicroelectronics - All Rights Reserved
+ * Author: Alexandre Torgue <alexandre.torgue@st.com> for STMicroelectronics.
  */
 
 &pinctrl {
diff --git a/include/arch/aarch64/el2_common_macros.S b/include/arch/aarch64/el2_common_macros.S
index c57a1ec..7bf4806 100644
--- a/include/arch/aarch64/el2_common_macros.S
+++ b/include/arch/aarch64/el2_common_macros.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -82,10 +82,6 @@
 	 * Initialise MDCR_EL2, setting all fields rather than relying on
 	 * hw. Some fields are architecturally UNKNOWN on reset.
 	 *
-	 * MDCR_EL2.SDD: Set to one to disable AArch64 Secure self-hosted
-	 *  debug. Debug exceptions, other than Breakpoint Instruction
-	 *  exceptions, are disabled from all ELs in Secure state.
-	 *
 	 * MDCR_EL2.TDOSA: Set to zero so that EL2 and EL2 System register
 	 *  access to the powerdown debug registers do not trap to EL2.
 	 *
@@ -97,17 +93,7 @@
 	 *  register accesses to all Performance Monitors registers do not trap
 	 *  to EL2.
 	 *
-	 * MDCR_EL2.SCCD: Set to one so that cycle counting by PMCCNTR_EL0
-	 *  is prohibited in Secure state. This bit is RES0 in versions of the
-	 *  architecture with FEAT_PMUv3p5 not implemented, setting it to 1
-	 *  doesn't have any effect on them.
-	 *
-	 * MDCR_EL2.MCCD: Set to one so that cycle counting by PMCCNTR_EL0
-	 *  is prohibited in EL2. This bit is RES0 in versions of the
-	 *  architecture with FEAT_PMUv3p7 not implemented, setting it to 1
-	 *  doesn't have any effect on them.
-	 *
-	 * MDCR_EL2.SPME: Set to zero so that event counting by the program-
+	 * MDCR_EL2.HPMD: Set to zero so that event counting by the program-
 	 *  mable counters PMEVCNTR<n>_EL0 is prohibited in Secure state. If
 	 *  ARMv8.2 Debug is not implemented this bit does not have any effect
 	 *  on the counters unless there is support for the implementation
@@ -115,9 +101,9 @@
 	 *  ExternalSecureNoninvasiveDebugEnabled().
 	 * ---------------------------------------------------------------------
 	 */
-	mov_imm	x0, ((MDCR_EL2_RESET_VAL | MDCR_SDD_BIT | \
-		      MDCR_SPD32(MDCR_SPD32_DISABLE) | MDCR_SCCD_BIT | \
-		      MDCR_MCCD_BIT) & ~(MDCR_SPME_BIT | MDCR_TDOSA_BIT | \
+	mov_imm	x0, ((MDCR_EL2_RESET_VAL | \
+		      MDCR_SPD32(MDCR_SPD32_DISABLE)) \
+		      & ~(MDCR_EL2_HPMD | MDCR_TDOSA_BIT | \
 		      MDCR_TDA_BIT | MDCR_TPM_BIT))
 
 	msr	mdcr_el2, x0
@@ -126,17 +112,6 @@
 	 * Initialise PMCR_EL0 setting all fields rather than relying
 	 * on hw. Some fields are architecturally UNKNOWN on reset.
 	 *
-	 * PMCR_EL0.LP: Set to one so that event counter overflow, that
-	 *  is recorded in PMOVSCLR_EL0[0-30], occurs on the increment
-	 *  that changes PMEVCNTR<n>_EL0[63] from 1 to 0, when ARMv8.5-PMU
-	 *  is implemented. This bit is RES0 in versions of the architecture
-	 *  earlier than ARMv8.5, setting it to 1 doesn't have any effect
-	 *  on them.
-	 *
-	 * PMCR_EL0.LC: Set to one so that cycle counter overflow, that
-	 *  is recorded in PMOVSCLR_EL0[31], occurs on the increment
-	 *  that changes PMCCNTR_EL0[63] from 1 to 0.
-	 *
 	 * PMCR_EL0.DP: Set to one so that the cycle counter,
 	 *  PMCCNTR_EL0 does not count when event counting is prohibited.
 	 *
@@ -146,8 +121,7 @@
 	 *  counts on every clock cycle.
 	 * ---------------------------------------------------------------------
 	 */
-	mov_imm	x0, ((PMCR_EL0_RESET_VAL | PMCR_EL0_LP_BIT | \
-		      PMCR_EL0_LC_BIT | PMCR_EL0_DP_BIT) & \
+	mov_imm	x0, ((PMCR_EL0_RESET_VAL | PMCR_EL0_DP_BIT) & \
 		    ~(PMCR_EL0_X_BIT | PMCR_EL0_D_BIT))
 
 	msr	pmcr_el0, x0
diff --git a/include/drivers/st/stm32mp1_usb.h b/include/drivers/st/stm32mp1_usb.h
new file mode 100644
index 0000000..06a34cb
--- /dev/null
+++ b/include/drivers/st/stm32mp1_usb.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2021, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef STM32MP1_USB_H
+#define STM32MP1_USB_H
+
+#include <drivers/usb_device.h>
+
+void stm32mp1_usb_init_driver(struct usb_handle *usb_core_handle,
+			      struct pcd_handle *pcd_handle,
+			      void *base_register);
+
+#endif /* STM32MP1_USB_H */
diff --git a/include/drivers/usb_device.h b/include/drivers/usb_device.h
new file mode 100644
index 0000000..e21e315
--- /dev/null
+++ b/include/drivers/usb_device.h
@@ -0,0 +1,276 @@
+/*
+ * Copyright (c) 2021, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef USB_DEVICE_H
+#define USB_DEVICE_H
+
+#include <stdint.h>
+
+#include <lib/utils_def.h>
+
+#define USBD_MAX_NUM_INTERFACES			1U
+#define USBD_MAX_NUM_CONFIGURATION		1U
+
+#define USB_LEN_DEV_QUALIFIER_DESC		0x0AU
+#define USB_LEN_DEV_DESC			0x12U
+#define USB_LEN_CFG_DESC			0x09U
+#define USB_LEN_IF_DESC				0x09U
+#define USB_LEN_EP_DESC				0x07U
+#define USB_LEN_OTG_DESC			0x03U
+#define USB_LEN_LANGID_STR_DESC			0x04U
+#define USB_LEN_OTHER_SPEED_DESC_SIZ		0x09U
+
+#define USBD_IDX_LANGID_STR			0x00U
+#define USBD_IDX_MFC_STR			0x01U
+#define USBD_IDX_PRODUCT_STR			0x02U
+#define USBD_IDX_SERIAL_STR			0x03U
+#define USBD_IDX_CONFIG_STR			0x04U
+#define USBD_IDX_INTERFACE_STR			0x05U
+#define USBD_IDX_USER0_STR			0x06U
+
+#define USB_REQ_TYPE_STANDARD			0x00U
+#define USB_REQ_TYPE_CLASS			0x20U
+#define USB_REQ_TYPE_VENDOR			0x40U
+#define USB_REQ_TYPE_MASK			0x60U
+
+#define USB_REQ_RECIPIENT_DEVICE		0x00U
+#define USB_REQ_RECIPIENT_INTERFACE		0x01U
+#define USB_REQ_RECIPIENT_ENDPOINT		0x02U
+#define USB_REQ_RECIPIENT_MASK			0x1FU
+
+#define USB_REQ_DIRECTION			0x80U
+
+#define USB_REQ_GET_STATUS			0x00U
+#define USB_REQ_CLEAR_FEATURE			0x01U
+#define USB_REQ_SET_FEATURE			0x03U
+#define USB_REQ_SET_ADDRESS			0x05U
+#define USB_REQ_GET_DESCRIPTOR			0x06U
+#define USB_REQ_SET_DESCRIPTOR			0x07U
+#define USB_REQ_GET_CONFIGURATION		0x08U
+#define USB_REQ_SET_CONFIGURATION		0x09U
+#define USB_REQ_GET_INTERFACE			0x0AU
+#define USB_REQ_SET_INTERFACE			0x0BU
+#define USB_REQ_SYNCH_FRAME			0x0CU
+
+#define USB_DESC_TYPE_DEVICE			0x01U
+#define USB_DESC_TYPE_CONFIGURATION		0x02U
+#define USB_DESC_TYPE_STRING			0x03U
+#define USB_DESC_TYPE_INTERFACE			0x04U
+#define USB_DESC_TYPE_ENDPOINT			0x05U
+#define USB_DESC_TYPE_DEVICE_QUALIFIER		0x06U
+#define USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION	0x07U
+#define USB_DESC_TYPE_BOS			0x0FU
+
+#define USB_CONFIG_REMOTE_WAKEUP		2U
+#define USB_CONFIG_SELF_POWERED			1U
+
+#define USB_MAX_EP0_SIZE			64U
+
+/* Device Status */
+#define USBD_STATE_DEFAULT			1U
+#define USBD_STATE_ADDRESSED			2U
+#define USBD_STATE_CONFIGURED			3U
+#define USBD_STATE_SUSPENDED			4U
+
+/* EP0 State */
+#define USBD_EP0_IDLE				0U
+#define USBD_EP0_SETUP				1U
+#define USBD_EP0_DATA_IN			2U
+#define USBD_EP0_DATA_OUT			3U
+#define USBD_EP0_STATUS_IN			4U
+#define USBD_EP0_STATUS_OUT			5U
+#define USBD_EP0_STALL				6U
+
+#define USBD_EP_TYPE_CTRL			0U
+#define USBD_EP_TYPE_ISOC			1U
+#define USBD_EP_TYPE_BULK			2U
+#define USBD_EP_TYPE_INTR			3U
+
+#define  USBD_OUT_EPNUM_MASK			GENMASK(15, 0)
+#define  USBD_OUT_COUNT_MASK			GENMASK(31, 16)
+#define  USBD_OUT_COUNT_SHIFT			16U
+
+/* Number of EP supported, allow to reduce footprint: default max = 15 */
+#ifndef CONFIG_USBD_EP_NB
+#define  USBD_EP_NB				15U
+#else
+#define  USBD_EP_NB				CONFIG_USBD_EP_NB
+#endif
+
+#define LOBYTE(x)	((uint8_t)((x) & 0x00FF))
+#define HIBYTE(x)	((uint8_t)(((x) & 0xFF00) >> 8))
+
+struct usb_setup_req {
+	uint8_t bm_request;
+	uint8_t b_request;
+	uint16_t value;
+	uint16_t index;
+	uint16_t length;
+};
+
+struct usb_handle;
+
+struct usb_class {
+	uint8_t (*init)(struct usb_handle *pdev, uint8_t cfgidx);
+	uint8_t (*de_init)(struct usb_handle *pdev, uint8_t cfgidx);
+	/* Control Endpoints */
+	uint8_t (*setup)(struct usb_handle *pdev, struct usb_setup_req *req);
+	uint8_t (*ep0_tx_sent)(struct usb_handle *pdev);
+	uint8_t (*ep0_rx_ready)(struct usb_handle *pdev);
+	/* Class Specific Endpoints */
+	uint8_t (*data_in)(struct usb_handle *pdev, uint8_t epnum);
+	uint8_t (*data_out)(struct usb_handle *pdev, uint8_t epnum);
+	uint8_t (*sof)(struct usb_handle *pdev);
+	uint8_t (*iso_in_incomplete)(struct usb_handle *pdev, uint8_t epnum);
+	uint8_t (*iso_out_incomplete)(struct usb_handle *pdev, uint8_t epnum);
+};
+
+/* Following USB Device status */
+enum usb_status {
+	USBD_OK = 0U,
+	USBD_BUSY,
+	USBD_FAIL,
+	USBD_TIMEOUT
+};
+
+/* Action to do after IT handling */
+enum usb_action {
+	USB_NOTHING = 0U,
+	USB_DATA_OUT,
+	USB_DATA_IN,
+	USB_SETUP,
+	USB_ENUM_DONE,
+	USB_READ_DATA_PACKET,
+	USB_READ_SETUP_PACKET,
+	USB_RESET,
+	USB_RESUME,
+	USB_SUSPEND,
+	USB_LPM,
+	USB_SOF,
+	USB_DISCONNECT,
+	USB_WRITE_EMPTY
+};
+
+/* USB Device descriptors structure */
+struct usb_desc {
+	uint8_t *(*get_device_desc)(uint16_t *length);
+	uint8_t *(*get_lang_id_desc)(uint16_t *length);
+	uint8_t *(*get_manufacturer_desc)(uint16_t *length);
+	uint8_t *(*get_product_desc)(uint16_t *length);
+	uint8_t *(*get_serial_desc)(uint16_t *length);
+	uint8_t *(*get_configuration_desc)(uint16_t *length);
+	uint8_t *(*get_interface_desc)(uint16_t *length);
+	uint8_t *(*get_usr_desc)(uint8_t index, uint16_t *length);
+	uint8_t *(*get_config_desc)(uint16_t *length);
+	uint8_t *(*get_device_qualifier_desc)(uint16_t *length);
+};
+
+/* USB Device handle structure */
+struct usb_endpoint {
+	uint32_t status;
+	uint32_t total_length;
+	uint32_t rem_length;
+	uint32_t maxpacket;
+};
+
+/*
+ * EndPoint descriptor
+ * num : Endpoint number, between 0 and 15 (limited by USBD_EP_NB)
+ * is_in: Endpoint direction
+ * type : Endpoint type
+ * maxpacket:  Endpoint Max packet size: between 0 and 64KB
+ * xfer_buff: Pointer to transfer buffer
+ * xfer_len: Current transfer lengt
+ * hxfer_count: Partial transfer length in case of multi packet transfer
+ */
+struct usbd_ep {
+	uint8_t num;
+	bool is_in;
+	uint8_t type;
+	uint32_t maxpacket;
+	uint8_t *xfer_buff;
+	uint32_t xfer_len;
+	uint32_t xfer_count;
+};
+
+enum pcd_lpm_state {
+	LPM_L0 = 0x00U, /* on */
+	LPM_L1 = 0x01U, /* LPM L1 sleep */
+	LPM_L2 = 0x02U, /* suspend */
+	LPM_L3 = 0x03U, /* off */
+};
+
+/* USB Device descriptors structure */
+struct usb_driver {
+	enum usb_status (*ep0_out_start)(void *handle);
+	enum usb_status (*ep_start_xfer)(void *handle, struct usbd_ep *ep);
+	enum usb_status (*ep0_start_xfer)(void *handle, struct usbd_ep *ep);
+	enum usb_status (*write_packet)(void *handle, uint8_t *src,
+				     uint8_t ch_ep_num, uint16_t len);
+	void *(*read_packet)(void *handle, uint8_t *dest, uint16_t len);
+	enum usb_status (*ep_set_stall)(void *handle, struct usbd_ep *ep);
+	enum usb_status (*start_device)(void *handle);
+	enum usb_status (*stop_device)(void *handle);
+	enum usb_status (*set_address)(void *handle, uint8_t address);
+	enum usb_status (*write_empty_tx_fifo)(void *handle,
+					    uint32_t epnum, uint32_t xfer_len,
+					    uint32_t *xfer_count,
+					    uint32_t maxpacket,
+					    uint8_t **xfer_buff);
+	enum usb_action (*it_handler)(void *handle, uint32_t *param);
+};
+
+/* USB Peripheral Controller Drivers */
+struct pcd_handle {
+	void *instance; /* Register base address */
+	struct usbd_ep in_ep[USBD_EP_NB]; /* IN endpoint parameters */
+	struct usbd_ep out_ep[USBD_EP_NB]; /* OUT endpoint parameters */
+	uint32_t setup[12]; /* Setup packet buffer */
+	enum pcd_lpm_state lpm_state; /* LPM State */
+};
+
+/* USB Device handle structure */
+struct usb_handle {
+	uint8_t id;
+	uint32_t dev_config;
+	uint32_t dev_config_status;
+	struct usb_endpoint ep_in[USBD_EP_NB];
+	struct usb_endpoint ep_out[USBD_EP_NB];
+	uint32_t ep0_state;
+	uint32_t ep0_data_len;
+	uint8_t dev_state;
+	uint8_t dev_old_state;
+	uint8_t dev_address;
+	uint32_t dev_remote_wakeup;
+	struct usb_setup_req request;
+	const struct usb_desc *desc;
+	struct usb_class *class;
+	void *class_data;
+	void *user_data;
+	struct pcd_handle *data;
+	const struct usb_driver *driver;
+};
+
+enum usb_status usb_core_handle_it(struct usb_handle *pdev);
+enum usb_status usb_core_receive(struct usb_handle *pdev, uint8_t ep_addr,
+				 uint8_t *p_buf, uint32_t len);
+enum usb_status usb_core_transmit(struct usb_handle *pdev, uint8_t ep_addr,
+				  uint8_t *p_buf, uint32_t len);
+enum usb_status usb_core_receive_ep0(struct usb_handle *pdev, uint8_t *p_buf,
+				     uint32_t len);
+enum usb_status usb_core_transmit_ep0(struct usb_handle *pdev, uint8_t *p_buf,
+				      uint32_t len);
+void usb_core_ctl_error(struct usb_handle *pdev);
+enum usb_status usb_core_start(struct usb_handle *pdev);
+enum usb_status usb_core_stop(struct usb_handle *pdev);
+enum usb_status register_usb_driver(struct usb_handle *pdev,
+				    struct pcd_handle *pcd_handle,
+				    const struct usb_driver *driver,
+				    void *driver_handle);
+enum usb_status register_platform(struct usb_handle *pdev,
+				  const struct usb_desc *plat_call_back);
+
+#endif /* USB_DEVICE_H */
diff --git a/lib/extensions/amu/amu_fconf.c b/lib/extensions/amu/amu_fconf.c
deleted file mode 100644
index c7fb803..0000000
--- a/lib/extensions/amu/amu_fconf.c
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * Copyright (c) 2021, Arm Limited. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include "amu_private.h"
-#include <common/debug.h>
-#include <common/fdt_wrappers.h>
-#include <lib/extensions/amu.h>
-#include <lib/fconf/fconf.h>
-#include <libfdt.h>
-
-#include <plat/common/platform.h>
-
-static bool amu_topology_populated_ ; /* Whether the topology is valid */
-static struct amu_fconf_topology amu_topology_; /* Populated topology cache */
-
-const struct amu_fconf_topology *amu_topology(void)
-{
-	if (!amu_topology_populated_) {
-		return NULL;
-	}
-
-	return &amu_topology_;
-}
-
-/*
- * Populate the core-specific AMU structure with information retrieved from a
- * device tree.
- *
- * Returns `0` on success, or a negative integer representing an error code.
- */
-static int amu_fconf_populate_cpu_amu(const void *fdt, int parent,
-				      struct amu_fconf_core *amu)
-{
-	int ret = 0;
-	int node = 0;
-
-	fdt_for_each_subnode(node, fdt, parent) {
-		const char *name;
-		const char *value;
-		int len;
-
-		uintptr_t idx = 0U;
-
-		name = fdt_get_name(fdt, node, &len);
-		if (strncmp(name, "counter@", 8) != 0) {
-			continue;
-		}
-
-		ret = fdt_get_reg_props_by_index(fdt, node, 0, &idx, NULL);
-		if (ret < 0) {
-			break;
-		}
-
-		value = fdt_getprop(fdt, node, "enable-at-el3", &len);
-		if ((value == NULL) && (len != -FDT_ERR_NOTFOUND)) {
-			break;
-		}
-
-		if (len != -FDT_ERR_NOTFOUND) {
-			amu->enable |= (1 << idx);
-		}
-	}
-
-	if ((node < 0) && (node != -FDT_ERR_NOTFOUND)) {
-		return node;
-	}
-
-	return ret;
-}
-
-/*
- * Within a `cpu` node, attempt to dereference the `amu` property, and populate
- * the AMU information for the core.
- *
- * Returns `0` on success, or a negative integer representing an error code.
- */
-static int amu_fconf_populate_cpu(const void *fdt, int node, uintptr_t mpidr)
-{
-	int ret;
-	int idx;
-
-	uint32_t amu_phandle;
-	struct amu_fconf_core *amu;
-
-	ret = fdt_read_uint32(fdt, node, "amu", &amu_phandle);
-	if (ret < 0) {
-		if (ret == -FDT_ERR_NOTFOUND) {
-			ret = 0;
-		}
-
-		return ret;
-	}
-
-	node = fdt_node_offset_by_phandle(fdt, amu_phandle);
-	if (node < 0) {
-		return node;
-	}
-
-	idx = plat_core_pos_by_mpidr(mpidr);
-	amu = &amu_topology_.cores[idx];
-
-	return amu_fconf_populate_cpu_amu(fdt, node, amu);
-}
-
-/*
- * For every CPU node (`/cpus/cpu@n`) in an FDT, executes a callback passing a
- * pointer to the FDT and the offset of the CPU node. If the return value of the
- * callback is negative, it is treated as an error and the loop is aborted. In
- * this situation, the value of the callback is returned from the function.
- *
- * Returns `0` on success, or a negative integer representing an error code.
- */
-static int amu_fconf_foreach_cpu(const void *fdt,
-				 int (*callback)(const void *, int, uintptr_t))
-{
-	int ret = 0;
-	int parent, node = 0;
-
-	parent = fdt_path_offset(fdt, "/cpus");
-	if (parent < 0) {
-		if (parent == -FDT_ERR_NOTFOUND) {
-			parent = 0;
-		}
-
-		return parent;
-	}
-
-	fdt_for_each_subnode(node, fdt, parent) {
-		const char *name;
-		int len;
-
-		uintptr_t mpidr = 0U;
-
-		name = fdt_get_name(fdt, node, &len);
-		if (strncmp(name, "cpu@", 4) != 0) {
-			continue;
-		}
-
-		ret = fdt_get_reg_props_by_index(fdt, node, 0, &mpidr, NULL);
-		if (ret < 0) {
-			break;
-		}
-
-		ret = callback(fdt, node, mpidr);
-		if (ret < 0) {
-			break;
-		}
-	}
-
-	if ((node < 0) && (node != -FDT_ERR_NOTFOUND)) {
-		return node;
-	}
-
-	return ret;
-}
-
-/*
- * Populates the global `amu_topology` structure based on what's described by
- * the hardware configuration device tree blob.
- *
- * The device tree is expected to provide an `amu` property for each `cpu` node,
- * like so:
- *
- *     cpu@0 {
- *         amu = <&cpu0_amu>;
- *     };
- *
- *     amus {
- *         cpu0_amu: amu-0 {
- *             counters {
- *                 #address-cells = <2>;
- *                 #size-cells = <0>;
- *
- *                 counter@x,y {
- *                     reg = <x y>; // Group x, counter y
- *                 };
- *             };
- *         };
- *     };
- */
-static int amu_fconf_populate(uintptr_t config)
-{
-	int ret = amu_fconf_foreach_cpu(
-		(const void *)config, amu_fconf_populate_cpu);
-	if (ret < 0) {
-		ERROR("AMU-FCONF: Failed to configure AMU: %d\n", ret);
-	} else {
-		amu_topology_populated_ = true;
-	}
-
-	return ret;
-}
-
-FCONF_REGISTER_POPULATOR(HW_CONFIG, amu, amu_fconf_populate);
diff --git a/lib/gpt_rme/gpt_rme.c b/lib/gpt_rme/gpt_rme.c
index 1f90e64..6d1ff4d 100644
--- a/lib/gpt_rme/gpt_rme.c
+++ b/lib/gpt_rme/gpt_rme.c
@@ -708,8 +708,12 @@
 	/* GPCCR_EL3.PGS */
 	gpccr_el3 |= SET_GPCCR_PGS(gpt_config.pgs);
 
-	/* Set shareability attribute to Outher Shareable */
-	gpccr_el3 |= SET_GPCCR_SH(GPCCR_SH_OS);
+	/*
+	 * Since EL3 maps the L1 region as Inner shareable, use the same
+	 * shareability attribute for GPC as well so that
+	 * GPC fetches are visible to PEs
+	 */
+	gpccr_el3 |= SET_GPCCR_SH(GPCCR_SH_IS);
 
 	/* Outer and Inner cacheability set to Normal memory, WB, RA, WA. */
 	gpccr_el3 |= SET_GPCCR_ORGN(GPCCR_ORGN_WB_RA_WA);
@@ -720,6 +724,7 @@
 
 	/* TODO: Configure GPCCR_EL3_GPCP for Fault control. */
 	write_gpccr_el3(gpccr_el3);
+	isb();
 	tlbipaallos();
 	dsb();
 	isb();
@@ -759,7 +764,7 @@
 	int ret;
 	uint64_t gpt_desc;
 
-	/* Ensure that MMU and caches are enabled. */
+	/* Ensure that MMU and Data caches are enabled. */
 	assert((read_sctlr_el3() & SCTLR_C_BIT) != 0U);
 
 	/* Validate other parameters. */
@@ -814,7 +819,7 @@
 	int ret;
 	int l1_gpt_cnt;
 
-	/* Ensure that MMU and caches are enabled. */
+	/* Ensure that MMU and Data caches are enabled. */
 	assert((read_sctlr_el3() & SCTLR_C_BIT) != 0U);
 
 	/* PGS is needed for gpt_validate_pas_mappings so check it now. */
@@ -888,6 +893,9 @@
 
 	/* Make sure that all the entries are written to the memory. */
 	dsbishst();
+	tlbipaallos();
+	dsb();
+	isb();
 
 	return 0;
 }
@@ -907,7 +915,7 @@
 {
 	u_register_t reg;
 
-	/* Ensure that MMU and caches are enabled. */
+	/* Ensure that MMU and Data caches are enabled. */
 	assert((read_sctlr_el3() & SCTLR_C_BIT) != 0U);
 
 	/* Ensure GPC are already enabled. */
@@ -1028,6 +1036,9 @@
 	/* Ensure that the tables have been set up before taking requests. */
 	assert(gpt_config.plat_gpt_l0_base != 0U);
 
+	/* Ensure that MMU and data caches are enabled. */
+	assert((read_sctlr_el3() & SCTLR_C_BIT) != 0U);
+
 	/* Check for address range overflow. */
 	if ((ULONG_MAX - base) < size) {
 		VERBOSE("[GPT] Transition request address overflow!\n");
@@ -1093,18 +1104,18 @@
 	gpt_l1_desc |= ((uint64_t)target_pas << gpi_shift);
 	gpt_l1_addr[idx] = gpt_l1_desc;
 
-	/* Ensure that the write operation happens before the unlock. */
-	dmbishst();
+	/* Ensure that the write operation will be observed by GPC */
+	dsbishst();
 
 	/* Unlock access to the L1 tables. */
 	spin_unlock(&gpt_lock);
 
-	/* Cache maintenance. */
-	clean_dcache_range((uintptr_t)&gpt_l1_addr[idx],
-			   sizeof(uint64_t));
 	gpt_tlbi_by_pa(base, GPT_PGS_ACTUAL_SIZE(gpt_config.p));
 	dsbishst();
-
+	/*
+	 * The isb() will be done as part of context
+	 * synchronization when returning to lower EL
+	 */
 	VERBOSE("[GPT] Granule 0x%llx, GPI 0x%x->0x%x\n", base, gpi,
 		target_pas);
 
diff --git a/lib/xlat_mpu/xlat_mpu_utils.c b/lib/xlat_mpu/xlat_mpu_utils.c
index f305632..5400875 100644
--- a/lib/xlat_mpu/xlat_mpu_utils.c
+++ b/lib/xlat_mpu/xlat_mpu_utils.c
@@ -22,13 +22,13 @@
 #warning "xlat_mpu library is currently experimental and its API may change in future."
 
 
-#if LOG_LEVEL < LOG_LEVEL_VERBOSE
-
 void xlat_mmap_print(__unused const mmap_region_t *mmap)
 {
 	/* Empty */
 }
 
+#if LOG_LEVEL < LOG_LEVEL_VERBOSE
+
 void xlat_tables_print(__unused xlat_ctx_t *ctx)
 {
 	/* Empty */
@@ -36,36 +36,48 @@
 
 #else /* if LOG_LEVEL >= LOG_LEVEL_VERBOSE */
 
-static const char *invalid_descriptors_ommited =
-		"%s(%d invalid descriptors omitted)\n";
-
-void xlat_tables_print(xlat_ctx_t *ctx)
+static void xlat_tables_print_internal(__unused xlat_ctx_t *ctx)
 {
-	const char *xlat_regime_str;
-	int used_page_tables;
+	int region_to_use = 0;
+	uintptr_t region_base;
+	size_t region_size;
+	uint64_t prenr_el2_value = 0U;
 
-	if (ctx->xlat_regime == EL1_EL0_REGIME) {
-		xlat_regime_str = "1&0";
-	} else if (ctx->xlat_regime == EL2_REGIME) {
-		xlat_regime_str = "2";
-	} else {
-		assert(ctx->xlat_regime == EL3_REGIME);
-		xlat_regime_str = "3";
-		/* If no EL3 and EL3 tables generated, then need to know. */
+	/*
+	 * Keep track of how many invalid descriptors are counted in a row.
+	 * Whenever multiple invalid descriptors are found, only the first one
+	 * is printed, and a line is added to inform about how many descriptors
+	 * have been omitted.
+	 */
+
+	/*
+	 * TODO:  Remove this WARN() and comment when these API calls are more
+	 *        completely implemented and tested!
+	 */
+	WARN("%s in this early version of xlat_mpu library may not produce reliable results!",
+	     __func__);
+
+	/*
+	 * Sequence through all regions and print those in-use (PRENR has an
+	 * enable bit for each MPU region, 1 for in-use or 0 for unused):
+	 */
+	prenr_el2_value = read_prenr_el2();
+	for (region_to_use = 0;  region_to_use < N_MPU_REGIONS;
+	     region_to_use++) {
+		if (((prenr_el2_value >> region_to_use) & 1U) == 0U) {
+			continue;
+		}
+		region_base = read_prbar_el2() & PRBAR_PRLAR_ADDR_MASK;
+		region_size = read_prlar_el2() & PRBAR_PRLAR_ADDR_MASK;
+		printf("Address:  0x%llx, size:  0x%llx ",
+			(long long) region_base,
+			(long long) region_size);
 	}
-	VERBOSE("Translation tables state:\n");
-	VERBOSE("  Xlat regime:     EL%s\n", xlat_regime_str);
-	VERBOSE("  Max allowed PA:  0x%llx\n", ctx->pa_max_address);
-	VERBOSE("  Max allowed VA:  0x%lx\n", ctx->va_max_address);
-	VERBOSE("  Max mapped PA:   0x%llx\n", ctx->max_pa);
-	VERBOSE("  Max mapped VA:   0x%lx\n", ctx->max_va);
+}
 
-	VERBOSE("  Initial lookup level: %u\n", ctx->base_level);
-	VERBOSE("  Entries @initial lookup level: %u\n",
-		ctx->base_table_entries);
-
-	xlat_tables_print_internal(ctx, 0U, ctx->base_table,
-				   ctx->base_table_entries, ctx->base_level);
+void xlat_tables_print(__unused xlat_ctx_t *ctx)
+{
+	xlat_tables_print_internal(ctx);
 }
 
 #endif /* LOG_LEVEL >= LOG_LEVEL_VERBOSE */
diff --git a/plat/arm/board/fvp_r/fvp_r_bl1_context_mgmt.c b/plat/arm/board/fvp_r/fvp_r_bl1_context_mgmt.c
deleted file mode 100644
index c6544b4..0000000
--- a/plat/arm/board/fvp_r/fvp_r_bl1_context_mgmt.c
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <assert.h>
-
-#include "../../../../bl1/bl1_private.h"
-#include <arch_helpers.h>
-#include <common/debug.h>
-#include <context.h>
-#include <lib/el3_runtime/context_mgmt.h>
-
-#include <plat/common/platform.h>
-
-
-void cm_prepare_el2_exit(void);
-
-/* Following contains the cpu context pointers. */
-static void *bl1_cpu_context_ptr[2];
-
-void *cm_get_context(uint32_t security_state)
-{
-	assert(sec_state_is_valid(security_state));
-	return bl1_cpu_context_ptr[security_state];
-}
-
-void cm_set_context(void *context, uint32_t security_state)
-{
-	assert(sec_state_is_valid(security_state));
-	bl1_cpu_context_ptr[security_state] = context;
-}
-
-/*******************************************************************************
- * This function prepares the context for Secure/Normal world images.
- * Normal world images are transitioned to EL2(if supported) else EL1.
- ******************************************************************************/
-void bl1_prepare_next_image(unsigned int image_id)
-{
-	/*
-	 * Following array will be used for context management.
-	 * There are 2 instances, for the Secure and Non-Secure contexts.
-	 */
-	static cpu_context_t bl1_cpu_context[2];
-
-	unsigned int security_state, mode = MODE_EL1;
-	image_desc_t *desc;
-	entry_point_info_t *next_bl_ep;
-
-#if CTX_INCLUDE_AARCH32_REGS
-	/*
-	 * Ensure that the build flag to save AArch32 system registers in CPU
-	 * context is not set for AArch64-only platforms.
-	 */
-	if (el_implemented(1) == EL_IMPL_A64ONLY) {
-		ERROR("EL1 supports AArch64-only. Please set build flag %s",
-				"CTX_INCLUDE_AARCH32_REGS = 0\n");
-		panic();
-	}
-#endif
-
-	/* Get the image descriptor. */
-	desc = bl1_plat_get_image_desc(image_id);
-	assert(desc != NULL);
-
-	/* Get the entry point info. */
-	next_bl_ep = &desc->ep_info;
-
-	/* Get the image security state. */
-	security_state = GET_SECURITY_STATE(next_bl_ep->h.attr);
-
-	/* Setup the Secure/Non-Secure context if not done already. */
-	if (cm_get_context(security_state) == NULL) {
-		cm_set_context(&bl1_cpu_context[security_state], security_state);
-	}
-	/* Prepare the SPSR for the next BL image. */
-	next_bl_ep->spsr = (uint32_t)SPSR_64((uint64_t) mode,
-		(uint64_t)MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
-
-	/* Allow platform to make change */
-	bl1_plat_set_ep_info(image_id, next_bl_ep);
-
-	/* Prepare context for the next EL */
-	cm_prepare_el2_exit();
-
-	/* Indicate that image is in execution state. */
-	desc->state = IMAGE_STATE_EXECUTED;
-
-	print_entry_point_info(next_bl_ep);
-}
diff --git a/plat/arm/board/fvp_r/fvp_r_bl1_entrypoint.S b/plat/arm/board/fvp_r/fvp_r_bl1_entrypoint.S
index 19a685c..15f4c43 100644
--- a/plat/arm/board/fvp_r/fvp_r_bl1_entrypoint.S
+++ b/plat/arm/board/fvp_r/fvp_r_bl1_entrypoint.S
@@ -43,14 +43,6 @@
 	 */
 	bl	bl1_setup
 
-#if ENABLE_PAUTH
-	/* --------------------------------------------------------------------
-	 * Program APIAKey_EL1 and enable pointer authentication.
-	 * --------------------------------------------------------------------
-	 */
-	bl	pauth_init_enable_el2
-#endif /* ENABLE_PAUTH */
-
 	/* --------------------------------------------------------------------
 	 * Initialize platform and jump to our c-entry point
 	 * for this type of reset.
@@ -85,15 +77,6 @@
 	 */
 	bl	clear_all_mpu_regions
 
-#if ENABLE_PAUTH
-	/* ---------------------------------------------
-	 * Disable pointer authentication before jumping
-	 * to next boot image.
-	 * ---------------------------------------------
-	 */
-	bl	pauth_disable_el2
-#endif /* ENABLE_PAUTH */
-
 	/* --------------------------------------------------
 	 * Do the transition to next boot image.
 	 * --------------------------------------------------
diff --git a/plat/arm/board/fvp_r/fvp_r_bl1_main.c b/plat/arm/board/fvp_r/fvp_r_bl1_main.c
index 2fd0e97..841a176 100644
--- a/plat/arm/board/fvp_r/fvp_r_bl1_main.c
+++ b/plat/arm/board/fvp_r/fvp_r_bl1_main.c
@@ -25,6 +25,8 @@
 #include <platform_def.h>
 
 
+void cm_prepare_el2_exit(void);
+
 void bl1_run_next_image(const struct entry_point_info *bl_ep_info);
 
 /*******************************************************************************
@@ -39,13 +41,6 @@
 	/* Get the image id of next image to load and run. */
 	image_id = bl1_plat_get_next_image_id();
 
-#if ENABLE_PAUTH
-	/*
-	 * Disable pointer authentication before running next boot image
-	 */
-	pauth_disable_el2();
-#endif /* ENABLE_PAUTH */
-
 #if !ARM_DISABLE_TRUSTED_WDOG
 	/* Disable watchdog before leaving BL1 */
 	plat_arm_secure_wdt_stop();
@@ -96,12 +91,6 @@
 	NOTICE("BL1: Booting BL33\n");
 }
 
-static void bl1_load_bl2(void);
-
-#if ENABLE_PAUTH
-uint64_t bl1_apiakey[2];
-#endif
-
 /*******************************************************************************
  * Helper utility to calculate the BL2 memory layout taking into consideration
  * the BL1 RW data assuming that it is at the top of the memory layout.
@@ -124,6 +113,53 @@
 }
 
 /*******************************************************************************
+ * This function prepares for entry to BL33
+ ******************************************************************************/
+void bl1_prepare_next_image(unsigned int image_id)
+{
+	unsigned int mode = MODE_EL1;
+	image_desc_t *desc;
+	entry_point_info_t *next_bl_ep;
+
+#if CTX_INCLUDE_AARCH32_REGS
+	/*
+	 * Ensure that the build flag to save AArch32 system registers in CPU
+	 * context is not set for AArch64-only platforms.
+	 */
+	if (el_implemented(1) == EL_IMPL_A64ONLY) {
+		ERROR("EL1 supports AArch64-only. Please set build flag %s",
+				"CTX_INCLUDE_AARCH32_REGS = 0\n");
+		panic();
+	}
+#endif
+
+	/* Get the image descriptor. */
+	desc = bl1_plat_get_image_desc(image_id);
+	assert(desc != NULL);
+
+	/* Get the entry point info. */
+	next_bl_ep = &desc->ep_info;
+
+	/* FVP-R is only secure */
+	assert(GET_SECURITY_STATE(next_bl_ep->h.attr) == SECURE);
+
+	/* Prepare the SPSR for the next BL image. */
+	next_bl_ep->spsr = (uint32_t)SPSR_64((uint64_t) mode,
+		(uint64_t)MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
+
+	/* Allow platform to make change */
+	bl1_plat_set_ep_info(image_id, next_bl_ep);
+
+	/* Prepare context for the next EL */
+	cm_prepare_el2_exit();
+
+	/* Indicate that image is in execution state. */
+	desc->state = IMAGE_STATE_EXECUTED;
+
+	print_entry_point_info(next_bl_ep);
+}
+
+/*******************************************************************************
  * Setup function for BL1.
  ******************************************************************************/
 void bl1_setup(void)
@@ -133,14 +169,6 @@
 
 	/* Perform late platform-specific setup */
 	bl1_plat_arch_setup();
-
-#if CTX_INCLUDE_PAUTH_REGS
-	/*
-	 * Assert that the ARMv8.3-PAuth registers are present or an access
-	 * fault will be triggered when they are being saved or restored.
-	 */
-	assert(is_armv8_3_pauth_present());
-#endif /* CTX_INCLUDE_PAUTH_REGS */
 }
 
 /*******************************************************************************
@@ -199,12 +227,6 @@
 	/* Perform platform setup in BL1. */
 	bl1_platform_setup();
 
-#if ENABLE_PAUTH
-	/* Store APIAKey_EL1 key */
-	bl1_apiakey[0] = read_apiakeylo_el1();
-	bl1_apiakey[1] = read_apiakeyhi_el1();
-#endif /* ENABLE_PAUTH */
-
 	/* Get the image id of next image to load and run. */
 	image_id = bl1_plat_get_next_image_id();
 
@@ -212,9 +234,7 @@
 	 * We currently interpret any image id other than
 	 * BL2_IMAGE_ID as the start of firmware update.
 	 */
-	if (image_id == BL2_IMAGE_ID) {
-		bl1_load_bl2();
-	} else if (image_id == BL33_IMAGE_ID) {
+	if (image_id == BL33_IMAGE_ID) {
 		bl1_load_bl33();
 	} else {
 		NOTICE("BL1-FWU: *******FWU Process Started*******\n");
@@ -228,48 +248,6 @@
 }
 
 /*******************************************************************************
- * This function locates and loads the BL2 raw binary image in the trusted SRAM.
- * Called by the primary cpu after a cold boot.
- * TODO: Add support for alternative image load mechanism e.g using virtio/elf
- * loader etc.
- ******************************************************************************/
-static void bl1_load_bl2(void)
-{
-	image_desc_t *desc;
-	image_info_t *info;
-	int err;
-
-	/* Get the image descriptor */
-	desc = bl1_plat_get_image_desc(BL2_IMAGE_ID);
-	assert(desc != NULL);
-
-	/* Get the image info */
-	info = &desc->image_info;
-	INFO("BL1: Loading BL2\n");
-
-	err = bl1_plat_handle_pre_image_load(BL2_IMAGE_ID);
-	if (err != 0) {
-		ERROR("Failure in pre image load handling of BL2 (%d)\n", err);
-		plat_error_handler(err);
-	}
-
-	err = load_auth_image(BL2_IMAGE_ID, info);
-	if (err != 0) {
-		ERROR("Failed to load BL2 firmware.\n");
-		plat_error_handler(err);
-	}
-
-	/* Allow platform to handle image information. */
-	err = bl1_plat_handle_post_image_load(BL2_IMAGE_ID);
-	if (err != 0) {
-		ERROR("Failure in post image load handling of BL2 (%d)\n", err);
-		plat_error_handler(err);
-	}
-
-	NOTICE("BL1: Booting BL2\n");
-}
-
-/*******************************************************************************
  * Function called just before handing over to the next BL to inform the user
  * about the boot progress. In debug mode, also print details about the BL
  * image's execution context.
diff --git a/plat/arm/board/fvp_r/fvp_r_common.c b/plat/arm/board/fvp_r/fvp_r_common.c
index bce943d..edcf658 100644
--- a/plat/arm/board/fvp_r/fvp_r_common.c
+++ b/plat/arm/board/fvp_r/fvp_r_common.c
@@ -11,7 +11,6 @@
 #include <common/debug.h>
 
 #include <drivers/arm/cci.h>
-#include <drivers/arm/ccn.h>
 #include <drivers/arm/gicv2.h>
 #include <drivers/arm/sp804_delay_timer.h>
 #include <drivers/generic_delay_timer.h>
@@ -80,7 +79,6 @@
 
 ARM_CASSERT_MMAP
 
-#if FVP_R_INTERCONNECT_DRIVER != FVP_R_CCN
 static const int fvp_cci400_map[] = {
 	PLAT_FVP_R_CCI400_CLUS0_SL_PORT,
 	PLAT_FVP_R_CCI400_CLUS1_SL_PORT,
@@ -103,7 +101,6 @@
 	assert(master < FVP_R_CLUSTER_COUNT);
 	return master;
 }
-#endif
 
 /*******************************************************************************
  * Initialize the platform config for future decision making
@@ -198,14 +195,6 @@
 
 void __init fvp_interconnect_init(void)
 {
-#if FVP_R_INTERCONNECT_DRIVER == FVP_R_CCN
-	if (ccn_get_part0_id(PLAT_ARM_CCN_BASE) != CCN_502_PART0_ID) {
-		ERROR("Unrecognized CCN variant detected. Only CCN-502 is supported");
-		panic();
-	}
-
-	plat_arm_interconnect_init();
-#else
 	uintptr_t cci_base = 0U;
 	const int *cci_map = NULL;
 	unsigned int map_size = 0U;
@@ -226,14 +215,10 @@
 	assert(cci_base != 0U);
 	assert(cci_map != NULL);
 	cci_init(cci_base, cci_map, map_size);
-#endif
 }
 
 void fvp_interconnect_enable(void)
 {
-#if FVP_R_INTERCONNECT_DRIVER == FVP_R_CCN
-	plat_arm_interconnect_enter_coherency();
-#else
 	unsigned int master;
 
 	if ((arm_config.flags & (ARM_CONFIG_FVP_HAS_CCI400 |
@@ -241,14 +226,10 @@
 		master = get_interconnect_master();
 		cci_enable_snoop_dvm_reqs(master);
 	}
-#endif
 }
 
 void fvp_interconnect_disable(void)
 {
-#if FVP_R_INTERCONNECT_DRIVER == FVP_R_CCN
-	plat_arm_interconnect_exit_coherency();
-#else
 	unsigned int master;
 
 	if ((arm_config.flags & (ARM_CONFIG_FVP_HAS_CCI400 |
@@ -256,7 +237,6 @@
 		master = get_interconnect_master();
 		cci_disable_snoop_dvm_reqs(master);
 	}
-#endif
 }
 
 #if TRUSTED_BOARD_BOOT
diff --git a/plat/arm/board/fvp_r/fvp_r_context.S b/plat/arm/board/fvp_r/fvp_r_context.S
deleted file mode 100644
index 2746c2e..0000000
--- a/plat/arm/board/fvp_r/fvp_r_context.S
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <asm_macros.S>
-
-	.global	el2_exit
-
-/* ------------------------------------------------------------------
- * The mechanism, from el3_exit, is not used in this v8-R64 implementation.
- * ------------------------------------------------------------------
- */
-func el2_exit
-	exception_return
-endfunc el2_exit
diff --git a/plat/arm/board/fvp_r/fvp_r_debug.S b/plat/arm/board/fvp_r/fvp_r_debug.S
index 8db1b09..88f0a29 100644
--- a/plat/arm/board/fvp_r/fvp_r_debug.S
+++ b/plat/arm/board/fvp_r/fvp_r_debug.S
@@ -41,6 +41,7 @@
 
 _panic_handler:
 	/* Pass to plat_panic_handler the address from where el2_panic was
-	 * called, not the address of the call from el2_panic. */
+	 * called, not the address of the call from el2_panic.
+	 */
 	mov	x30, x6
 	b	plat_panic_handler
diff --git a/plat/arm/board/fvp_r/fvp_r_def.h b/plat/arm/board/fvp_r/fvp_r_def.h
index b9f6989..eda39cf 100644
--- a/plat/arm/board/fvp_r/fvp_r_def.h
+++ b/plat/arm/board/fvp_r/fvp_r_def.h
@@ -9,28 +9,18 @@
 
 #include <lib/utils_def.h>
 
-#ifndef FVP_R_CLUSTER_COUNT
-#error "FVP_R_CLUSTER_COUNT is not set in makefile"
-#endif
-
-#ifndef FVP_R_MAX_CPUS_PER_CLUSTER
-#error "FVP_R_MAX_CPUS_PER_CLUSTER is not set in makefile"
-#endif
-
-#ifndef FVP_R_MAX_PE_PER_CPU
-#error "FVP_R_MAX_PE_PER_CPU is not set in makefile"
-#endif
-
-#define FVP_R_PRIMARY_CPU			0x0
-
-/* Defines for the Interconnect build selection */
-#define FVP_R_CCI			1
-#define FVP_R_CCN			2
+/******************************************************************************
+ * FVP-R topology constants
+ *****************************************************************************/
+#define FVP_R_CLUSTER_COUNT		2
+#define FVP_R_MAX_CPUS_PER_CLUSTER	4
+#define FVP_R_MAX_PE_PER_CPU		1
+#define FVP_R_PRIMARY_CPU		0x0
 
 /******************************************************************************
  * Definition of platform soc id
  *****************************************************************************/
-#define FVP_R_SOC_ID      0
+#define FVP_R_SOC_ID			0
 
 /*******************************************************************************
  * FVP_R memory map related constants
diff --git a/plat/arm/board/fvp_r/fvp_r_helpers.S b/plat/arm/board/fvp_r/fvp_r_helpers.S
index f7a04d8..ba85777 100644
--- a/plat/arm/board/fvp_r/fvp_r_helpers.S
+++ b/plat/arm/board/fvp_r/fvp_r_helpers.S
@@ -16,7 +16,6 @@
 	.globl	plat_secondary_cold_boot_setup
 	.globl	plat_get_my_entrypoint
 	.globl	plat_is_my_cpu_primary
-	.globl	plat_arm_calc_core_pos
 
 	/* -----------------------------------------------------
 	 * void plat_secondary_cold_boot_setup (void);
@@ -127,40 +126,3 @@
 	cset	w0, eq
 	ret
 endfunc plat_is_my_cpu_primary
-
-	/* ---------------------------------------------------------------------
-	 * unsigned int plat_arm_calc_core_pos(u_register_t mpidr)
-	 *
-	 * Function to calculate the core position on FVP_R.
-	 *
-	 * (ClusterId * FVP_R_MAX_CPUS_PER_CLUSTER * FVP_R_MAX_PE_PER_CPU) +
-	 * (CPUId * FVP_R_MAX_PE_PER_CPU) +
-	 * ThreadId
-	 *
-	 * which can be simplified as:
-	 *
-	 * ((ClusterId * FVP_R_MAX_CPUS_PER_CLUSTER + CPUId) * FVP_R_MAX_PE_PER_CPU)
-	 * + ThreadId
-	 * ---------------------------------------------------------------------
-	 */
-func plat_arm_calc_core_pos
-	/*
-	 * Check for MT bit in MPIDR. If not set, shift MPIDR to left to make it
-	 * look as if in a multi-threaded implementation.
-	 */
-	tst	x0, #MPIDR_MT_MASK
-	lsl	x3, x0, #MPIDR_AFFINITY_BITS
-	csel	x3, x3, x0, eq
-
-	/* Extract individual affinity fields from MPIDR */
-	ubfx	x0, x3, #MPIDR_AFF0_SHIFT, #MPIDR_AFFINITY_BITS
-	ubfx	x1, x3, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS
-	ubfx	x2, x3, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS
-
-	/* Compute linear position */
-	mov	x4, #FVP_R_MAX_CPUS_PER_CLUSTER
-	madd	x1, x2, x4, x1
-	mov	x5, #FVP_R_MAX_PE_PER_CPU
-	madd	x0, x1, x5, x0
-	ret
-endfunc plat_arm_calc_core_pos
diff --git a/plat/arm/board/fvp_r/fvp_r_pauth_helpers.S b/plat/arm/board/fvp_r/fvp_r_pauth_helpers.S
deleted file mode 100644
index 7e6bc3d..0000000
--- a/plat/arm/board/fvp_r/fvp_r_pauth_helpers.S
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (c) 2021, Arm Limited. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <arch.h>
-#include <asm_macros.S>
-#include <lib/el3_runtime/cpu_data.h>
-
-	.global	pauth_init_enable_el2
-	.global	pauth_disable_el2
-
-/* -------------------------------------------------------------
- * File contains EL2 versions of EL3 funcs in:
- * 	.../lib/extensions/pauth/pauth_helpers.S
- * -------------------------------------------------------------
- */
-
-/* -------------------------------------------------------------
- * Program APIAKey_EL1 and enable pointer authentication in EL2
- * -------------------------------------------------------------
- */
-func pauth_init_enable_el2
-	stp	x29, x30, [sp, #-16]!
-
-	/* Initialize platform key */
-	bl	plat_init_apkey
-
-	/* Program instruction key A used by the Trusted Firmware */
-	msr	APIAKeyLo_EL1, x0
-	msr	APIAKeyHi_EL1, x1
-
-	/* Enable pointer authentication */
-	mrs	x0, sctlr_el2
-	orr	x0, x0, #SCTLR_EnIA_BIT
-
-#if ENABLE_BTI
-	 /* Enable PAC branch type compatibility */
-	bic	x0, x0, #SCTLR_BT_BIT
-#endif
-	msr	sctlr_el2, x0
-	isb
-
-	ldp	x29, x30, [sp], #16
-	ret
-endfunc pauth_init_enable_el2
-
-/* -------------------------------------------------------------
- * Disable pointer authentication in EL2
- * -------------------------------------------------------------
- */
-func pauth_disable_el2
-	mrs	x0, sctlr_el2
-	bic	x0, x0, #SCTLR_EnIA_BIT
-	msr	sctlr_el2, x0
-	isb
-	ret
-endfunc pauth_disable_el2
diff --git a/plat/arm/board/fvp_r/include/plat.ld.S b/plat/arm/board/fvp_r/include/plat.ld.S
deleted file mode 100644
index e91a5a0..0000000
--- a/plat/arm/board/fvp_r/include/plat.ld.S
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-#ifndef PLAT_LD_S
-#define PLAT_LD_S
-
-#include <plat/arm/common/arm_tzc_dram.ld.S>
-
-#endif /* PLAT_LD_S */
diff --git a/plat/arm/board/fvp_r/include/platform_def.h b/plat/arm/board/fvp_r/include/platform_def.h
index 4a6b441..ea3a258 100644
--- a/plat/arm/board/fvp_r/include/platform_def.h
+++ b/plat/arm/board/fvp_r/include/platform_def.h
@@ -210,10 +210,6 @@
 #define PLAT_FVP_R_CCI5XX_CLUS0_SL_PORT	5
 #define PLAT_FVP_R_CCI5XX_CLUS1_SL_PORT	6
 
-/* CCN related constants. Only CCN 502 is currently supported */
-#define PLAT_ARM_CCN_BASE		UL(0xae000000)
-#define PLAT_ARM_CLUSTER_TO_CCN_ID_MAP	1, 5, 7, 11
-
 /* System timer related constants */
 #define PLAT_ARM_NSTIMER_FRAME_ID	U(1)
 
diff --git a/plat/arm/board/fvp_r/platform.mk b/plat/arm/board/fvp_r/platform.mk
index 8f5878f..93b5cf2 100644
--- a/plat/arm/board/fvp_r/platform.mk
+++ b/plat/arm/board/fvp_r/platform.mk
@@ -15,47 +15,12 @@
 
 override CTX_INCLUDE_AARCH32_REGS	:=	0
 
-# Default cluster count for FVP_R
-FVP_R_CLUSTER_COUNT	:= 2
-
-# Default number of CPUs per cluster on FVP_R
-FVP_R_MAX_CPUS_PER_CLUSTER	:= 4
-
-# Default number of threads per CPU on FVP_R
-FVP_R_MAX_PE_PER_CPU	:= 1
-
 # Use MPU-based memory management:
 XLAT_MPU_LIB_V1		:=	1
 
-# Pass FVP_R_CLUSTER_COUNT to the build system.
-$(eval $(call add_define,FVP_R_CLUSTER_COUNT))
-
-# Pass FVP_R_MAX_CPUS_PER_CLUSTER to the build system.
-$(eval $(call add_define,FVP_R_MAX_CPUS_PER_CLUSTER))
-
-# Pass FVP_R_MAX_PE_PER_CPU to the build system.
-$(eval $(call add_define,FVP_R_MAX_PE_PER_CPU))
-
-# Sanity check the cluster count and if FVP_R_CLUSTER_COUNT <= 2,
-# choose the CCI driver , else the CCN driver
-ifeq ($(FVP_R_CLUSTER_COUNT), 0)
-$(error "Incorrect cluster count specified for FVP_R port")
-else ifeq ($(FVP_R_CLUSTER_COUNT),$(filter $(FVP_R_CLUSTER_COUNT),1 2))
-FVP_R_INTERCONNECT_DRIVER := FVP_R_CCI
-else
-FVP_R_INTERCONNECT_DRIVER := FVP_R_CCN
-endif
-
-$(eval $(call add_define,FVP_R_INTERCONNECT_DRIVER))
-
-ifeq (${FVP_R_INTERCONNECT_DRIVER}, FVP_R_CCI)
+# FVP R will not have more than 2 clusters so just use CCI interconnect
 FVP_R_INTERCONNECT_SOURCES	:= 	drivers/arm/cci/cci.c
-else ifeq (${FVP_R_INTERCONNECT_DRIVER}, FVP_R_CCN)
-FVP_R_INTERCONNECT_SOURCES	:= 	drivers/arm/ccn/ccn.c		\
-					plat/arm/common/arm_ccn.c
-else
-$(error "Incorrect CCN driver chosen on FVP_R port")
-endif
+
 
 include plat/arm/board/common/board_common.mk
 include plat/arm/common/arm_common.mk
@@ -64,17 +29,14 @@
 
 FVP_R_BL_COMMON_SOURCES	:=	plat/arm/board/fvp_r/fvp_r_common.c		\
 				plat/arm/board/fvp_r/fvp_r_context_mgmt.c	\
-				plat/arm/board/fvp_r/fvp_r_context.S		\
 				plat/arm/board/fvp_r/fvp_r_debug.S		\
 				plat/arm/board/fvp_r/fvp_r_err.c		\
 				plat/arm/board/fvp_r/fvp_r_helpers.S		\
-				plat/arm/board/fvp_r/fvp_r_misc_helpers.S	\
-				plat/arm/board/fvp_r/fvp_r_pauth_helpers.S
+				plat/arm/board/fvp_r/fvp_r_misc_helpers.S
 
 FVP_R_BL1_SOURCES	:=	plat/arm/board/fvp_r/fvp_r_bl1_arch_setup.c	\
 				plat/arm/board/fvp_r/fvp_r_bl1_setup.c		\
 				plat/arm/board/fvp_r/fvp_r_io_storage.c		\
-				plat/arm/board/fvp_r/fvp_r_bl1_context_mgmt.c	\
 				plat/arm/board/fvp_r/fvp_r_bl1_entrypoint.S	\
 				plat/arm/board/fvp_r/fvp_r_bl1_exceptions.S	\
 				plat/arm/board/fvp_r/fvp_r_bl1_main.c
@@ -82,17 +44,13 @@
 FVP_R_CPU_LIBS		:=	lib/cpus/${ARCH}/aem_generic.S
 
 FVP_R_DYNC_CFG_SOURCES	:=	common/fdt_wrappers.c				\
-				common/uuid.c					\
-				plat/arm/common/arm_dyn_cfg.c			\
-				plat/arm/common/arm_dyn_cfg_helpers.c
+				plat/arm/common/arm_dyn_cfg.c
 
 ifeq (${TRUSTED_BOARD_BOOT},1)
 FVP_R_AUTH_SOURCES	:=	drivers/auth/auth_mod.c				\
 				drivers/auth/crypto_mod.c			\
 				drivers/auth/img_parser_mod.c			\
 				lib/fconf/fconf_tbbr_getter.c			\
-				bl1/tbbr/tbbr_img_desc.c			\
-				plat/arm/common/arm_bl1_fwu.c			\
 				plat/common/tbbr/plat_tbbr.c			\
 				drivers/auth/tbbr/tbbr_cot_bl1_r64.c		\
 				drivers/auth/tbbr/tbbr_cot_common.c		\
@@ -125,11 +83,6 @@
 				drivers/io/io_storage.c				\
 				drivers/io/io_semihosting.c			\
 				lib/cpus/aarch64/cpu_helpers.S			\
-				lib/cpus/errata_report.c			\
-				lib/cpus/aarch64/dsu_helpers.S			\
-				lib/el3_runtime/aarch64/context.S		\
-				lib/el3_runtime/aarch64/context_mgmt.c		\
-				lib/fconf/fconf.c				\
 				lib/fconf/fconf_dyn_cfg_getter.c		\
 				lib/semihosting/semihosting.c			\
 				lib/semihosting/${ARCH}/semihosting_call.S	\
diff --git a/plat/st/common/bl2_io_storage.c b/plat/st/common/bl2_io_storage.c
index 7e76083..b0314d2 100644
--- a/plat/st/common/bl2_io_storage.c
+++ b/plat/st/common/bl2_io_storage.c
@@ -13,6 +13,7 @@
 #include <drivers/io/io_block.h>
 #include <drivers/io/io_driver.h>
 #include <drivers/io/io_fip.h>
+#include <drivers/io/io_memmap.h>
 #include <drivers/io/io_mtd.h>
 #include <drivers/io/io_storage.h>
 #include <drivers/mmc.h>
@@ -24,6 +25,7 @@
 #include <drivers/st/stm32_fmc2_nand.h>
 #include <drivers/st/stm32_qspi.h>
 #include <drivers/st/stm32_sdmmc2.h>
+#include <drivers/usb_device.h>
 #include <lib/fconf/fconf.h>
 #include <lib/mmio.h>
 #include <lib/utils.h>
@@ -31,7 +33,9 @@
 #include <tools_share/firmware_image_package.h>
 
 #include <platform_def.h>
+#include <stm32cubeprogrammer.h>
 #include <stm32mp_fconf_getter.h>
+#include <usb_dfu.h>
 
 /* IO devices */
 uintptr_t fip_dev_handle;
@@ -95,6 +99,10 @@
 static const io_dev_connector_t *spi_dev_con;
 #endif
 
+#if STM32MP_USB_PROGRAMMER
+static const io_dev_connector_t *memmap_dev_con;
+#endif
+
 io_block_spec_t image_block_spec = {
 	.offset = 0U,
 	.length = 0U,
@@ -128,6 +136,9 @@
 	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_QSPI:
 		INFO("Using SPI NAND\n");
 		break;
+	case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB:
+		INFO("Using USB\n");
+		break;
 	default:
 		ERROR("Boot interface %u not found\n",
 		      boot_context->boot_interface_selected);
@@ -246,6 +257,32 @@
 }
 #endif /* STM32MP_SPI_NAND */
 
+#if STM32MP_USB_PROGRAMMER
+static void mmap_io_setup(void)
+{
+	int io_result __unused;
+
+	io_result = register_io_dev_memmap(&memmap_dev_con);
+	assert(io_result == 0);
+
+	io_result = io_dev_open(memmap_dev_con, (uintptr_t)NULL,
+				&storage_dev_handle);
+	assert(io_result == 0);
+}
+
+static void stm32cubeprogrammer_usb(void)
+{
+	int ret __unused;
+	struct usb_handle *pdev;
+
+	/* Init USB on platform */
+	pdev = usb_dfu_plat_init();
+
+	ret = stm32cubeprog_usb_load(pdev, DWL_BUFFER_BASE, DWL_BUFFER_SIZE);
+	assert(ret == 0);
+}
+#endif
+
 void stm32mp_io_setup(void)
 {
 	int io_result __unused;
@@ -297,6 +334,12 @@
 		boot_spi_nand(boot_context);
 		break;
 #endif
+#if STM32MP_USB_PROGRAMMER
+	case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB:
+		dmbsy();
+		mmap_io_setup();
+		break;
+#endif
 
 	default:
 		ERROR("Boot interface %d not supported\n",
@@ -357,6 +400,17 @@
 		break;
 #endif
 
+#if STM32MP_USB_PROGRAMMER
+	case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB:
+		if (image_id == FW_CONFIG_ID) {
+			stm32cubeprogrammer_usb();
+			/* FIP loaded at DWL address */
+			image_block_spec.offset = DWL_BUFFER_BASE;
+			image_block_spec.length = DWL_BUFFER_SIZE;
+		}
+		break;
+#endif
+
 	default:
 		ERROR("FIP Not found\n");
 		panic();
diff --git a/plat/st/common/include/stm32cubeprogrammer.h b/plat/st/common/include/stm32cubeprogrammer.h
new file mode 100644
index 0000000..503d919
--- /dev/null
+++ b/plat/st/common/include/stm32cubeprogrammer.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef STM32CUBEPROGRAMMER_H
+#define STM32CUBEPROGRAMMER_H
+
+#include <stdint.h>
+
+#include <usb_dfu.h>
+
+/* Phase definition */
+#define PHASE_FLASHLAYOUT	0U
+#define PHASE_SSBL		3U
+#define PHASE_CMD		0xF1U
+#define PHASE_RESET		0xFFU
+
+/* Functions provided by plat */
+uint8_t usb_dfu_get_phase(uint8_t alt);
+
+int stm32cubeprog_usb_load(struct usb_handle *usb_core_handle,
+			   uintptr_t ssbl_base,
+			   size_t ssbl_len);
+
+#endif /* STM32CUBEPROGRAMMER_H */
diff --git a/plat/st/common/include/usb_dfu.h b/plat/st/common/include/usb_dfu.h
new file mode 100644
index 0000000..f7d4245
--- /dev/null
+++ b/plat/st/common/include/usb_dfu.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2021, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef USB_DFU_H
+#define USB_DFU_H
+
+#include <stdint.h>
+
+#include <drivers/usb_device.h>
+
+#define DFU_DESCRIPTOR_TYPE		0x21U
+
+/* Max DFU Packet Size = 1024 bytes */
+#define USBD_DFU_XFER_SIZE		1024U
+
+#define TRANSFER_SIZE_BYTES(size) \
+	((uint8_t)((size) & 0xFF)), /* XFERSIZEB0 */\
+	((uint8_t)((size) >> 8))    /* XFERSIZEB1 */
+
+/*
+ * helper for descriptor of DFU interface 0 Alternate setting n
+ * with iInterface = index of string descriptor, assumed Nth user string
+ */
+#define USBD_DFU_IF_DESC(n)	0x09U, /* Interface Descriptor size */\
+				USB_DESC_TYPE_INTERFACE, /* descriptor type */\
+				0x00U, /* Number of Interface */\
+				(n), /* Alternate setting */\
+				0x00U, /* bNumEndpoints*/\
+				0xFEU, /* Application Specific Class Code */\
+				0x01U, /* Device Firmware Upgrade Code */\
+				0x02U, /* DFU mode protocol */ \
+				USBD_IDX_USER0_STR + (n) /* iInterface */
+
+/* DFU1.1 Standard */
+#define USB_DFU_VERSION			0x0110U
+#define USB_DFU_ITF_SIZ			9U
+#define USB_DFU_DESC_SIZ(itf)		(USB_DFU_ITF_SIZ * ((itf) + 2U))
+
+/*
+ * bmAttribute value for DFU:
+ * bitCanDnload = 1(bit 0)
+ * bitCanUpload = 1(bit 1)
+ * bitManifestationTolerant = 1 (bit 2)
+ * bitWillDetach = 1(bit 3)
+ * Reserved (bit4-6)
+ * bitAcceleratedST = 0(bit 7)
+ */
+#define DFU_BM_ATTRIBUTE		0x0FU
+
+#define DFU_STATUS_SIZE			6U
+
+/* Callback for media access */
+struct usb_dfu_media {
+	int (*upload)(uint8_t alt, uintptr_t *buffer, uint32_t *len,
+		      void *user_data);
+	int (*download)(uint8_t alt, uintptr_t *buffer, uint32_t *len,
+			void *user_data);
+	int (*manifestation)(uint8_t alt, void *user_data);
+};
+
+/* Internal DFU handle */
+struct usb_dfu_handle {
+	uint8_t status[DFU_STATUS_SIZE];
+	uint8_t dev_state;
+	uint8_t dev_status;
+	uint8_t alt_setting;
+	const struct usb_dfu_media *callback;
+};
+
+void usb_dfu_register(struct usb_handle *pdev, struct usb_dfu_handle *phandle);
+
+int usb_dfu_loop(struct usb_handle *pdev, const struct usb_dfu_media *pmedia);
+
+/* Function provided by plat */
+struct usb_handle *usb_dfu_plat_init(void);
+
+#endif /* USB_DFU_H */
diff --git a/plat/st/common/stm32cubeprogrammer_usb.c b/plat/st/common/stm32cubeprogrammer_usb.c
new file mode 100644
index 0000000..19a6bba
--- /dev/null
+++ b/plat/st/common/stm32cubeprogrammer_usb.c
@@ -0,0 +1,196 @@
+/*
+ * Copyright (c) 2021, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+
+#include <tools_share/firmware_image_package.h>
+
+#include <stm32cubeprogrammer.h>
+#include <usb_dfu.h>
+
+/* Undefined download address */
+#define UNDEFINED_DOWN_ADDR	0xFFFFFFFF
+
+struct dfu_state {
+	uint8_t phase;
+	uintptr_t base;
+	size_t len;
+	uintptr_t address;
+	/* working buffer */
+	uint8_t buffer[UCHAR_MAX];
+};
+
+static struct dfu_state dfu_state;
+
+/* minimal size of Get Pḧase = offset for additionnl information */
+#define	GET_PHASE_LEN	9
+
+#define DFU_ERROR(...) \
+	{ \
+		ERROR(__VA_ARGS__); \
+		if (dfu->phase != PHASE_RESET) { \
+			snprintf((char *)&dfu->buffer[GET_PHASE_LEN], \
+				 sizeof(dfu->buffer) - GET_PHASE_LEN, \
+				 __VA_ARGS__); \
+			dfu->phase = PHASE_RESET; \
+			dfu->address = UNDEFINED_DOWN_ADDR; \
+			dfu->len = 0; \
+		} \
+	}
+
+static bool is_valid_header(fip_toc_header_t *header)
+{
+	if ((header->name == TOC_HEADER_NAME) && (header->serial_number != 0U)) {
+		return true;
+	}
+
+	return false;
+}
+
+static int dfu_callback_upload(uint8_t alt, uintptr_t *buffer, uint32_t *len,
+			       void *user_data)
+{
+	int result = 0;
+	uint32_t length = 0;
+	struct dfu_state *dfu = (struct dfu_state *)user_data;
+
+	switch (usb_dfu_get_phase(alt)) {
+	case PHASE_CMD:
+		/* Get Pḧase */
+		dfu->buffer[0] = dfu->phase;
+		dfu->buffer[1] = (uint8_t)(dfu->address);
+		dfu->buffer[2] = (uint8_t)(dfu->address >> 8);
+		dfu->buffer[3] = (uint8_t)(dfu->address >> 16);
+		dfu->buffer[4] = (uint8_t)(dfu->address >> 24);
+		dfu->buffer[5] = 0x00;
+		dfu->buffer[6] = 0x00;
+		dfu->buffer[7] = 0x00;
+		dfu->buffer[8] = 0x00;
+		length = GET_PHASE_LEN;
+		if (dfu->phase == PHASE_FLASHLAYOUT &&
+		    dfu->address == UNDEFINED_DOWN_ADDR) {
+			INFO("Send detach request\n");
+			dfu->buffer[length++] = 0x01;
+		}
+		if (dfu->phase == PHASE_RESET) {
+			/* error information is added by DFU_ERROR macro */
+			length += strnlen((char *)&dfu->buffer[GET_PHASE_LEN],
+					  sizeof(dfu->buffer) - GET_PHASE_LEN)
+				  - 1;
+		}
+		break;
+
+	default:
+		DFU_ERROR("phase ID :%i, alternate %i for phase %i\n",
+			  dfu->phase, alt, usb_dfu_get_phase(alt));
+		result = -EIO;
+		break;
+	}
+
+	if (result == 0) {
+		*len = length;
+		*buffer = (uintptr_t)dfu->buffer;
+	}
+
+	return result;
+}
+
+static int dfu_callback_download(uint8_t alt, uintptr_t *buffer, uint32_t *len,
+				 void *user_data)
+{
+	struct dfu_state *dfu = (struct dfu_state *)user_data;
+
+	if ((dfu->phase != usb_dfu_get_phase(alt)) ||
+	    (dfu->address == UNDEFINED_DOWN_ADDR)) {
+		DFU_ERROR("phase ID :%i, alternate %i, address %x\n",
+			  dfu->phase, alt, (uint32_t)dfu->address);
+		return -EIO;
+	}
+
+	VERBOSE("Download %d %lx %x\n", alt, dfu->address, *len);
+	*buffer = dfu->address;
+	dfu->address += *len;
+
+	if (dfu->address - dfu->base > dfu->len) {
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int dfu_callback_manifestation(uint8_t alt, void *user_data)
+{
+	struct dfu_state *dfu = (struct dfu_state *)user_data;
+
+	if (dfu->phase != usb_dfu_get_phase(alt)) {
+		ERROR("Manifestation phase ID :%i, alternate %i, address %lx\n",
+		      dfu->phase, alt, dfu->address);
+		return -EIO;
+	}
+
+	INFO("phase ID :%i, Manifestation %d at %lx\n",
+	     dfu->phase, alt, dfu->address);
+
+	switch (dfu->phase) {
+	case PHASE_SSBL:
+		if (!is_valid_header((fip_toc_header_t *)dfu->base)) {
+			DFU_ERROR("FIP Header check failed for phase %d\n", alt);
+			return -EIO;
+		}
+		VERBOSE("FIP header looks OK.\n");
+
+		/* Configure End with request detach */
+		dfu->phase = PHASE_FLASHLAYOUT;
+		dfu->address = UNDEFINED_DOWN_ADDR;
+		dfu->len = 0;
+		break;
+	default:
+		DFU_ERROR("Unknown phase\n");
+	}
+
+	return 0;
+}
+
+/* Open a connection to the USB device */
+static const struct usb_dfu_media usb_dfu_fops = {
+	.upload = dfu_callback_upload,
+	.download = dfu_callback_download,
+	.manifestation = dfu_callback_manifestation,
+};
+
+int stm32cubeprog_usb_load(struct usb_handle *usb_core_handle,
+			   uintptr_t base,
+			   size_t len)
+{
+	int ret;
+
+	usb_core_handle->user_data = (void *)&dfu_state;
+
+	INFO("DFU USB START...\n");
+	ret = usb_core_start(usb_core_handle);
+	if (ret != USBD_OK) {
+		return -EIO;
+	}
+
+	dfu_state.phase = PHASE_SSBL;
+	dfu_state.address = base;
+	dfu_state.base = base;
+	dfu_state.len = len;
+
+	ret = usb_dfu_loop(usb_core_handle, &usb_dfu_fops);
+	if (ret != USBD_OK) {
+		return -EIO;
+	}
+
+	INFO("DFU USB STOP...\n");
+	ret = usb_core_stop(usb_core_handle);
+	if (ret != USBD_OK) {
+		return -EIO;
+	}
+
+	return 0;
+}
diff --git a/plat/st/common/usb_dfu.c b/plat/st/common/usb_dfu.c
new file mode 100644
index 0000000..8bb0994
--- /dev/null
+++ b/plat/st/common/usb_dfu.c
@@ -0,0 +1,538 @@
+/*
+ * Copyright (c) 2021, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <errno.h>
+#include <string.h>
+
+#include <common/debug.h>
+
+#include <platform_def.h>
+#include <usb_dfu.h>
+
+/* Device states as defined in DFU spec */
+#define STATE_APP_IDLE			0
+#define STATE_APP_DETACH		1
+#define STATE_DFU_IDLE			2
+#define STATE_DFU_DNLOAD_SYNC		3
+#define STATE_DFU_DNLOAD_BUSY		4
+#define STATE_DFU_DNLOAD_IDLE		5
+#define STATE_DFU_MANIFEST_SYNC		6
+#define STATE_DFU_MANIFEST		7
+#define STATE_DFU_MANIFEST_WAIT_RESET	8
+#define STATE_DFU_UPLOAD_IDLE		9
+#define STATE_DFU_ERROR			10
+
+/* DFU errors */
+#define DFU_ERROR_NONE			0x00
+#define DFU_ERROR_TARGET		0x01
+#define DFU_ERROR_FILE			0x02
+#define DFU_ERROR_WRITE			0x03
+#define DFU_ERROR_ERASE			0x04
+#define DFU_ERROR_CHECK_ERASED		0x05
+#define DFU_ERROR_PROG			0x06
+#define DFU_ERROR_VERIFY		0x07
+#define DFU_ERROR_ADDRESS		0x08
+#define DFU_ERROR_NOTDONE		0x09
+#define DFU_ERROR_FIRMWARE		0x0A
+#define DFU_ERROR_VENDOR		0x0B
+#define DFU_ERROR_USB			0x0C
+#define DFU_ERROR_POR			0x0D
+#define DFU_ERROR_UNKNOWN		0x0E
+#define DFU_ERROR_STALLEDPKT		0x0F
+
+/* DFU request */
+#define DFU_DETACH			0
+#define DFU_DNLOAD			1
+#define DFU_UPLOAD			2
+#define DFU_GETSTATUS			3
+#define DFU_CLRSTATUS			4
+#define DFU_GETSTATE			5
+#define DFU_ABORT			6
+
+static bool usb_dfu_detach_req;
+
+/*
+ * usb_dfu_init
+ *         Initialize the DFU interface
+ * pdev: device instance
+ * cfgidx: Configuration index
+ * return: status
+ */
+static uint8_t usb_dfu_init(struct usb_handle *pdev, uint8_t cfgidx)
+{
+	(void)pdev;
+	(void)cfgidx;
+
+	/* Nothing to do in this stage */
+	return USBD_OK;
+}
+
+/*
+ * usb_dfu_de_init
+ *         De-Initialize the DFU layer
+ * pdev: device instance
+ * cfgidx: Configuration index
+ * return: status
+ */
+static uint8_t usb_dfu_de_init(struct usb_handle *pdev, uint8_t cfgidx)
+{
+	(void)pdev;
+	(void)cfgidx;
+
+	/* Nothing to do in this stage */
+	return USBD_OK;
+}
+
+/*
+ * usb_dfu_data_in
+ *         handle data IN Stage
+ * pdev: device instance
+ * epnum: endpoint index
+ * return: status
+ */
+static uint8_t usb_dfu_data_in(struct usb_handle *pdev, uint8_t epnum)
+{
+	(void)pdev;
+	(void)epnum;
+
+	return USBD_OK;
+}
+
+/*
+ * usb_dfu_ep0_rx_ready
+ *         handle EP0 Rx Ready event
+ * pdev: device
+ * return: status
+ */
+static uint8_t usb_dfu_ep0_rx_ready(struct usb_handle *pdev)
+{
+	(void)pdev;
+
+	return USBD_OK;
+}
+
+/*
+ * usb_dfu_ep0_tx_ready
+ *         handle EP0 TRx Ready event
+ * pdev: device instance
+ * return: status
+ */
+static uint8_t usb_dfu_ep0_tx_ready(struct usb_handle *pdev)
+{
+	(void)pdev;
+
+	return USBD_OK;
+}
+
+/*
+ * usb_dfu_sof
+ *         handle SOF event
+ * pdev: device instance
+ * return: status
+ */
+static uint8_t usb_dfu_sof(struct usb_handle *pdev)
+{
+	(void)pdev;
+
+	return USBD_OK;
+}
+
+/*
+ * usb_dfu_iso_in_incomplete
+ *         handle data ISO IN Incomplete event
+ * pdev: device instance
+ * epnum: endpoint index
+ * return: status
+ */
+static uint8_t usb_dfu_iso_in_incomplete(struct usb_handle *pdev, uint8_t epnum)
+{
+	(void)pdev;
+	(void)epnum;
+
+	return USBD_OK;
+}
+
+/*
+ * usb_dfu_iso_out_incomplete
+ *         handle data ISO OUT Incomplete event
+ * pdev: device instance
+ * epnum: endpoint index
+ * return: status
+ */
+static uint8_t usb_dfu_iso_out_incomplete(struct usb_handle *pdev,
+					  uint8_t epnum)
+{
+	(void)pdev;
+	(void)epnum;
+
+	return USBD_OK;
+}
+
+/*
+ * usb_dfu_data_out
+ *         handle data OUT Stage
+ * pdev: device instance
+ * epnum: endpoint index
+ * return: status
+ */
+static uint8_t usb_dfu_data_out(struct usb_handle *pdev, uint8_t epnum)
+{
+	(void)pdev;
+	(void)epnum;
+
+	return USBD_OK;
+}
+
+/*
+ * usb_dfu_detach
+ *         Handles the DFU DETACH request.
+ * pdev: device instance
+ * req: pointer to the request structure.
+ */
+static void usb_dfu_detach(struct usb_handle *pdev, struct usb_setup_req *req)
+{
+	struct usb_dfu_handle *hdfu = (struct usb_dfu_handle *)pdev->class_data;
+
+	INFO("Receive DFU Detach\n");
+
+	if ((hdfu->dev_state == STATE_DFU_IDLE) ||
+	    (hdfu->dev_state == STATE_DFU_DNLOAD_SYNC) ||
+	    (hdfu->dev_state == STATE_DFU_DNLOAD_IDLE) ||
+	    (hdfu->dev_state == STATE_DFU_MANIFEST_SYNC) ||
+	    (hdfu->dev_state == STATE_DFU_UPLOAD_IDLE)) {
+		/* Update the state machine */
+		hdfu->dev_state = STATE_DFU_IDLE;
+		hdfu->dev_status = DFU_ERROR_NONE;
+	}
+
+	usb_dfu_detach_req = true;
+}
+
+/*
+ * usb_dfu_download
+ *         Handles the DFU DNLOAD request.
+ * pdev: device instance
+ * req: pointer to the request structure
+ */
+static void usb_dfu_download(struct usb_handle *pdev, struct usb_setup_req *req)
+{
+	struct usb_dfu_handle *hdfu = (struct usb_dfu_handle *)pdev->class_data;
+	uintptr_t data_ptr;
+	uint32_t length;
+	int ret;
+
+	/* Data setup request */
+	if (req->length > 0) {
+		/* Unsupported state */
+		if ((hdfu->dev_state != STATE_DFU_IDLE) &&
+		    (hdfu->dev_state != STATE_DFU_DNLOAD_IDLE)) {
+			/* Call the error management function (command will be nacked) */
+			usb_core_ctl_error(pdev);
+			return;
+		}
+
+		/* Get the data address */
+		length = req->length;
+		ret = hdfu->callback->download(hdfu->alt_setting, &data_ptr,
+					       &length, pdev->user_data);
+		if (ret == 0U) {
+			/* Update the state machine */
+			hdfu->dev_state = STATE_DFU_DNLOAD_SYNC;
+			/* Start the transfer */
+			usb_core_receive_ep0(pdev, (uint8_t *)data_ptr, length);
+		} else {
+			usb_core_ctl_error(pdev);
+		}
+	} else {
+		/* End of DNLOAD operation*/
+		if (hdfu->dev_state != STATE_DFU_DNLOAD_IDLE) {
+			/* Call the error management function (command will be nacked) */
+			usb_core_ctl_error(pdev);
+			return;
+		}
+		/* End of DNLOAD operation*/
+		hdfu->dev_state = STATE_DFU_MANIFEST_SYNC;
+		ret = hdfu->callback->manifestation(hdfu->alt_setting, pdev->user_data);
+		if (ret == 0U) {
+			hdfu->dev_state = STATE_DFU_MANIFEST_SYNC;
+		} else {
+			usb_core_ctl_error(pdev);
+		}
+	}
+}
+
+/*
+ * usb_dfu_upload
+ *         Handles the DFU UPLOAD request.
+ * pdev: instance
+ * req: pointer to the request structure
+ */
+static void usb_dfu_upload(struct usb_handle *pdev, struct usb_setup_req *req)
+{
+	struct usb_dfu_handle *hdfu = (struct usb_dfu_handle *)pdev->class_data;
+	uintptr_t data_ptr;
+	uint32_t length;
+	int ret;
+
+	/* Data setup request */
+	if (req->length == 0) {
+		/* No Data setup request */
+		hdfu->dev_state = STATE_DFU_IDLE;
+		return;
+	}
+
+	/* Unsupported state */
+	if ((hdfu->dev_state != STATE_DFU_IDLE) && (hdfu->dev_state != STATE_DFU_UPLOAD_IDLE)) {
+		ERROR("UPLOAD : Unsupported State\n");
+		/* Call the error management function (command will be nacked) */
+		usb_core_ctl_error(pdev);
+		return;
+	}
+
+	/* Update the data address */
+	length = req->length;
+	ret = hdfu->callback->upload(hdfu->alt_setting, &data_ptr, &length, pdev->user_data);
+	if (ret == 0U) {
+		/* Short frame */
+		hdfu->dev_state = (req->length > length) ? STATE_DFU_IDLE : STATE_DFU_UPLOAD_IDLE;
+
+		/* Start the transfer */
+		usb_core_transmit_ep0(pdev, (uint8_t *)data_ptr, length);
+	} else {
+		ERROR("UPLOAD : bad block %i on alt %i\n", req->value, req->index);
+		hdfu->dev_state = STATE_DFU_ERROR;
+		hdfu->dev_status = DFU_ERROR_STALLEDPKT;
+
+		/* Call the error management function (command will be nacked) */
+		usb_core_ctl_error(pdev);
+	}
+}
+
+/*
+ * usb_dfu_get_status
+ *         Handles the DFU GETSTATUS request.
+ * pdev: instance
+ */
+static void usb_dfu_get_status(struct usb_handle *pdev)
+{
+	struct usb_dfu_handle *hdfu = (struct usb_dfu_handle *)pdev->class_data;
+
+	hdfu->status[0] = hdfu->dev_status;	/* bStatus */
+	hdfu->status[1] = 0;			/* bwPollTimeout[3] */
+	hdfu->status[2] = 0;
+	hdfu->status[3] = 0;
+	hdfu->status[4] = hdfu->dev_state;	/* bState */
+	hdfu->status[5] = 0;			/* iString */
+
+	/* next step */
+	switch (hdfu->dev_state) {
+	case STATE_DFU_DNLOAD_SYNC:
+		hdfu->dev_state = STATE_DFU_DNLOAD_IDLE;
+		break;
+	case STATE_DFU_MANIFEST_SYNC:
+		/* the device is 'ManifestationTolerant' */
+		hdfu->status[4] = STATE_DFU_MANIFEST;
+		hdfu->status[1] = 1U; /* bwPollTimeout = 1ms */
+		hdfu->dev_state = STATE_DFU_IDLE;
+		break;
+
+	default:
+		break;
+	}
+
+	/* Start the transfer */
+	usb_core_transmit_ep0(pdev, (uint8_t *)&hdfu->status[0], sizeof(hdfu->status));
+}
+
+/*
+ * usb_dfu_clear_status
+ *         Handles the DFU CLRSTATUS request.
+ * pdev: device instance
+ */
+static void usb_dfu_clear_status(struct usb_handle *pdev)
+{
+	struct usb_dfu_handle *hdfu = (struct usb_dfu_handle *)pdev->class_data;
+
+	if (hdfu->dev_state == STATE_DFU_ERROR) {
+		hdfu->dev_state = STATE_DFU_IDLE;
+		hdfu->dev_status = DFU_ERROR_NONE;
+	} else {
+		/* State Error */
+		hdfu->dev_state = STATE_DFU_ERROR;
+		hdfu->dev_status = DFU_ERROR_UNKNOWN;
+	}
+}
+
+/*
+ * usb_dfu_get_state
+ *         Handles the DFU GETSTATE request.
+ * pdev: device instance
+ */
+static void usb_dfu_get_state(struct usb_handle *pdev)
+{
+	struct usb_dfu_handle *hdfu = (struct usb_dfu_handle *)pdev->class_data;
+
+	/* Return the current state of the DFU interface */
+	usb_core_transmit_ep0(pdev, &hdfu->dev_state, 1);
+}
+
+/*
+ * usb_dfu_abort
+ *         Handles the DFU ABORT request.
+ * pdev: device instance
+ */
+static void usb_dfu_abort(struct usb_handle *pdev)
+{
+	struct usb_dfu_handle *hdfu = (struct usb_dfu_handle *)pdev->class_data;
+
+	if ((hdfu->dev_state == STATE_DFU_IDLE) ||
+	    (hdfu->dev_state == STATE_DFU_DNLOAD_SYNC) ||
+	    (hdfu->dev_state == STATE_DFU_DNLOAD_IDLE) ||
+	    (hdfu->dev_state == STATE_DFU_MANIFEST_SYNC) ||
+	    (hdfu->dev_state == STATE_DFU_UPLOAD_IDLE)) {
+		hdfu->dev_state = STATE_DFU_IDLE;
+		hdfu->dev_status = DFU_ERROR_NONE;
+	}
+}
+
+/*
+ * usb_dfu_setup
+ *         Handle the DFU specific requests
+ * pdev: instance
+ * req: usb requests
+ * return: status
+ */
+static uint8_t usb_dfu_setup(struct usb_handle *pdev, struct usb_setup_req *req)
+{
+	uint8_t *pbuf = NULL;
+	uint16_t len = 0U;
+	uint8_t ret = USBD_OK;
+	struct usb_dfu_handle *hdfu = (struct usb_dfu_handle *)pdev->class_data;
+
+	switch (req->bm_request & USB_REQ_TYPE_MASK) {
+	case USB_REQ_TYPE_CLASS:
+		switch (req->b_request) {
+		case DFU_DNLOAD:
+			usb_dfu_download(pdev, req);
+			break;
+
+		case DFU_UPLOAD:
+			usb_dfu_upload(pdev, req);
+			break;
+
+		case DFU_GETSTATUS:
+			usb_dfu_get_status(pdev);
+			break;
+
+		case DFU_CLRSTATUS:
+			usb_dfu_clear_status(pdev);
+			break;
+
+		case DFU_GETSTATE:
+			usb_dfu_get_state(pdev);
+			break;
+
+		case DFU_ABORT:
+			usb_dfu_abort(pdev);
+			break;
+
+		case DFU_DETACH:
+			usb_dfu_detach(pdev, req);
+			break;
+
+		default:
+			ERROR("unknown request %x on alternate %i\n",
+			      req->b_request, hdfu->alt_setting);
+			usb_core_ctl_error(pdev);
+			ret = USBD_FAIL;
+			break;
+		}
+		break;
+	case USB_REQ_TYPE_STANDARD:
+		switch (req->b_request) {
+		case USB_REQ_GET_DESCRIPTOR:
+			if (HIBYTE(req->value) == DFU_DESCRIPTOR_TYPE) {
+				pbuf = pdev->desc->get_config_desc(&len);
+				/* DFU descriptor at the end of the USB */
+				pbuf += len - 9U;
+				len = 9U;
+				len = MIN(len, req->length);
+			}
+
+			/* Start the transfer */
+			usb_core_transmit_ep0(pdev, pbuf, len);
+
+			break;
+
+		case USB_REQ_GET_INTERFACE:
+			/* Start the transfer */
+			usb_core_transmit_ep0(pdev, (uint8_t *)&hdfu->alt_setting, 1U);
+			break;
+
+		case USB_REQ_SET_INTERFACE:
+			hdfu->alt_setting = LOBYTE(req->value);
+			break;
+
+		default:
+			usb_core_ctl_error(pdev);
+			ret = USBD_FAIL;
+			break;
+		}
+	default:
+		break;
+	}
+
+	return ret;
+}
+
+static const struct usb_class usb_dfu = {
+	.init = usb_dfu_init,
+	.de_init = usb_dfu_de_init,
+	.setup = usb_dfu_setup,
+	.ep0_tx_sent = usb_dfu_ep0_tx_ready,
+	.ep0_rx_ready = usb_dfu_ep0_rx_ready,
+	.data_in = usb_dfu_data_in,
+	.data_out = usb_dfu_data_out,
+	.sof = usb_dfu_sof,
+	.iso_in_incomplete = usb_dfu_iso_in_incomplete,
+	.iso_out_incomplete = usb_dfu_iso_out_incomplete,
+};
+
+void usb_dfu_register(struct usb_handle *pdev, struct usb_dfu_handle *phandle)
+{
+	pdev->class = (struct usb_class *)&usb_dfu;
+	pdev->class_data = phandle;
+
+	phandle->dev_state = STATE_DFU_IDLE;
+	phandle->dev_status = DFU_ERROR_NONE;
+}
+
+int usb_dfu_loop(struct usb_handle *pdev, const struct usb_dfu_media *pmedia)
+{
+	uint32_t it_count;
+	enum usb_status ret;
+	struct usb_dfu_handle *hdfu = (struct usb_dfu_handle *)pdev->class_data;
+
+	hdfu->callback = pmedia;
+	usb_dfu_detach_req = false;
+	/* Continue to handle USB core IT to assure complete data transmission */
+	it_count = 100U;
+
+	/* DFU infinite loop until DETACH_REQ */
+	while (it_count != 0U) {
+		ret = usb_core_handle_it(pdev);
+		if (ret != USBD_OK) {
+			return -EIO;
+		}
+
+		/* Detach request received */
+		if (usb_dfu_detach_req) {
+			it_count--;
+		}
+	}
+
+	return 0;
+}
diff --git a/plat/st/stm32mp1/bl2_plat_setup.c b/plat/st/stm32mp1/bl2_plat_setup.c
index e87c529..7eaf0ed 100644
--- a/plat/st/stm32mp1/bl2_plat_setup.c
+++ b/plat/st/stm32mp1/bl2_plat_setup.c
@@ -490,5 +490,19 @@
 
 void bl2_el3_plat_prepare_exit(void)
 {
+	uint16_t boot_itf = stm32mp_get_boot_itf_selected();
+
+	switch (boot_itf) {
+#if STM32MP_USB_PROGRAMMER
+	case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB:
+		/* Invalidate the downloaded buffer used with io_memmap */
+		inv_dcache_range(DWL_BUFFER_BASE, DWL_BUFFER_SIZE);
+		break;
+#endif
+	default:
+		/* Do nothing in default case */
+		break;
+	}
+
 	stm32mp1_security_setup();
 }
diff --git a/plat/st/stm32mp1/include/boot_api.h b/plat/st/stm32mp1/include/boot_api.h
index c16639a..52b1d1a 100644
--- a/plat/st/stm32mp1/include/boot_api.h
+++ b/plat/st/stm32mp1/include/boot_api.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2017-2021, STMicroelectronics - All Rights Reserved
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -39,6 +39,9 @@
 /* Boot occurred on QSPI NOR */
 #define BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NOR_QSPI		0x4U
 
+/* Boot occurred on USB */
+#define BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB		0x6U
+
 /* Boot occurred on QSPI NAND */
 #define BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_QSPI		0x7U
 
diff --git a/plat/st/stm32mp1/include/platform_def.h b/plat/st/stm32mp1/include/platform_def.h
index 8a065bf..1e9443e 100644
--- a/plat/st/stm32mp1/include/platform_def.h
+++ b/plat/st/stm32mp1/include/platform_def.h
@@ -92,6 +92,10 @@
  */
 #define PLAT_STM32MP_NS_IMAGE_OFFSET	BL33_BASE
 
+/* Needed by STM32CubeProgrammer support */
+#define DWL_BUFFER_BASE			(STM32MP_DDR_BASE + U(0x08000000))
+#define DWL_BUFFER_SIZE			U(0x08000000)
+
 /*
  * SSBL offset in case it's stored in eMMC boot partition.
  * We can fix it to 256K because TF-A size can't be bigger than SRAM
diff --git a/plat/st/stm32mp1/platform.mk b/plat/st/stm32mp1/platform.mk
index 14f90d4..badc926 100644
--- a/plat/st/stm32mp1/platform.mk
+++ b/plat/st/stm32mp1/platform.mk
@@ -53,6 +53,9 @@
 STM32MP_SPI_NOR		?=	0
 STM32MP_EMMC_BOOT	?=	0
 
+# Serial boot devices
+STM32MP_USB_PROGRAMMER	?=	0
+
 # Device tree
 DTB_FILE_NAME		?=	stm32mp157c-ev1.dtb
 ifeq ($(STM32MP_USE_STM32IMAGE),1)
@@ -127,6 +130,7 @@
 		STM32MP_SPI_NOR \
 		STM32MP_EMMC_BOOT \
 		PLAT_XLAT_TABLES_DYNAMIC \
+		STM32MP_USB_PROGRAMMER \
 		STM32MP_USE_STM32IMAGE \
 )))
 
@@ -147,6 +151,7 @@
 		PLAT_XLAT_TABLES_DYNAMIC \
 		STM32_TF_A_COPIES \
 		PLAT_PARTITION_MAX_ENTRIES \
+		STM32MP_USB_PROGRAMMER \
 		STM32MP_USE_STM32IMAGE \
 )))
 
@@ -154,15 +159,17 @@
 PLAT_INCLUDES		:=	-Iplat/st/common/include/
 PLAT_INCLUDES		+=	-Iplat/st/stm32mp1/include/
 
+ifeq (${STM32MP_USE_STM32IMAGE},1)
 include common/fdt_wrappers.mk
+else
+include lib/fconf/fconf.mk
+endif
 include lib/libfdt/libfdt.mk
 
 PLAT_BL_COMMON_SOURCES	:=	common/uuid.c						\
 				plat/st/common/stm32mp_common.c				\
 				plat/st/stm32mp1/stm32mp1_private.c
 
-PLAT_BL_COMMON_SOURCES	+=	${FDT_WRAPPERS_SOURCES}
-
 PLAT_BL_COMMON_SOURCES	+=	drivers/st/uart/aarch32/stm32_console.S
 
 ifneq (${ENABLE_STACK_PROTECTOR},0)
@@ -194,14 +201,16 @@
 				plat/st/stm32mp1/stm32mp1_syscfg.c
 
 ifneq (${STM32MP_USE_STM32IMAGE},1)
+BL2_SOURCES		+=	${FCONF_SOURCES} ${FCONF_DYN_SOURCES}
+
 BL2_SOURCES		+=	drivers/io/io_fip.c					\
-				lib/fconf/fconf.c					\
-				lib/fconf/fconf_dyn_cfg_getter.c			\
 				plat/st/common/bl2_io_storage.c				\
 				plat/st/common/stm32mp_fconf_io.c			\
 				plat/st/stm32mp1/plat_bl2_mem_params_desc.c		\
 				plat/st/stm32mp1/stm32mp1_fconf_firewall.c
 else
+BL2_SOURCES		+=	${FDT_WRAPPERS_SOURCES}
+
 BL2_SOURCES		+=	drivers/io/io_dummy.c					\
 				drivers/st/io/io_stm32image.c				\
 				plat/st/common/bl2_stm32_io_storage.c			\
@@ -251,6 +260,17 @@
 BL2_SOURCES		+=	plat/st/stm32mp1/stm32mp1_boot_device.c
 endif
 
+ifeq (${STM32MP_USB_PROGRAMMER},1)
+#The DFU stack uses only one end point, reduce the USB stack footprint
+$(eval $(call add_define_val,CONFIG_USBD_EP_NB,1U))
+BL2_SOURCES		+=	drivers/io/io_memmap.c					\
+				drivers/st/usb/stm32mp1_usb.c				\
+				drivers/usb/usb_device.c				\
+				plat/st/common/stm32cubeprogrammer_usb.c		\
+				plat/st/common/usb_dfu.c					\
+				plat/st/stm32mp1/stm32mp1_usb_dfu.c
+endif
+
 BL2_SOURCES		+=	drivers/st/ddr/stm32mp1_ddr.c				\
 				drivers/st/ddr/stm32mp1_ram.c
 
@@ -274,7 +294,8 @@
 	    [ ${STM32MP_SDMMC} != 1 ] && \
 	    [ ${STM32MP_RAW_NAND} != 1 ] && \
 	    [ ${STM32MP_SPI_NAND} != 1 ] && \
-	    [ ${STM32MP_SPI_NOR} != 1 ]; then \
+	    [ ${STM32MP_SPI_NOR} != 1 ] && \
+	    [ ${STM32MP_USB_PROGRAMMER} != 1 ]; then \
 		echo "No boot device driver is enabled"; \
 		false; \
 	fi
diff --git a/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk b/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk
index 4d4820a..239b60a 100644
--- a/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk
+++ b/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk
@@ -15,6 +15,10 @@
 				plat/st/stm32mp1/stm32mp1_shared_resources.c	\
 				plat/st/stm32mp1/stm32mp1_topology.c
 
+# FDT wrappers
+include common/fdt_wrappers.mk
+BL32_SOURCES		+=	${FDT_WRAPPERS_SOURCES}
+
 # Generic GIC v2
 include drivers/arm/gic/v2/gicv2.mk
 
diff --git a/plat/st/stm32mp1/stm32mp1_def.h b/plat/st/stm32mp1/stm32mp1_def.h
index 469c2d9..f5d4b2f 100644
--- a/plat/st/stm32mp1/stm32mp1_def.h
+++ b/plat/st/stm32mp1/stm32mp1_def.h
@@ -339,6 +339,9 @@
 #define DATA0_OTP			U(0)
 #define PART_NUMBER_OTP			U(1)
 #define NAND_OTP			U(9)
+#define UID0_OTP			U(13)
+#define UID1_OTP			U(14)
+#define UID2_OTP			U(15)
 #define PACKAGE_OTP			U(16)
 #define HW2_OTP				U(18)
 
@@ -401,6 +404,9 @@
 /* NAND number of planes */
 #define NAND_PLANE_BIT_NB_MASK		BIT(14)
 
+/* UID OTP */
+#define UID_WORD_NB			U(3)
+
 /*******************************************************************************
  * STM32MP1 TAMP
  ******************************************************************************/
@@ -415,6 +421,11 @@
 #endif
 
 /*******************************************************************************
+ * STM32MP1 USB
+ ******************************************************************************/
+#define USB_OTG_BASE			U(0x49000000)
+
+/*******************************************************************************
  * STM32MP1 DDRCTRL
  ******************************************************************************/
 #define DDRCTRL_BASE			U(0x5A003000)
diff --git a/plat/st/stm32mp1/stm32mp1_usb_dfu.c b/plat/st/stm32mp1/stm32mp1_usb_dfu.c
new file mode 100644
index 0000000..051d435
--- /dev/null
+++ b/plat/st/stm32mp1/stm32mp1_usb_dfu.c
@@ -0,0 +1,388 @@
+/*
+ * Copyright (c) 2021, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <limits.h>
+#include <string.h>
+
+#include <common/debug.h>
+#include <drivers/st/bsec.h>
+#include <drivers/st/stm32mp1_usb.h>
+#include <drivers/usb_device.h>
+
+#include <platform_def.h>
+#include <stm32cubeprogrammer.h>
+#include <stm32mp_common.h>
+#include <usb_dfu.h>
+
+/*  String size (1 byte) + type (1 byte) + 24 UTF16 characters: 2 bytes each */
+#define SIZ_STRING_SERIAL		U(24)
+#define USB_SIZ_STRING_SERIAL		(1U + 1U + (SIZ_STRING_SERIAL * 2U))
+#define USBD_MAX_STR_DESC_SIZ		0x100
+#define USBD_VID			0x0483
+#define USBD_PID			0xDF11
+#define USBD_LANGID_STRING		0x409
+#define USBD_MANUFACTURER_STRING	"STMicroelectronics"
+#define USBD_CONFIGURATION_STRING	"DFU Config"
+#define USBD_INTERFACE_STRING		"DFU Interface"
+
+#define USB_DFU_ITF_NUM			6
+
+#define USB_DFU_CONFIG_DESC_SIZ		USB_DFU_DESC_SIZ(USB_DFU_ITF_NUM)
+
+/* DFU devices */
+static struct usb_dfu_handle usb_dfu_handle;
+
+/* USB Standard Device Descriptor */
+static const uint8_t usb_stm32mp1_desc[USB_LEN_DEV_DESC] = {
+	USB_LEN_DEV_DESC,           /* bLength */
+	USB_DESC_TYPE_DEVICE,       /* bDescriptorType */
+	0x00,                       /* bcdUSB */
+	0x02,                       /* version */
+	0x00,                       /* bDeviceClass */
+	0x00,                       /* bDeviceSubClass */
+	0x00,                       /* bDeviceProtocol */
+	USB_MAX_EP0_SIZE,           /* bMaxPacketSize */
+	LOBYTE(USBD_VID),           /* idVendor */
+	HIBYTE(USBD_VID),           /* idVendor */
+	LOBYTE(USBD_PID),           /* idVendor */
+	HIBYTE(USBD_PID),           /* idVendor */
+	0x00,                       /* bcdDevice rel. 2.00 */
+	0x02,
+	USBD_IDX_MFC_STR,           /* Index of manufacturer string */
+	USBD_IDX_PRODUCT_STR,       /* Index of product string */
+	USBD_IDX_SERIAL_STR,        /* Index of serial number string */
+	USBD_MAX_NUM_CONFIGURATION  /* bNumConfigurations */
+}; /* USB_DeviceDescriptor */
+
+/* USB Standard String Descriptor */
+static const uint8_t usb_stm32mp1_lang_id_desc[USB_LEN_LANGID_STR_DESC] = {
+	USB_LEN_LANGID_STR_DESC,
+	USB_DESC_TYPE_STRING,
+	LOBYTE(USBD_LANGID_STRING),
+	HIBYTE(USBD_LANGID_STRING),
+};
+
+/* USB Standard Device Descriptor */
+static const uint8_t
+usbd_stm32mp1_qualifier_desc[USB_LEN_DEV_QUALIFIER_DESC] = {
+	USB_LEN_DEV_QUALIFIER_DESC,
+	USB_DESC_TYPE_DEVICE_QUALIFIER,
+	0x00,
+	0x02,
+	0x00,
+	0x00,
+	0x00,
+	0x40,
+	0x01,
+	0x00,
+};
+
+/* USB serial number: build dynamically */
+static uint8_t usb_stm32mp1_serial[USB_SIZ_STRING_SERIAL + 1];
+
+/* USB DFU device Configuration Descriptor */
+static const uint8_t usb_stm32mp1_config_desc[USB_DFU_CONFIG_DESC_SIZ] = {
+	0x09, /* bLength: Configuration Descriptor size */
+	USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */
+	USB_DFU_CONFIG_DESC_SIZ, /* wTotalLength: Bytes returned */
+	0x00,
+	0x01, /* bNumInterfaces: 1 interface */
+	0x01, /* bConfigurationValue: Configuration value */
+	0x02, /* iConfiguration: Index of string descriptor for configuration */
+	0xC0, /* bmAttributes: bus powered and Supprts Remote Wakeup */
+	0x32, /* MaxPower 100 mA: this current is used for detecting Vbus */
+
+	/* Descriptor of DFU interface 0 Alternate setting 0..N */
+	USBD_DFU_IF_DESC(0),
+	USBD_DFU_IF_DESC(1),
+	USBD_DFU_IF_DESC(2),
+	USBD_DFU_IF_DESC(3),
+	USBD_DFU_IF_DESC(4),
+	USBD_DFU_IF_DESC(5),
+
+	/* DFU Functional Descriptor */
+	0x09, /* blength = 9 Bytes */
+	DFU_DESCRIPTOR_TYPE, /* DFU Functional Descriptor */
+	DFU_BM_ATTRIBUTE, /* bmAttribute for DFU */
+	0xFF, /* DetachTimeOut = 255 ms */
+	0x00,
+	TRANSFER_SIZE_BYTES(USBD_DFU_XFER_SIZE), /* TransferSize = 1024 Byte */
+	((USB_DFU_VERSION >> 0) & 0xFF), /* bcdDFUVersion */
+	((USB_DFU_VERSION >> 8) & 0xFF)
+};
+
+/* The user strings: one by alternate as defined in USBD_DFU_IF_DESC */
+const char *const if_desc_string[USB_DFU_ITF_NUM] = {
+	"@Partition0 /0x00/1*256Ke",
+	"@FSBL /0x01/1*1Me",
+	"@Partition2 /0x02/1*1Me",
+	"@Partition3 /0x03/1*16Me",
+	"@Partition4 /0x04/1*16Me",
+	"@virtual /0xF1/1*512Ba"
+};
+
+/* Buffer to build the unicode string provided to USB device stack */
+static uint8_t usb_str_dec[USBD_MAX_STR_DESC_SIZ];
+
+/*
+ * Convert Ascii string into unicode one
+ * desc : descriptor buffer
+ * unicode : Formatted string buffer (unicode)
+ * len : descriptor length
+ */
+static void stm32mp1_get_string(const char *desc, uint8_t *unicode, uint16_t *len)
+{
+	uint8_t idx = 0U;
+
+	if (desc == NULL) {
+		return;
+	}
+
+	*len =  strlen(desc) * 2U + 2U;
+	unicode[idx++] = *len;
+	unicode[idx++] =  USB_DESC_TYPE_STRING;
+
+	while (*desc != '\0') {
+		unicode[idx++] = *desc++;
+		unicode[idx++] =  0x00U;
+	}
+}
+
+/*
+ * Create the serial number string descriptor
+ */
+static void update_serial_num_string(void)
+{
+	uint8_t i;
+	uint32_t result;
+	char serial_string[SIZ_STRING_SERIAL + 2U];
+	uint32_t deviceserial[UID_WORD_NB];
+	uint16_t length;
+
+	for (i = 0U; i < UID_WORD_NB; i++) {
+		result = bsec_shadow_register(i + UID0_OTP);
+		if (result != BSEC_OK) {
+			ERROR("BSEC: UID%d Shadowing Error\n", i);
+			break;
+		}
+		result = bsec_read_otp(&deviceserial[i], i + UID0_OTP);
+		if (result != BSEC_OK) {
+			ERROR("BSEC: UID%d Read Error\n", i);
+			break;
+		}
+	}
+	/* On bsec error: serial number is set to 0 */
+	if (result != BSEC_OK) {
+		for (i = 0; i < UID_WORD_NB; i++) {
+			deviceserial[i] = 0U;
+		}
+	}
+	/* build serial number with OTP value as in ROM code */
+	snprintf(serial_string, sizeof(serial_string), "%08X%08X%08X",
+		 deviceserial[0], deviceserial[1], deviceserial[2]);
+
+	length = USB_SIZ_STRING_SERIAL;
+	stm32mp1_get_string(serial_string, usb_stm32mp1_serial, &length);
+}
+
+/*
+ * Return Device Qualifier descriptor
+ * length : pointer data length
+ * return : pointer to descriptor buffer
+ */
+static uint8_t *stm32mp1_get_qualifier_desc(uint16_t *length)
+{
+	*length = sizeof(usbd_stm32mp1_qualifier_desc);
+
+	return (uint8_t *)usbd_stm32mp1_qualifier_desc;
+}
+
+/*
+ * Return configuration descriptor
+ * length : pointer data length
+ * return : pointer to descriptor buffer
+ */
+static uint8_t *stm32mp1_get_config_desc(uint16_t *length)
+{
+	*length = sizeof(usb_stm32mp1_config_desc);
+
+	return (uint8_t *)usb_stm32mp1_config_desc;
+}
+
+/*
+ * Returns the device descriptor.
+ * length: Pointer to data length variable
+ * return : Pointer to descriptor buffer
+ */
+static uint8_t *stm32mp1_device_desc(uint16_t *length)
+{
+	*length = sizeof(usb_stm32mp1_desc);
+
+	return (uint8_t *)usb_stm32mp1_desc;
+}
+
+/*
+ * Returns the LangID string descriptor.
+ * length: Pointer to data length variable
+ * return : Pointer to descriptor buffer
+ */
+static uint8_t *stm32mp1_lang_id_desc(uint16_t *length)
+{
+	*length = sizeof(usb_stm32mp1_lang_id_desc);
+
+	return (uint8_t *)usb_stm32mp1_lang_id_desc;
+}
+
+/*
+ *  Returns the product string descriptor.
+ * length: Pointer to data length variable
+ * return : Pointer to descriptor buffer
+ */
+static uint8_t *stm32mp1_product_desc(uint16_t *length)
+{
+	char name[STM32_SOC_NAME_SIZE];
+	char product[128];
+	uint32_t chip_id;
+	uint32_t chip_version;
+
+	stm32mp_get_soc_name(name);
+	chip_id = stm32mp_get_chip_dev_id();
+	chip_version = stm32mp_get_chip_version();
+
+	snprintf(product, sizeof(product),
+		 "DFU @Device ID /0x%03X, @Revision ID /0x%04X, @Name /%s,",
+		 chip_id, chip_version, name);
+
+	stm32mp1_get_string(product, usb_str_dec, length);
+
+	return usb_str_dec;
+}
+
+/*
+ * Returns the manufacturer string descriptor.
+ * length: Pointer to data length variable
+ * return : Pointer to descriptor buffer
+ */
+static uint8_t *stm32mp1_manufacturer_desc(uint16_t *length)
+{
+	stm32mp1_get_string(USBD_MANUFACTURER_STRING, usb_str_dec, length);
+
+	return usb_str_dec;
+}
+
+/*
+ * Returns the serial number string descriptor.
+ * length: Pointer to data length variable
+ * return : Pointer to descriptor buffer
+ */
+static uint8_t *stm32mp1_serial_desc(uint16_t *length)
+{
+	*length = USB_SIZ_STRING_SERIAL;
+
+	return (uint8_t *)usb_stm32mp1_serial;
+}
+
+/*
+ * Returns the configuration string descriptor.
+ * length: Pointer to data length variable
+ * return : Pointer to descriptor buffer
+ */
+static uint8_t *stm32mp1_config_desc(uint16_t *length)
+{
+	stm32mp1_get_string(USBD_CONFIGURATION_STRING, usb_str_dec, length);
+
+	return usb_str_dec;
+}
+
+/*
+ * Returns the interface string descriptor.
+ * length : Pointer to data length variable
+ * return : Pointer to descriptor buffer
+ */
+static uint8_t *stm32mp1_interface_desc(uint16_t *length)
+{
+	stm32mp1_get_string(USBD_INTERFACE_STRING, usb_str_dec, length);
+
+	return usb_str_dec;
+}
+
+/*
+ * Manages the transfer of memory interfaces string descriptors.
+ * index: descriptor index
+ * length : pointer data length
+ * return : pointer to the descriptor table or NULL if the descriptor
+ *          is not supported.
+ */
+static uint8_t *stm32mp1_get_usr_desc(uint8_t index, uint16_t *length)
+{
+	if (index >= ARRAY_SIZE(if_desc_string)) {
+		return NULL;
+	}
+
+	stm32mp1_get_string(if_desc_string[index], usb_str_dec, length);
+
+	return usb_str_dec;
+}
+
+static const struct usb_desc dfu_desc = {
+	.get_device_desc = stm32mp1_device_desc,
+	.get_lang_id_desc = stm32mp1_lang_id_desc,
+	.get_manufacturer_desc = stm32mp1_manufacturer_desc,
+	.get_product_desc = stm32mp1_product_desc,
+	.get_configuration_desc = stm32mp1_config_desc,
+	.get_serial_desc = stm32mp1_serial_desc,
+	.get_interface_desc = stm32mp1_interface_desc,
+	.get_usr_desc = stm32mp1_get_usr_desc,
+	.get_config_desc = stm32mp1_get_config_desc,
+	.get_device_qualifier_desc = stm32mp1_get_qualifier_desc,
+};
+
+static struct usb_handle usb_core_handle;
+static struct pcd_handle pcd_handle;
+
+struct usb_handle *usb_dfu_plat_init(void)
+{
+	/* Prepare USB Driver */
+	pcd_handle.in_ep[0].maxpacket = USB_MAX_EP0_SIZE;
+	pcd_handle.out_ep[0].maxpacket = USB_MAX_EP0_SIZE;
+	stm32mp1_usb_init_driver(&usb_core_handle, &pcd_handle,
+				 (uint32_t *)USB_OTG_BASE);
+
+	/* STM32MP15 = keep the configuration from ROM code */
+	usb_core_handle.ep0_state = USBD_EP0_DATA_IN;
+	usb_core_handle.dev_state = USBD_STATE_CONFIGURED;
+
+	/* Update the serial number string descriptor from the unique ID */
+	update_serial_num_string();
+
+	/* Prepare USB DFU stack */
+	usb_dfu_register(&usb_core_handle, &usb_dfu_handle);
+
+	/* Register DFU descriptor in USB stack */
+	register_platform(&usb_core_handle, &dfu_desc);
+
+	return &usb_core_handle;
+}
+
+/* Link between USB alternate and STM32CubeProgramer phase */
+uint8_t usb_dfu_get_phase(uint8_t alt)
+{
+	uint8_t ret;
+
+	switch (alt) {
+	case 3:
+		ret = PHASE_SSBL;
+		break;
+	case 5:
+		ret = PHASE_CMD;
+		break;
+	default:
+		ret = PHASE_RESET;
+		break;
+	}
+
+	return ret;
+}
diff --git a/services/std_svc/spmd/spmd_main.c b/services/std_svc/spmd/spmd_main.c
index 6de5feb..a9ff459 100644
--- a/services/std_svc/spmd/spmd_main.c
+++ b/services/std_svc/spmd/spmd_main.c
@@ -489,15 +489,6 @@
 		 * forward to SPM Core which will handle it if implemented.
 		 */
 
-		/*
-		 * Check if x1 holds a valid FFA fid. This is an
-		 * optimization.
-		 */
-		if (!is_ffa_fid(x1)) {
-			return spmd_ffa_error_return(handle,
-						     FFA_ERROR_NOT_SUPPORTED);
-		}
-
 		/* Forward SMC from Normal world to the SPM Core */
 		if (!secure_origin) {
 			return spmd_smc_forward(smc_fid, secure_origin,