driver: brcm: add USB driver

Signed-off-by: Bharat Gooty <bharat.gooty@broadcom.com>
Change-Id: I456aa7a641fffa8ea4e833615af3effec42a31b2
diff --git a/plat/brcm/board/stingray/driver/sr_usb.h b/plat/brcm/board/stingray/driver/sr_usb.h
new file mode 100644
index 0000000..5033683
--- /dev/null
+++ b/plat/brcm/board/stingray/driver/sr_usb.h
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2019 - 2021, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SR_USB_H
+#define SR_USB_H
+
+#define CDRU_PM_RESET_N_R	BIT(CDRU_MISC_RESET_CONTROL__CDRU_PM_RESET_N_R)
+#define CDRU_USBSS_RESET_N	BIT(CDRU_MISC_RESET_CONTROL__CDRU_USBSS_RESET_N)
+#define CDRU_MISC_CLK_USBSS \
+			BIT(CDRU_MISC_CLK_ENABLE_CONTROL__CDRU_USBSS_CLK_EN_R)
+
+#define RESCAL_I_RSTB			BIT(26)
+#define RESCAL_I_PWRDNB			BIT(27)
+
+#define DRDU3_U3PHY_CTRL		0x68500014
+#define	PHY_RESET			BIT(1)
+#define	POR_RESET			BIT(28)
+#define	MDIO_RESET			BIT(29)
+
+#define DRDU3_PWR_CTRL			0x6850002c
+#define POWER_CTRL_OVRD			BIT(2)
+
+#define USB3H_U3PHY_CTRL		0x68510014
+#define USB3H_U3SOFT_RST_N		BIT(30)
+
+#define USB3H_PWR_CTRL			0x68510028
+
+#define USB3_PHY_MDIO_BLOCK_BASE_REG	0x1f
+#define BDC_AXI_SOFT_RST_N_OFFSET	0
+#define XHC_AXI_SOFT_RST_N_OFFSET	1
+#define MDIO_BUS_ID			3
+#define USB3H_PHY_ID			5
+#define USB3DRD_PHY_ID			2
+
+#define USB3_PHY_RXPMD_BLOCK_BASE	0x8020
+#define USB3_PHY_RXPMD_REG1		0x1
+#define USB3_PHY_RXPMD_REG2		0x2
+#define USB3_PHY_RXPMD_REG5		0x5
+#define USB3_PHY_RXPMD_REG7		0x7
+
+#define USB3_PHY_TXPMD_BLOCK_BASE	0x8040
+#define USB3_PHY_TXPMD_REG1		0x1
+#define USB3_PHY_TXPMD_REG2		0x2
+
+#define USB3_PHY_ANA_BLOCK_BASE		0x8090
+#define USB3_PHY_ANA_REG0		0x0
+#define USB3_PHY_ANA_REG1		0x1
+#define USB3_PHY_ANA_REG2		0x2
+#define USB3_PHY_ANA_REG5		0x5
+#define USB3_PHY_ANA_REG8		0x8
+#define USB3_PHY_ANA_REG11		0xb
+
+#define USB3_PHY_AEQ_BLOCK_BASE		0x80e0
+#define USB3_PHY_AEQ_REG1		0x1
+#define USB3_PHY_AEQ_REG3		0x3
+
+#ifdef USB_DMA_COHERENT
+#define DRDU3_U3XHC_SOFT_RST_N		BIT(31)
+#define DRDU3_U3BDC_SOFT_RST_N		BIT(30)
+
+#define DRDU3_SOFT_RESET_CTRL		0x68500030
+#define DRDU3_XHC_AXI_SOFT_RST_N	BIT(1)
+#define DRDU3_BDC_AXI_SOFT_RST_N	BIT(0)
+
+#define DRDU2_PHY_CTRL			0x6852000c
+#define DRDU2_U2SOFT_RST_N		BIT(29)
+
+#define USB3H_SOFT_RESET_CTRL		0x6851002c
+#define USB3H_XHC_AXI_SOFT_RST_N	BIT(1)
+
+#define DRDU2_SOFT_RESET_CTRL		0x68520020
+#define DRDU2_BDC_AXI_SOFT_RST_N	BIT(0)
+
+#define DRD2U3H_XHC_REGS_AXIWRA		0x68511c08
+#define DRD2U3H_XHC_REGS_AXIRDA		0x68511c0c
+#define DRDU2D_BDC_REGS_AXIWRA		0x68521c08
+#define DRDU2D_BDC_REGS_AXIRDA		0x68521c0c
+#define DRDU3H_XHC_REGS_AXIWRA		0x68501c08
+#define DRDU3H_XHC_REGS_AXIRDA		0x68501c0c
+#define DRDU3D_BDC_REGS_AXIWRA		0x68502c08
+#define DRDU3D_BDC_REGS_AXIRDA		0x68502c0c
+/* cacheable write-back, allocate on both reads and writes */
+#define USBAXI_AWCACHE		0xf
+#define USBAXI_ARCACHE		0xf
+/* non-secure */
+#define USBAXI_AWPROT		0x8
+#define USBAXI_ARPROT		0x8
+#define USBAXIWR_SA_VAL		((USBAXI_AWCACHE << 4 | USBAXI_AWPROT) << 0)
+#define USBAXIWR_SA_MASK	((0xf << 4 | 0xf) << 0)
+#define USBAXIWR_UA_VAL		((USBAXI_AWCACHE << 4 | USBAXI_AWPROT) << 16)
+#define USBAXIWR_UA_MASK	((0xf << 4 | 0xf) << 0)
+#define USBAXIRD_SA_VAL		((USBAXI_ARCACHE << 4 | USBAXI_ARPROT) << 0)
+#define USBAXIRD_SA_MASK	((0xf << 4 | 0xf) << 0)
+#define USBAXIRD_UA_VAL		((USBAXI_ARCACHE << 4 | USBAXI_ARPROT) << 16)
+#define USBAXIRD_UA_MASK	((0xf << 4 | 0xf) << 0)
+#endif /* USB_DMA_COHERENT */
+
+#define ICFG_DRDU3_SID_CTRL		0x6850001c
+#define ICFG_USB3H_SID_CTRL		0x6851001c
+#define ICFG_DRDU2_SID_CTRL		0x68520010
+#define ICFG_USB_SID_SHIFT		5
+#define ICFG_USB_SID_AWADDR_OFFSET	0x0
+#define ICFG_USB_SID_ARADDR_OFFSET	0x4
+
+#define USBIC_GPV_BASE			0x68600000
+#define USBIC_GPV_SECURITY0		(USBIC_GPV_BASE + 0x8)
+#define USBIC_GPV_SECURITY0_FIELD	BIT(0)
+#define USBIC_GPV_SECURITY1		(USBIC_GPV_BASE + 0xc)
+#define USBIC_GPV_SECURITY1_FIELD	(BIT(0) | BIT(1))
+#define USBIC_GPV_SECURITY2		(USBIC_GPV_BASE + 0x10)
+#define USBIC_GPV_SECURITY2_FIELD	(BIT(0) | BIT(1))
+#define USBIC_GPV_SECURITY4		(USBIC_GPV_BASE + 0x18)
+#define USBIC_GPV_SECURITY4_FIELD	BIT(0)
+#define USBIC_GPV_SECURITY10		(USBIC_GPV_BASE + 0x30)
+#define USBIC_GPV_SECURITY10_FIELD	(0x7 << 0)
+
+#define USBSS_TZPCDECPROT_BASE		0x68540800
+#define USBSS_TZPCDECPROT0set		(USBSS_TZPCDECPROT_BASE + 0x4)
+#define USBSS_TZPCDECPROT0clr		(USBSS_TZPCDECPROT_BASE + 0x8)
+#define DECPROT0_USBSS_DRD2U3H		BIT(3)
+#define DECPROT0_USBSS_DRDU2H		BIT(2)
+#define DECPROT0_USBSS_DRDU3D		BIT(1)
+#define DECPROT0_USBSS_DRDU2D		BIT(0)
+#define USBSS_TZPCDECPROT0 \
+		(DECPROT0_USBSS_DRD2U3H | \
+		DECPROT0_USBSS_DRDU2H |   \
+		DECPROT0_USBSS_DRDU3D |   \
+		DECPROT0_USBSS_DRDU2D)
+
+int32_t usb_device_init(unsigned int);
+
+#endif /* SR_USB_H */
diff --git a/plat/brcm/board/stingray/driver/usb.c b/plat/brcm/board/stingray/driver/usb.c
new file mode 100644
index 0000000..4a84141
--- /dev/null
+++ b/plat/brcm/board/stingray/driver/usb.c
@@ -0,0 +1,296 @@
+/*
+ * Copyright (c) 2019 - 2021, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdint.h>
+
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+
+#include <mdio.h>
+#include <platform_usb.h>
+#include <sr_utils.h>
+#include "sr_usb.h"
+#include <usbh_xhci_regs.h>
+
+static uint32_t usb_func = USB3_DRD | USB3H_USB2DRD;
+
+static void usb_pm_rescal_init(void)
+{
+	uint32_t data;
+	uint32_t try;
+
+	mmio_setbits_32(CDRU_MISC_RESET_CONTROL, CDRU_PM_RESET_N_R);
+	/* release reset */
+	mmio_setbits_32(CDRU_CHIP_TOP_SPARE_REG0, RESCAL_I_RSTB);
+	udelay(10U);
+	/* power up */
+	mmio_setbits_32(CDRU_CHIP_TOP_SPARE_REG0,
+			RESCAL_I_RSTB | RESCAL_I_PWRDNB);
+	try = 1000U;
+	do {
+		udelay(1U);
+		data = mmio_read_32(CDRU_CHIP_TOP_SPARE_REG1);
+		try--;
+	} while ((data & RESCAL_I_PWRDNB) == 0x0U && (try != 0U));
+
+	if (try == 0U) {
+		ERROR("CDRU_CHIP_TOP_SPARE_REG1: 0x%x\n", data);
+	}
+
+	INFO("USB and PM Rescal Init done..\n");
+}
+
+const unsigned int xhc_portsc_reg_offset[MAX_USB_PORTS] = {
+	XHC_PORTSC1_OFFSET,
+	XHC_PORTSC2_OFFSET,
+	XHC_PORTSC3_OFFSET,
+};
+
+static void usb3h_usb2drd_init(void)
+{
+	uint32_t val;
+
+	INFO("USB3H + USB 2DRD init\n");
+	mmio_clrbits_32(USB3H_U3PHY_CTRL, POR_RESET);
+	val = mmio_read_32(USB3H_PWR_CTRL);
+	val &= ~(0x3U << POWER_CTRL_OVRD);
+	val |= (1U << POWER_CTRL_OVRD);
+	mmio_write_32(USB3H_PWR_CTRL, val);
+	mmio_setbits_32(USB3H_U3PHY_CTRL, PHY_RESET);
+	/* Phy to come out of reset */
+	udelay(2U);
+	mmio_clrbits_32(USB3H_U3PHY_CTRL, MDIO_RESET);
+
+	/* MDIO in reset */
+	udelay(2U);
+	mmio_setbits_32(USB3H_U3PHY_CTRL, MDIO_RESET);
+
+	/* After MDIO reset release */
+	udelay(2U);
+
+	/* USB 3.0 phy Analog Block Initialization */
+	mdio_write(MDIO_BUS_ID, USB3H_PHY_ID, USB3_PHY_MDIO_BLOCK_BASE_REG,
+			USB3_PHY_ANA_BLOCK_BASE);
+	mdio_write(MDIO_BUS_ID, USB3H_PHY_ID, USB3_PHY_ANA_REG0, 0x4646U);
+	mdio_write(MDIO_BUS_ID, USB3H_PHY_ID, USB3_PHY_ANA_REG1, 0x80c9U);
+	mdio_write(MDIO_BUS_ID, USB3H_PHY_ID, USB3_PHY_ANA_REG2, 0x88a6U);
+	mdio_write(MDIO_BUS_ID, USB3H_PHY_ID, USB3_PHY_ANA_REG5, 0x7c12U);
+	mdio_write(MDIO_BUS_ID, USB3H_PHY_ID, USB3_PHY_ANA_REG8, 0x1d07U);
+	mdio_write(MDIO_BUS_ID, USB3H_PHY_ID, USB3_PHY_ANA_REG11, 0x25cU);
+
+	/* USB 3.0 phy RXPMD Block initialization*/
+	mdio_write(MDIO_BUS_ID, USB3H_PHY_ID, USB3_PHY_MDIO_BLOCK_BASE_REG,
+			USB3_PHY_RXPMD_BLOCK_BASE);
+	mdio_write(MDIO_BUS_ID, USB3H_PHY_ID, USB3_PHY_RXPMD_REG1, 0x4052U);
+	mdio_write(MDIO_BUS_ID, USB3H_PHY_ID, USB3_PHY_RXPMD_REG2, 0x4cU);
+	mdio_write(MDIO_BUS_ID, USB3H_PHY_ID, USB3_PHY_RXPMD_REG5, 0x7U);
+	mdio_write(MDIO_BUS_ID, USB3H_PHY_ID, USB3_PHY_RXPMD_REG7, 0x173U);
+
+	/* USB 3.0 phy AEQ Block initialization*/
+	mdio_write(MDIO_BUS_ID, USB3H_PHY_ID, USB3_PHY_MDIO_BLOCK_BASE_REG,
+			USB3_PHY_AEQ_BLOCK_BASE);
+	mdio_write(MDIO_BUS_ID, USB3H_PHY_ID, USB3_PHY_AEQ_REG1, 0x3000U);
+	mdio_write(MDIO_BUS_ID, USB3H_PHY_ID, USB3_PHY_AEQ_REG3, 0x2c70U);
+
+	/* USB 3.0 phy TXPMD Block initialization*/
+	mdio_write(MDIO_BUS_ID, USB3H_PHY_ID, USB3_PHY_MDIO_BLOCK_BASE_REG,
+			USB3_PHY_TXPMD_BLOCK_BASE);
+	mdio_write(MDIO_BUS_ID, USB3H_PHY_ID, USB3_PHY_TXPMD_REG1, 0x100fU);
+	mdio_write(MDIO_BUS_ID, USB3H_PHY_ID, USB3_PHY_TXPMD_REG2, 0x238cU);
+}
+
+static void usb3drd_init(void)
+{
+	uint32_t val;
+
+	INFO("USB3DRD init\n");
+	mmio_clrbits_32(DRDU3_U3PHY_CTRL, POR_RESET);
+	val = mmio_read_32(DRDU3_PWR_CTRL);
+	val &= ~(0x3U << POWER_CTRL_OVRD);
+	val |= (1U << POWER_CTRL_OVRD);
+	mmio_write_32(DRDU3_PWR_CTRL, val);
+	mmio_setbits_32(DRDU3_U3PHY_CTRL, PHY_RESET);
+	/* Phy to come out of reset */
+	udelay(2U);
+	mmio_clrbits_32(DRDU3_U3PHY_CTRL, MDIO_RESET);
+
+	/* MDIO in reset */
+	udelay(2U);
+	mmio_setbits_32(DRDU3_U3PHY_CTRL, MDIO_RESET);
+
+	/* After MDIO reset release */
+	udelay(2U);
+
+	/* USB 3.0 DRD phy Analog Block Initialization */
+	mdio_write(MDIO_BUS_ID, USB3DRD_PHY_ID, USB3_PHY_MDIO_BLOCK_BASE_REG,
+			USB3_PHY_ANA_BLOCK_BASE);
+	mdio_write(MDIO_BUS_ID, USB3DRD_PHY_ID, USB3_PHY_ANA_REG0, 0x4646U);
+	mdio_write(MDIO_BUS_ID, USB3DRD_PHY_ID, USB3_PHY_ANA_REG1, 0x80c9U);
+	mdio_write(MDIO_BUS_ID, USB3DRD_PHY_ID, USB3_PHY_ANA_REG2, 0x88a6U);
+	mdio_write(MDIO_BUS_ID, USB3DRD_PHY_ID, USB3_PHY_ANA_REG5, 0x7c12U);
+	mdio_write(MDIO_BUS_ID, USB3DRD_PHY_ID, USB3_PHY_ANA_REG8, 0x1d07U);
+	mdio_write(MDIO_BUS_ID, USB3DRD_PHY_ID, USB3_PHY_ANA_REG11, 0x25cU);
+
+	/* USB 3.0 DRD phy RXPMD Block initialization*/
+	mdio_write(MDIO_BUS_ID, USB3DRD_PHY_ID, USB3_PHY_MDIO_BLOCK_BASE_REG,
+			USB3_PHY_RXPMD_BLOCK_BASE);
+	mdio_write(MDIO_BUS_ID, USB3DRD_PHY_ID, USB3_PHY_RXPMD_REG1, 0x4052U);
+	mdio_write(MDIO_BUS_ID, USB3DRD_PHY_ID, USB3_PHY_RXPMD_REG2, 0x4cU);
+	mdio_write(MDIO_BUS_ID, USB3DRD_PHY_ID, USB3_PHY_RXPMD_REG5, 0x7U);
+	mdio_write(MDIO_BUS_ID, USB3DRD_PHY_ID, USB3_PHY_RXPMD_REG7, 0x173U);
+
+	/* USB 3.0 DRD phy AEQ Block initialization*/
+	mdio_write(MDIO_BUS_ID, USB3DRD_PHY_ID, USB3_PHY_MDIO_BLOCK_BASE_REG,
+			USB3_PHY_AEQ_BLOCK_BASE);
+	mdio_write(MDIO_BUS_ID, USB3DRD_PHY_ID, USB3_PHY_AEQ_REG1, 0x3000U);
+	mdio_write(MDIO_BUS_ID, USB3DRD_PHY_ID, USB3_PHY_AEQ_REG3, 0x2c70U);
+
+	/* USB 3.0 DRD phy TXPMD Block initialization*/
+	mdio_write(MDIO_BUS_ID, USB3DRD_PHY_ID, USB3_PHY_MDIO_BLOCK_BASE_REG,
+			USB3_PHY_TXPMD_BLOCK_BASE);
+	mdio_write(MDIO_BUS_ID, USB3DRD_PHY_ID, USB3_PHY_TXPMD_REG1, 0x100fU);
+	mdio_write(MDIO_BUS_ID, USB3DRD_PHY_ID, USB3_PHY_TXPMD_REG2, 0x238cU);
+}
+
+static void usb3_phy_init(void)
+{
+	usb_pm_rescal_init();
+
+	if ((usb_func & USB3H_USB2DRD) != 0U) {
+		usb3h_usb2drd_init();
+	}
+
+	if ((usb_func & USB3_DRD) != 0U) {
+		usb3drd_init();
+	}
+}
+
+#ifdef USB_DMA_COHERENT
+void usb_enable_coherence(void)
+{
+	if (usb_func & USB3H_USB2DRD) {
+		mmio_setbits_32(USB3H_SOFT_RESET_CTRL,
+				USB3H_XHC_AXI_SOFT_RST_N);
+		mmio_setbits_32(DRDU2_SOFT_RESET_CTRL,
+				DRDU2_BDC_AXI_SOFT_RST_N);
+		mmio_setbits_32(USB3H_U3PHY_CTRL, USB3H_U3SOFT_RST_N);
+		mmio_setbits_32(DRDU2_PHY_CTRL, DRDU2_U2SOFT_RST_N);
+
+		mmio_clrsetbits_32(DRD2U3H_XHC_REGS_AXIWRA,
+				   (USBAXIWR_UA_MASK | USBAXIWR_SA_MASK),
+				   (USBAXIWR_UA_VAL | USBAXIWR_SA_VAL));
+
+		mmio_clrsetbits_32(DRD2U3H_XHC_REGS_AXIRDA,
+				   (USBAXIRD_UA_MASK | USBAXIRD_SA_MASK),
+				   (USBAXIRD_UA_VAL | USBAXIRD_SA_VAL));
+
+		mmio_clrsetbits_32(DRDU2D_BDC_REGS_AXIWRA,
+				   (USBAXIWR_UA_MASK | USBAXIWR_SA_MASK),
+				   (USBAXIWR_UA_VAL | USBAXIWR_SA_VAL));
+
+		mmio_clrsetbits_32(DRDU2D_BDC_REGS_AXIRDA,
+				   (USBAXIRD_UA_MASK | USBAXIRD_SA_MASK),
+				   (USBAXIRD_UA_VAL | USBAXIRD_SA_VAL));
+
+	}
+
+	if (usb_func & USB3_DRD) {
+		mmio_setbits_32(DRDU3_SOFT_RESET_CTRL,
+				(DRDU3_XHC_AXI_SOFT_RST_N |
+				DRDU3_BDC_AXI_SOFT_RST_N));
+		mmio_setbits_32(DRDU3_U3PHY_CTRL,
+				(DRDU3_U3XHC_SOFT_RST_N |
+				DRDU3_U3BDC_SOFT_RST_N));
+
+		mmio_clrsetbits_32(DRDU3H_XHC_REGS_AXIWRA,
+				   (USBAXIWR_UA_MASK | USBAXIWR_SA_MASK),
+				   (USBAXIWR_UA_VAL | USBAXIWR_SA_VAL));
+
+		mmio_clrsetbits_32(DRDU3H_XHC_REGS_AXIRDA,
+				   (USBAXIRD_UA_MASK | USBAXIRD_SA_MASK),
+				   (USBAXIRD_UA_VAL | USBAXIRD_SA_VAL));
+
+		mmio_clrsetbits_32(DRDU3D_BDC_REGS_AXIWRA,
+				   (USBAXIWR_UA_MASK | USBAXIWR_SA_MASK),
+				   (USBAXIWR_UA_VAL | USBAXIWR_SA_VAL));
+
+		mmio_clrsetbits_32(DRDU3D_BDC_REGS_AXIRDA,
+				   (USBAXIRD_UA_MASK | USBAXIRD_SA_MASK),
+				   (USBAXIRD_UA_VAL | USBAXIRD_SA_VAL));
+	}
+}
+#endif
+
+void xhci_phy_init(void)
+{
+	uint32_t val;
+
+	INFO("usb init start\n");
+	mmio_setbits_32(CDRU_MISC_CLK_ENABLE_CONTROL,
+			CDRU_MISC_CLK_USBSS);
+
+	mmio_setbits_32(CDRU_MISC_RESET_CONTROL, CDRU_USBSS_RESET_N);
+
+	if (usb_func & USB3_DRD) {
+		VERBOSE(" - configure stream_id = 0x6800 for DRDU3\n");
+		val = SR_SID_VAL(0x3U, 0x1U, 0x0U) << ICFG_USB_SID_SHIFT;
+		mmio_write_32(ICFG_DRDU3_SID_CTRL + ICFG_USB_SID_AWADDR_OFFSET,
+				val);
+		mmio_write_32(ICFG_DRDU3_SID_CTRL + ICFG_USB_SID_ARADDR_OFFSET,
+				val);
+
+		/*
+		 * DRDU3 Device USB Space, DRDU3 Host USB Space,
+		 * DRDU3 SS Config
+		 */
+		mmio_setbits_32(USBIC_GPV_SECURITY10,
+				USBIC_GPV_SECURITY10_FIELD);
+	}
+
+	if (usb_func & USB3H_USB2DRD) {
+		VERBOSE(" - configure stream_id = 0x6801 for USB3H\n");
+		val = SR_SID_VAL(0x3U, 0x1U, 0x1U) << ICFG_USB_SID_SHIFT;
+		mmio_write_32(ICFG_USB3H_SID_CTRL + ICFG_USB_SID_AWADDR_OFFSET,
+				val);
+		mmio_write_32(ICFG_USB3H_SID_CTRL + ICFG_USB_SID_ARADDR_OFFSET,
+				val);
+
+		VERBOSE(" - configure stream_id = 0x6802 for DRDU2\n");
+		val = SR_SID_VAL(0x3U, 0x1U, 0x2U) << ICFG_USB_SID_SHIFT;
+		mmio_write_32(ICFG_DRDU2_SID_CTRL + ICFG_USB_SID_AWADDR_OFFSET,
+				val);
+		mmio_write_32(ICFG_DRDU2_SID_CTRL + ICFG_USB_SID_ARADDR_OFFSET,
+				val);
+
+		/* DRDU2 APB Bridge:DRDU2 USB Device, USB3H SS Config */
+		mmio_setbits_32(USBIC_GPV_SECURITY1, USBIC_GPV_SECURITY1_FIELD);
+
+		/*
+		 * USB3H APB Bridge:DRDU2 Host + USB3 Host USB Space,
+		 * USB3H SS Config
+		 */
+		mmio_setbits_32(USBIC_GPV_SECURITY2, USBIC_GPV_SECURITY2_FIELD);
+	}
+
+	/* Configure Host masters as non-Secure */
+	mmio_setbits_32(USBSS_TZPCDECPROT0set, USBSS_TZPCDECPROT0);
+
+	/* CCN Slave on USBIC */
+	mmio_setbits_32(USBIC_GPV_SECURITY0, USBIC_GPV_SECURITY0_FIELD);
+
+	/* SLAVE_8:IDM Register Space */
+	mmio_setbits_32(USBIC_GPV_SECURITY4, USBIC_GPV_SECURITY4_FIELD);
+
+	usb3_phy_init();
+#ifdef USB_DMA_COHERENT
+	usb_enable_coherence();
+#endif
+
+	usb_device_init(usb_func);
+
+	INFO("PLAT USB: init done.\n");
+}
diff --git a/plat/brcm/board/stingray/driver/usb_phy.c b/plat/brcm/board/stingray/driver/usb_phy.c
new file mode 100644
index 0000000..54c98e1
--- /dev/null
+++ b/plat/brcm/board/stingray/driver/usb_phy.c
@@ -0,0 +1,601 @@
+/*
+ * Copyright (c) 2019 - 2021, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_usb.h>
+#include <usb_phy.h>
+
+#define USB_PHY_ALREADY_STARTED	(-2)
+#define USB_MAX_DEVICES		 2
+#define USB3H_USB2DRD_PHY	 0
+#define USB3_DRD_PHY		 1
+
+/* Common bit fields for all the USB2 phy */
+#define USB2_PHY_ISO		DRDU2_U2PHY_ISO
+#define USB2_AFE_PLL_PWRDWNB	DRDU2_U2AFE_PLL_PWRDWNB
+#define USB2_AFE_BG_PWRDWNB	DRDU2_U2AFE_BG_PWRDWNB
+#define USB2_AFE_LDO_PWRDWNB	DRDU2_U2AFE_LDO_PWRDWNB
+#define USB2_CTRL_CORERDY	DRDU2_U2CTRL_CORERDY
+
+#define USB2_PHY_PCTL_MASK	DRDU2_U2PHY_PCTL_MASK
+#define USB2_PHY_PCTL_OFFSET	DRDU2_U2PHY_PCTL_OFFSET
+#define USB2_PHY_PCTL_VAL	U2PHY_PCTL_VAL
+
+#define USB2_PLL_RESETB		DRDU2_U2PLL_RESETB
+#define USB2_PHY_RESETB		DRDU2_U2PHY_RESETB
+
+static usb_phy_port_t usb_phy_port[2U][MAX_NR_PORTS];
+
+static usb_phy_t usb_phy_info[2U] = {
+	{DRDU2_U2PLL_NDIV_FRAC, USB3H_PIPE_CTRL, 0U, USB3H_DRDU2_PHY},
+	{0U, 0U, DRDU3_PIPE_CTRL, DRDU3_PHY}
+};
+
+typedef struct {
+	void *pcd_id;
+} usb_platform_dev;
+
+/* index 0: USB3H + USB2 DRD, 1: USB3 DRD */
+static usb_platform_dev xhci_devices_configs[USB_MAX_DEVICES] = {
+	{&usb_phy_info[0U]},
+	{&usb_phy_info[1U]}
+};
+
+static int32_t pll_lock_check(uint32_t address, uint32_t bit)
+{
+	uint32_t retry;
+	uint32_t data;
+
+	retry = PLL_LOCK_RETRY_COUNT;
+	do {
+		data = mmio_read_32(address);
+		if ((data & bit) != 0U) {
+			return 0;
+		}
+		udelay(1);
+	} while (--retry != 0);
+
+	ERROR("%s(): FAIL (0x%08x)\n", __func__, address);
+	return -1;
+}
+
+/*
+ * USB2 PHY using external FSM bringup sequence
+ * Total #3 USB2 phys. All phys has the same
+ * bringup sequence. Register bit fields for
+ * some of the PHY's are different.
+ * Bit fields which are different are passed using
+ * struct u2_phy_ext_fsm with bit-fields and register addr.
+ */
+
+static void u2_phy_ext_fsm_power_on(struct u2_phy_ext_fsm *u2_phy)
+{
+	mmio_setbits_32(u2_phy->phy_ctrl_reg, USB2_PHY_ISO);
+	/* Delay as per external FSM spec */
+	udelay(10U);
+
+	mmio_setbits_32(u2_phy->phy_ctrl_reg, u2_phy->phy_iddq);
+	/* Delay as per external FSM spec */
+	udelay(10U);
+
+	mmio_clrbits_32(u2_phy->phy_ctrl_reg,
+			(USB2_AFE_BG_PWRDWNB |
+			 USB2_AFE_PLL_PWRDWNB |
+			 USB2_AFE_LDO_PWRDWNB |
+			 USB2_CTRL_CORERDY));
+
+	mmio_clrsetbits_32(u2_phy->phy_ctrl_reg,
+			   (USB2_PHY_PCTL_MASK << USB2_PHY_PCTL_OFFSET),
+			   (USB2_PHY_PCTL_VAL << USB2_PHY_PCTL_OFFSET));
+	/* Delay as per external FSM spec */
+	udelay(160U);
+
+	mmio_setbits_32(u2_phy->phy_ctrl_reg, USB2_CTRL_CORERDY);
+	/* Delay as per external FSM spec */
+	udelay(50U);
+
+	mmio_setbits_32(u2_phy->phy_ctrl_reg, USB2_AFE_BG_PWRDWNB);
+	/* Delay as per external FSM spec */
+	udelay(200U);
+
+	mmio_setbits_32(u2_phy->pwr_ctrl_reg, u2_phy->pwr_onin);
+	mmio_setbits_32(u2_phy->phy_ctrl_reg, USB2_AFE_LDO_PWRDWNB);
+	/* Delay as per external FSM spec */
+	udelay(10U);
+
+	mmio_setbits_32(u2_phy->pwr_ctrl_reg, u2_phy->pwr_okin);
+	/* Delay as per external FSM spec */
+	udelay(10U);
+
+	mmio_setbits_32(u2_phy->phy_ctrl_reg, USB2_AFE_PLL_PWRDWNB);
+	/* Delay as per external FSM spec */
+	udelay(10U);
+
+	mmio_clrbits_32(u2_phy->phy_ctrl_reg, USB2_PHY_ISO);
+	/* Delay as per external FSM spec */
+	udelay(10U);
+	mmio_clrbits_32(u2_phy->phy_ctrl_reg, u2_phy->phy_iddq);
+	/* Delay as per external FSM spec */
+	udelay(1U);
+
+	mmio_setbits_32(u2_phy->pll_ctrl_reg, USB2_PLL_RESETB);
+	mmio_setbits_32(u2_phy->phy_ctrl_reg, USB2_PHY_RESETB);
+
+}
+
+static int32_t usb3h_u2_phy_power_on(uint32_t base)
+{
+	int32_t status;
+	struct u2_phy_ext_fsm u2_phy;
+
+	u2_phy.pll_ctrl_reg = base + USB3H_U2PLL_CTRL;
+	u2_phy.phy_ctrl_reg = base + USB3H_U2PHY_CTRL;
+	u2_phy.phy_iddq = USB3H_U2PHY_IDDQ;
+	u2_phy.pwr_ctrl_reg = base + USB3H_PWR_CTRL;
+	u2_phy.pwr_okin = USB3H_PWR_CTRL_U2PHY_DFE_SWITCH_PWROKIN;
+	u2_phy.pwr_onin = USB3H_PWR_CTRL_U2PHY_DFE_SWITCH_PWRONIN;
+
+	u2_phy_ext_fsm_power_on(&u2_phy);
+
+	status = pll_lock_check(base + USB3H_U2PLL_CTRL, USB3H_U2PLL_LOCK);
+	if (status != 0) {
+		/* re-try by toggling the PLL reset */
+		mmio_clrbits_32(base + USB3H_U2PLL_CTRL,
+				(uint32_t)USB3H_U2PLL_RESETB);
+		mmio_setbits_32(base + USB3H_U2PLL_CTRL, USB3H_U2PLL_RESETB);
+		status = pll_lock_check(base + USB3H_U2PLL_CTRL,
+					USB3H_U2PLL_LOCK);
+		if (status != 0)
+			ERROR("%s() re-try PLL lock FAIL (0x%08x)\n", __func__,
+			      base + USB3H_U2PLL_CTRL);
+	}
+
+	mmio_clrsetbits_32(base + USB3H_U2PHY_CTRL,
+			   (USB3H_U2PHY_PCTL_MASK << USB3H_U2PHY_PCTL_OFFSET),
+			   (U2PHY_PCTL_NON_DRV_LOW << USB3H_U2PHY_PCTL_OFFSET));
+	return status;
+}
+
+static int32_t usb3h_u3_phy_power_on(uint32_t base)
+{
+	int32_t status;
+
+	/* Set pctl with mode and soft reset */
+	mmio_clrsetbits_32(base + USB3H_U3PHY_CTRL,
+			   (USB3H_U3PHY_PCTL_MASK << USB3H_U3PHY_PCTL_OFFSET),
+			   (U3PHY_PCTL_VAL << USB3H_U3PHY_PCTL_OFFSET));
+
+	mmio_clrbits_32(base + USB3H_U3PHY_PLL_CTRL,
+			(uint32_t) USB3H_U3SSPLL_SUSPEND_EN);
+	mmio_setbits_32(base + USB3H_U3PHY_PLL_CTRL, USB3H_U3PLL_SEQ_START);
+	mmio_setbits_32(base + USB3H_U3PHY_PLL_CTRL, USB3H_U3PLL_RESETB);
+
+	/* Time to stabilize the PLL Control */
+	mdelay(1U);
+
+	status = pll_lock_check(base + USB3H_U3PHY_PLL_CTRL,
+				USB3H_U3PLL_SS_LOCK);
+
+	return status;
+}
+
+static int32_t drdu3_u2_phy_power_on(uint32_t base)
+{
+	int32_t status;
+	struct u2_phy_ext_fsm u2_phy;
+
+	u2_phy.pll_ctrl_reg = base + DRDU3_U2PLL_CTRL;
+	u2_phy.phy_ctrl_reg = base + DRDU3_U2PHY_CTRL;
+	u2_phy.phy_iddq = DRDU3_U2PHY_IDDQ;
+	u2_phy.pwr_ctrl_reg = base + DRDU3_PWR_CTRL;
+	u2_phy.pwr_okin = DRDU3_U2PHY_DFE_SWITCH_PWROKIN;
+	u2_phy.pwr_onin = DRDU3_U2PHY_DFE_SWITCH_PWRONIN;
+
+	u2_phy_ext_fsm_power_on(&u2_phy);
+
+	status = pll_lock_check(base + DRDU3_U2PLL_CTRL, DRDU3_U2PLL_LOCK);
+	if (status != 0) {
+		/* re-try by toggling the PLL reset */
+		mmio_clrbits_32(base + DRDU3_U2PLL_CTRL,
+				(uint32_t)DRDU2_U2PLL_RESETB);
+		mmio_setbits_32(base + DRDU3_U2PLL_CTRL, DRDU3_U2PLL_RESETB);
+
+		status = pll_lock_check(base + DRDU3_U2PLL_CTRL,
+					DRDU3_U2PLL_LOCK);
+		if (status != 0) {
+			ERROR("%s() re-try PLL lock FAIL (0x%08x)\n", __func__,
+			      base + DRDU3_U2PLL_CTRL);
+		}
+	}
+	mmio_clrsetbits_32(base + DRDU3_U2PHY_CTRL,
+			   (DRDU3_U2PHY_PCTL_MASK << DRDU3_U2PHY_PCTL_OFFSET),
+			   (U2PHY_PCTL_NON_DRV_LOW << DRDU3_U2PHY_PCTL_OFFSET));
+
+	return status;
+}
+
+static int32_t drdu3_u3_phy_power_on(uint32_t base)
+{
+	int32_t status;
+
+	/* Set pctl with mode and soft reset */
+	mmio_clrsetbits_32(base + DRDU3_U3PHY_CTRL,
+			   (DRDU3_U3PHY_PCTL_MASK << DRDU3_U3PHY_PCTL_OFFSET),
+			   (U3PHY_PCTL_VAL << DRDU3_U3PHY_PCTL_OFFSET));
+
+	mmio_clrbits_32(base + DRDU3_U3PHY_PLL_CTRL,
+			(uint32_t) DRDU3_U3SSPLL_SUSPEND_EN);
+	mmio_setbits_32(base + DRDU3_U3PHY_PLL_CTRL, DRDU3_U3PLL_SEQ_START);
+	mmio_setbits_32(base + DRDU3_U3PHY_PLL_CTRL, DRDU3_U3PLL_RESETB);
+
+	/* Time to stabilize the PLL Control */
+	mdelay(1U);
+
+	status = pll_lock_check(base + DRDU3_U3PHY_PLL_CTRL,
+				DRDU3_U3PLL_SS_LOCK);
+
+	return status;
+}
+
+static int32_t drdu2_u2_phy_power_on(uint32_t base)
+{
+	int32_t status;
+	struct u2_phy_ext_fsm u2_phy;
+
+	u2_phy.pll_ctrl_reg = base + DRDU2_U2PLL_CTRL;
+	u2_phy.phy_ctrl_reg = base + DRDU2_PHY_CTRL;
+	u2_phy.phy_iddq = DRDU2_U2IDDQ;
+	u2_phy.pwr_ctrl_reg = base + DRDU2_PWR_CTRL;
+	u2_phy.pwr_okin = DRDU2_U2PHY_DFE_SWITCH_PWROKIN_I;
+	u2_phy.pwr_onin = DRDU2_U2PHY_DFE_SWITCH_PWRONIN_I;
+
+	u2_phy_ext_fsm_power_on(&u2_phy);
+
+	status = pll_lock_check(base + DRDU2_U2PLL_CTRL, DRDU2_U2PLL_LOCK);
+	if (status != 0) {
+		/* re-try by toggling the PLL reset */
+		mmio_clrbits_32(base + DRDU2_U2PLL_CTRL,
+				(uint32_t)DRDU2_U2PLL_RESETB);
+		mmio_setbits_32(base + DRDU2_U2PLL_CTRL, DRDU2_U2PLL_RESETB);
+
+		status = pll_lock_check(base + DRDU2_U2PLL_CTRL,
+					DRDU2_U2PLL_LOCK);
+		if (status != 0)
+			ERROR("%s() re-try PLL lock FAIL (0x%08x)\n", __func__,
+			      base + DRDU2_U2PLL_CTRL);
+	}
+	mmio_clrsetbits_32(base + DRDU2_PHY_CTRL,
+			   (DRDU2_U2PHY_PCTL_MASK << DRDU2_U2PHY_PCTL_OFFSET),
+			   (U2PHY_PCTL_NON_DRV_LOW << DRDU2_U2PHY_PCTL_OFFSET));
+
+	return status;
+}
+
+void u3h_u2drd_phy_reset(usb_phy_port_t *phy_port)
+{
+	usb_phy_t *phy = phy_port->p;
+
+	switch (phy_port->port_id) {
+	case USB3HS_PORT:
+		mmio_clrbits_32(phy->usb3hreg + USB3H_U2PHY_CTRL,
+				(uint32_t) USB3H_U2CTRL_CORERDY);
+		mmio_setbits_32(phy->usb3hreg + USB3H_U2PHY_CTRL,
+				USB3H_U2CTRL_CORERDY);
+		break;
+	case DRDU2_PORT:
+		mmio_clrbits_32(phy->drdu2reg + DRDU2_PHY_CTRL,
+				(uint32_t) DRDU2_U2CTRL_CORERDY);
+		mmio_setbits_32(phy->drdu2reg + DRDU2_PHY_CTRL,
+				DRDU2_U2CTRL_CORERDY);
+		break;
+	}
+}
+
+void u3drd_phy_reset(usb_phy_port_t *phy_port)
+{
+	usb_phy_t *phy = phy_port->p;
+
+	if (phy_port->port_id == DRD3HS_PORT) {
+		mmio_clrbits_32(phy->drdu3reg + DRDU3_U2PHY_CTRL,
+				(uint32_t) DRDU3_U2CTRL_CORERDY);
+		mmio_setbits_32(phy->drdu3reg + DRDU3_U2PHY_CTRL,
+				DRDU3_U2CTRL_CORERDY);
+	}
+}
+
+static int32_t u3h_u2drd_phy_power_on(usb_phy_port_t *phy_port)
+{
+	usb_phy_t *phy = phy_port->p;
+	int32_t status;
+
+	switch (phy_port->port_id) {
+	case USB3SS_PORT:
+		mmio_clrbits_32(phy->usb3hreg + USB3H_PHY_PWR_CTRL,
+				(uint32_t) USB3H_DISABLE_USB30_P0);
+		status = usb3h_u3_phy_power_on(phy->usb3hreg);
+		if (status != 0) {
+			goto err_usb3h_phy_on;
+		}
+		break;
+	case USB3HS_PORT:
+		mmio_clrbits_32(phy->usb3hreg + USB3H_PHY_PWR_CTRL,
+				(uint32_t) USB3H_DISABLE_EUSB_P1);
+		mmio_setbits_32(AXI_DEBUG_CTRL,
+				AXI_DBG_CTRL_SSPHY_DRD_MODE_DISABLE);
+		mmio_setbits_32(USB3H_DEBUG_CTRL,
+				USB3H_DBG_CTRL_SSPHY_DRD_MODE_DISABLE);
+
+		mmio_clrbits_32(phy->usb3hreg + USB3H_PWR_CTRL,
+				USB3H_PWR_CTRL_U2PHY_DFE_SWITCH_PWRONIN);
+		/* Delay as per external FSM spec */
+		udelay(10U);
+		mmio_clrbits_32(phy->usb3hreg + USB3H_PWR_CTRL,
+				USB3H_PWR_CTRL_U2PHY_DFE_SWITCH_PWROKIN);
+		status = usb3h_u2_phy_power_on(phy->usb3hreg);
+		if (status != 0) {
+			goto err_usb3h_phy_on;
+		}
+		break;
+	case DRDU2_PORT:
+		mmio_clrbits_32(phy->usb3hreg + USB3H_PHY_PWR_CTRL,
+				(uint32_t) USB3H_DISABLE_EUSB_P0);
+		mmio_setbits_32(AXI_DEBUG_CTRL,
+				AXI_DBG_CTRL_SSPHY_DRD_MODE_DISABLE);
+		mmio_setbits_32(USB3H_DEBUG_CTRL,
+				USB3H_DBG_CTRL_SSPHY_DRD_MODE_DISABLE);
+
+		mmio_clrbits_32(phy->usb3hreg + DRDU2_PWR_CTRL,
+				DRDU2_U2PHY_DFE_SWITCH_PWRONIN_I);
+		/* Delay as per external FSM spec */
+		udelay(10U);
+		mmio_clrbits_32(phy->usb3hreg + DRDU2_PWR_CTRL,
+				DRDU2_U2PHY_DFE_SWITCH_PWROKIN_I);
+
+		status = drdu2_u2_phy_power_on(phy->drdu2reg);
+		if (status != 0) {
+			mmio_setbits_32(phy->usb3hreg + USB3H_PHY_PWR_CTRL,
+					USB3H_DISABLE_EUSB_P0);
+			goto err_drdu2_phy_on;
+		}
+		break;
+	}
+
+	/* Device Mode */
+	if (phy_port->port_id == DRDU2_PORT) {
+		mmio_write_32(phy->drdu2reg + DRDU2_SOFT_RESET_CTRL,
+			      DRDU2_BDC_AXI_SOFT_RST_N);
+		mmio_setbits_32(phy->drdu2reg + DRDU2_PHY_CTRL,
+				DRDU2_U2SOFT_RST_N);
+	}
+	/* Host Mode */
+	mmio_write_32(phy->usb3hreg + USB3H_SOFT_RESET_CTRL,
+		      USB3H_XHC_AXI_SOFT_RST_N);
+	mmio_setbits_32(phy->usb3hreg + USB3H_U3PHY_CTRL, USB3H_U3SOFT_RST_N);
+
+	return 0U;
+ err_usb3h_phy_on:mmio_setbits_32(phy->usb3hreg + USB3H_PHY_PWR_CTRL,
+			(USB3H_DISABLE_EUSB_P1 |
+			 USB3H_DISABLE_USB30_P0));
+ err_drdu2_phy_on:
+
+	return status;
+}
+
+static int32_t u3drd_phy_power_on(usb_phy_port_t *phy_port)
+{
+	usb_phy_t *phy = phy_port->p;
+	int32_t status;
+
+	switch (phy_port->port_id) {
+	case DRD3SS_PORT:
+		mmio_clrbits_32(phy->drdu3reg + DRDU3_PHY_PWR_CTRL,
+				(uint32_t) DRDU3_DISABLE_USB30_P0);
+
+		status = drdu3_u3_phy_power_on(phy->drdu3reg);
+		if (status != 0) {
+			goto err_drdu3_phy_on;
+		}
+		break;
+	case DRD3HS_PORT:
+		mmio_clrbits_32(phy->drdu3reg + DRDU3_PHY_PWR_CTRL,
+				(uint32_t) DRDU3_DISABLE_EUSB_P0);
+		mmio_setbits_32(AXI_DEBUG_CTRL,
+				AXI_DBG_CTRL_SSPHY_DRD_MODE_DISABLE);
+		mmio_setbits_32(USB3H_DEBUG_CTRL,
+				USB3H_DBG_CTRL_SSPHY_DRD_MODE_DISABLE);
+
+		mmio_clrbits_32(phy->drdu3reg + DRDU3_PWR_CTRL,
+				DRDU3_U2PHY_DFE_SWITCH_PWRONIN);
+		/* Delay as per external FSM spec */
+		udelay(10U);
+		mmio_clrbits_32(phy->drdu3reg + DRDU3_PWR_CTRL,
+				DRDU3_U2PHY_DFE_SWITCH_PWROKIN);
+
+		status = drdu3_u2_phy_power_on(phy->drdu3reg);
+		if (status != 0) {
+			goto err_drdu3_phy_on;
+		}
+
+		/* Host Mode */
+		mmio_setbits_32(phy->drdu3reg + DRDU3_SOFT_RESET_CTRL,
+				DRDU3_XHC_AXI_SOFT_RST_N);
+		mmio_setbits_32(phy->drdu3reg + DRDU3_U3PHY_CTRL,
+				DRDU3_U3XHC_SOFT_RST_N);
+		/* Device Mode */
+		mmio_setbits_32(phy->drdu3reg + DRDU3_SOFT_RESET_CTRL,
+				DRDU3_BDC_AXI_SOFT_RST_N);
+		mmio_setbits_32(phy->drdu3reg + DRDU3_U3PHY_CTRL,
+				DRDU3_U3BDC_SOFT_RST_N);
+		break;
+	}
+
+	return 0U;
+ err_drdu3_phy_on:mmio_setbits_32(phy->drdu3reg + DRDU3_PHY_PWR_CTRL,
+			(DRDU3_DISABLE_EUSB_P0 |
+			 DRDU3_DISABLE_USB30_P0));
+
+	return status;
+}
+
+static void u3h_u2drd_phy_power_off(usb_phy_port_t *phy_port)
+{
+	usb_phy_t *p = phy_port->p;
+
+	switch (phy_port->port_id) {
+	case USB3SS_PORT:
+		mmio_setbits_32(p->usb3hreg + USB3H_PHY_PWR_CTRL,
+				USB3H_DISABLE_USB30_P0);
+		break;
+	case USB3HS_PORT:
+		mmio_setbits_32(p->usb3hreg + USB3H_PHY_PWR_CTRL,
+				USB3H_DISABLE_EUSB_P1);
+		break;
+	case DRDU2_PORT:
+		mmio_setbits_32(p->usb3hreg + USB3H_PHY_PWR_CTRL,
+				USB3H_DISABLE_EUSB_P0);
+		break;
+	}
+}
+
+static void u3drd_phy_power_off(usb_phy_port_t *phy_port)
+{
+	usb_phy_t *p = phy_port->p;
+
+	switch (phy_port->port_id) {
+	case DRD3SS_PORT:
+		mmio_setbits_32(p->drdu3reg + DRDU3_PHY_PWR_CTRL,
+				DRDU3_DISABLE_USB30_P0);
+		break;
+	case DRD3HS_PORT:
+		mmio_setbits_32(p->drdu3reg + DRDU3_PHY_PWR_CTRL,
+				DRDU3_DISABLE_EUSB_P0);
+		break;
+	}
+}
+
+int32_t usb_info_fill(usb_phy_t *phy_info)
+{
+	int32_t index;
+
+	if (phy_info->initialized != 0U) {
+		return USB_PHY_ALREADY_STARTED;
+	}
+
+	if (phy_info->phy_id == USB3H_DRDU2_PHY) {
+		phy_info->phy_port = usb_phy_port[USB3H_DRDU2_PHY - 1U];
+		phy_info->ports_enabled = 0x7U;
+	} else {
+		phy_info->phy_port = usb_phy_port[DRDU3_PHY - 1U];
+		phy_info->ports_enabled = 0x3U;
+	}
+
+	for (index = MAX_NR_PORTS - 1U; index > -1; index--) {
+		phy_info->phy_port[index].enabled = (phy_info->ports_enabled
+						     >> index) & 0x1U;
+		phy_info->phy_port[index].p = phy_info;
+		phy_info->phy_port[index].port_id = index;
+	}
+
+	return 0U;
+}
+
+int32_t usb_phy_init(usb_platform_dev *device)
+{
+	int32_t status;
+	usb_phy_t *phy_info;
+	uint32_t index;
+
+	phy_info = (usb_phy_t *)device->pcd_id;
+
+	status = usb_info_fill(phy_info);
+	if (status != 0) {
+		return (status == USB_PHY_ALREADY_STARTED) ? 0 : status;
+	}
+
+	for (index = 0U; index < MAX_NR_PORTS; index++) {
+		if (phy_info->phy_port[index].enabled != 0U) {
+			switch (phy_info->phy_id) {
+			case USB3H_DRDU2_PHY:
+				status =
+				    u3h_u2drd_phy_power_on(&phy_info->
+							   phy_port[index]);
+				break;
+			default:
+				status =
+				    u3drd_phy_power_on(&phy_info->
+						       phy_port[index]);
+			}
+		}
+	}
+
+	phy_info->initialized = !status;
+	return status;
+}
+
+void usb_phy_shutdown(usb_platform_dev *device)
+{
+	usb_phy_t *phy_info;
+	uint32_t index;
+
+	phy_info = (usb_phy_t *)device->pcd_id;
+
+	phy_info->initialized = 0U;
+
+	for (index = 0U; index < MAX_NR_PORTS; index++) {
+		if (phy_info->phy_port[index].enabled != 0U) {
+			switch (phy_info->phy_id) {
+			case USB3H_DRDU2_PHY:
+				u3h_u2drd_phy_power_off(&phy_info->
+							phy_port[index]);
+				break;
+			case DRDU3_PHY:
+				u3drd_phy_power_off(&phy_info->phy_port[index]);
+				break;
+			default:
+				INFO("%s: invalid phy id 0x%x\n", __func__,
+				     phy_info->phy_id);
+			}
+		}
+	}
+}
+
+int32_t usb_xhci_init(usb_platform_dev *device)
+{
+	int32_t status;
+
+	status = usb_phy_init(device);
+	if (status == USB_PHY_ALREADY_STARTED) {
+		status = 0U;
+	}
+
+	return status;
+}
+
+int32_t usb_device_init(unsigned int usb_func)
+{
+	int32_t status;
+	int32_t devices_initialized = 0U;
+
+	if ((usb_func & USB3H_USB2DRD) != 0U) {
+		status = usb_xhci_init(
+				&xhci_devices_configs[USB3H_USB2DRD_PHY]);
+		if (status == 0) {
+			devices_initialized++;
+		} else {
+			ERROR("%s(): USB3H_USB2DRD init failure\n", __func__);
+		}
+	}
+
+	if ((usb_func & USB3_DRD) != 0U) {
+		status = usb_xhci_init(&xhci_devices_configs[USB3_DRD_PHY]);
+		if (status == 0) {
+			devices_initialized++;
+		} else {
+			ERROR("%s(): USB3_DRD init failure\n", __func__);
+		}
+	}
+
+	return devices_initialized;
+}
diff --git a/plat/brcm/board/stingray/include/platform_usb.h b/plat/brcm/board/stingray/include/platform_usb.h
new file mode 100644
index 0000000..5b5309f
--- /dev/null
+++ b/plat/brcm/board/stingray/include/platform_usb.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2019 - 2021, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_USB_H
+#define PLATFORM_USB_H
+
+#include <platform_def.h>
+
+#define USB3_DRD		BIT(0U)
+#define USB3H_USB2DRD		BIT(1U)
+
+extern const unsigned int xhc_portsc_reg_offset[MAX_USB_PORTS];
+
+void xhci_phy_init(void);
+
+#endif /* PLATFORM_USB_H */
diff --git a/plat/brcm/board/stingray/include/usb_phy.h b/plat/brcm/board/stingray/include/usb_phy.h
new file mode 100644
index 0000000..7d83182
--- /dev/null
+++ b/plat/brcm/board/stingray/include/usb_phy.h
@@ -0,0 +1,244 @@
+/*
+ * Copyright (c) 2017 - 2021, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef USB_PHY_H
+#define USB_PHY_H
+
+#include <stdint.h>
+
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+
+#include <platform_def.h>
+
+#define DRDU2_U2PLL_NDIV_FRAC_OFFSET            0x0U
+
+#define DRDU2_U2PLL_NDIV_INT                    0x4U
+
+#define DRDU2_U2PLL_CTRL                        0x8U
+#define DRDU2_U2PLL_LOCK                        BIT(6U)
+#define DRDU2_U2PLL_RESETB                      BIT(5U)
+#define DRDU2_U2PLL_PDIV_MASK                   0xFU
+#define DRDU2_U2PLL_PDIV_OFFSET                 1U
+#define DRDU2_U2PLL_SUSPEND_EN                  BIT(0U)
+
+#define DRDU2_PHY_CTRL                          0x0CU
+#define DRDU2_U2IDDQ                            BIT(30U)
+#define DRDU2_U2SOFT_RST_N                      BIT(29U)
+#define DRDU2_U2PHY_ON_FLAG                     BIT(22U)
+#define DRDU2_U2PHY_PCTL_MASK                   0xFFFFU
+#define DRDU2_U2PHY_PCTL_OFFSET                 6U
+#define DRDU2_U2PHY_RESETB                      BIT(5U)
+#define DRDU2_U2PHY_ISO                         BIT(4U)
+#define DRDU2_U2AFE_BG_PWRDWNB                  BIT(3U)
+#define DRDU2_U2AFE_PLL_PWRDWNB                 BIT(2U)
+#define DRDU2_U2AFE_LDO_PWRDWNB                 BIT(1U)
+#define DRDU2_U2CTRL_CORERDY                    BIT(0U)
+
+#define DRDU2_STRAP_CTRL                        0x18U
+#define DRDU2_FORCE_HOST_MODE                   BIT(5U)
+#define DRDU2_FORCE_DEVICE_MODE                 BIT(4U)
+#define BDC_USB_STP_SPD_MASK                    0x7U
+#define BDC_USB_STP_SPD_OFFSET                  0U
+
+#define DRDU2_PWR_CTRL                          0x1CU
+#define DRDU2_U2PHY_DFE_SWITCH_PWROKIN_I        BIT(2U)
+#define DRDU2_U2PHY_DFE_SWITCH_PWRONIN_I        BIT(1U)
+
+#define DRDU2_SOFT_RESET_CTRL                   0x20U
+#define DRDU2_BDC_AXI_SOFT_RST_N                BIT(0U)
+
+#define USB3H_U2PLL_NDIV_FRAC                   0x4U
+
+#define USB3H_U2PLL_NDIV_INT                    0x8U
+
+#define USB3H_U2PLL_CTRL                        0xCU
+#define USB3H_U2PLL_LOCK                        BIT(6U)
+#define USB3H_U2PLL_RESETB                      BIT(5U)
+#define USB3H_U2PLL_PDIV_MASK                   0xFU
+#define USB3H_U2PLL_PDIV_OFFSET                 1U
+
+#define USB3H_U2PHY_CTRL                        0x10U
+#define USB3H_U2PHY_ON_FLAG                     22U
+#define USB3H_U2PHY_PCTL_MASK                   0xFFFFU
+#define USB3H_U2PHY_PCTL_OFFSET                 6U
+#define USB3H_U2PHY_IDDQ                        BIT(29U)
+#define USB3H_U2PHY_RESETB                      BIT(5U)
+#define USB3H_U2PHY_ISO                         BIT(4U)
+#define USB3H_U2AFE_BG_PWRDWNB                  BIT(3U)
+#define USB3H_U2AFE_PLL_PWRDWNB                 BIT(2U)
+#define USB3H_U2AFE_LDO_PWRDWNB                 BIT(1U)
+#define USB3H_U2CTRL_CORERDY                    BIT(0U)
+
+#define USB3H_U3PHY_CTRL                        0x14U
+#define USB3H_U3SOFT_RST_N                      BIT(30U)
+#define USB3H_U3MDIO_RESETB_I                   BIT(29U)
+#define USB3H_U3POR_RESET_I                     BIT(28U)
+#define USB3H_U3PHY_PCTL_MASK                   0xFFFFU
+#define USB3H_U3PHY_PCTL_OFFSET                 2U
+#define USB3H_U3PHY_RESETB                      BIT(1U)
+
+#define USB3H_U3PHY_PLL_CTRL                    0x18U
+#define USB3H_U3PLL_REFCLK_MASK                 0x7U
+#define USB3H_U3PLL_REFCLK_OFFSET               4U
+#define USB3H_U3PLL_SS_LOCK                     BIT(3U)
+#define USB3H_U3PLL_SEQ_START                   BIT(2U)
+#define USB3H_U3SSPLL_SUSPEND_EN                BIT(1U)
+#define USB3H_U3PLL_RESETB                      BIT(0U)
+
+#define USB3H_PWR_CTRL                          0x28U
+#define USB3H_PWR_CTRL_OVERRIDE_I_R             4U
+#define USB3H_PWR_CTRL_U2PHY_DFE_SWITCH_PWROKIN BIT(11U)
+#define USB3H_PWR_CTRL_U2PHY_DFE_SWITCH_PWRONIN BIT(10U)
+
+#define USB3H_SOFT_RESET_CTRL                   0x2CU
+#define USB3H_XHC_AXI_SOFT_RST_N                BIT(1U)
+
+#define USB3H_PHY_PWR_CTRL                      0x38U
+#define USB3H_DISABLE_USB30_P0                  BIT(2U)
+#define USB3H_DISABLE_EUSB_P1                   BIT(1U)
+#define USB3H_DISABLE_EUSB_P0                   BIT(0U)
+
+
+#define DRDU3_U2PLL_NDIV_FRAC                   0x4U
+
+#define DRDU3_U2PLL_NDIV_INT                    0x8U
+
+#define DRDU3_U2PLL_CTRL                        0xCU
+#define DRDU3_U2PLL_LOCK                        BIT(6U)
+#define DRDU3_U2PLL_RESETB                      BIT(5U)
+#define DRDU3_U2PLL_PDIV_MASK                   0xFU
+#define DRDU3_U2PLL_PDIV_OFFSET                 1U
+
+#define DRDU3_U2PHY_CTRL                        0x10U
+#define DRDU3_U2PHY_IDDQ                        BIT(29U)
+#define DRDU3_U2PHY_ON_FLAG                     BIT(22U)
+#define DRDU3_U2PHY_PCTL_MASK                   0xFFFFU
+#define DRDU3_U2PHY_PCTL_OFFSET                 6U
+#define DRDU3_U2PHY_RESETB                      BIT(5U)
+#define DRDU3_U2PHY_ISO                         BIT(4U)
+#define DRDU3_U2AFE_BG_PWRDWNB                  BIT(3U)
+#define DRDU3_U2AFE_PLL_PWRDWNB                 BIT(2U)
+#define DRDU3_U2AFE_LDO_PWRDWNB                 BIT(1U)
+#define DRDU3_U2CTRL_CORERDY                    BIT(0U)
+
+#define DRDU3_U3PHY_CTRL                        0x14U
+#define DRDU3_U3XHC_SOFT_RST_N                  BIT(31U)
+#define DRDU3_U3BDC_SOFT_RST_N                  BIT(30U)
+#define DRDU3_U3MDIO_RESETB_I                   BIT(29U)
+#define DRDU3_U3POR_RESET_I                     BIT(28U)
+#define DRDU3_U3PHY_PCTL_MASK                   0xFFFFU
+#define DRDU3_U3PHY_PCTL_OFFSET                 2U
+#define DRDU3_U3PHY_RESETB                      BIT(1U)
+
+#define DRDU3_U3PHY_PLL_CTRL                    0x18U
+#define DRDU3_U3PLL_REFCLK_MASK                 0x7U
+#define DRDU3_U3PLL_REFCLK_OFFSET               4U
+#define DRDU3_U3PLL_SS_LOCK                     BIT(3U)
+#define DRDU3_U3PLL_SEQ_START                   BIT(2U)
+#define DRDU3_U3SSPLL_SUSPEND_EN                BIT(1U)
+#define DRDU3_U3PLL_RESETB                      BIT(0U)
+
+#define DRDU3_STRAP_CTRL                        0x28U
+#define BDC_USB_STP_SPD_MASK                    0x7U
+#define BDC_USB_STP_SPD_OFFSET                  0U
+#define BDC_USB_STP_SPD_SS                      0x0U
+#define BDC_USB_STP_SPD_HS                      0x2U
+
+#define DRDU3_PWR_CTRL                          0x2cU
+#define DRDU3_U2PHY_DFE_SWITCH_PWROKIN          BIT(12U)
+#define DRDU3_U2PHY_DFE_SWITCH_PWRONIN          BIT(11U)
+#define DRDU3_PWR_CTRL_OVERRIDE_I_R             4U
+
+#define DRDU3_SOFT_RESET_CTRL                   0x30U
+#define DRDU3_XHC_AXI_SOFT_RST_N                BIT(1U)
+#define DRDU3_BDC_AXI_SOFT_RST_N                BIT(0U)
+
+#define DRDU3_PHY_PWR_CTRL                      0x3cU
+#define DRDU3_DISABLE_USB30_P0                  BIT(2U)
+#define DRDU3_DISABLE_EUSB_P1                   BIT(1U)
+#define DRDU3_DISABLE_EUSB_P0                   BIT(0U)
+
+#define PLL_REFCLK_PAD                          0x0U
+#define PLL_REFCLK_25MHZ                        0x1U
+#define PLL_REFCLK_96MHZ                        0x2U
+#define PLL_REFCLK_INTERNAL                     0x3U
+/* USB PLL lock time out for 10 ms */
+#define PLL_LOCK_RETRY_COUNT                    10000U
+
+
+#define U2PLL_NDIV_INT_VAL                      0x13U
+#define U2PLL_NDIV_FRAC_VAL                     0x1005U
+#define U2PLL_PDIV_VAL                          0x1U
+/*
+ * Using external FSM
+ * BIT-3:2: device mode; mode is not effect
+ * BIT-1: soft reset active low
+ */
+#define U2PHY_PCTL_VAL                          0x0003U
+/* Non-driving signal low */
+#define U2PHY_PCTL_NON_DRV_LOW                  0x0002U
+#define U3PHY_PCTL_VAL                          0x0006U
+
+#define MAX_NR_PORTS                            3U
+
+#define USB3H_DRDU2_PHY                         1U
+#define DRDU3_PHY                               2U
+
+#define USB_HOST_MODE                           1U
+#define USB_DEV_MODE                            2U
+
+#define USB3SS_PORT                             0U
+#define DRDU2_PORT                              1U
+#define USB3HS_PORT                             2U
+
+#define DRD3SS_PORT                             0U
+#define DRD3HS_PORT                             1U
+
+#define SR_USB_PHY_COUNT                        2U
+
+#define DRDU3_PIPE_CTRL			0x68500000U
+#define DRDU3H_XHC_REGS_CPLIVER		0x68501000U
+#define USB3H_PIPE_CTRL			0x68510000U
+#define DRD2U3H_XHC_REGS_CPLIVER	0x68511000U
+#define DRDU2_U2PLL_NDIV_FRAC		0x68520000U
+
+#define AXI_DEBUG_CTRL				0x68500038U
+#define AXI_DBG_CTRL_SSPHY_DRD_MODE_DISABLE	BIT(12U)
+
+#define USB3H_DEBUG_CTRL			0x68510034U
+#define USB3H_DBG_CTRL_SSPHY_DRD_MODE_DISABLE	BIT(7U)
+
+typedef struct _usb_phy_port usb_phy_port_t;
+
+typedef struct {
+	uint32_t drdu2reg;
+	uint32_t usb3hreg;
+	uint32_t drdu3reg;
+	uint32_t phy_id;
+	uint32_t ports_enabled;
+	uint32_t initialized;
+	usb_phy_port_t *phy_port;
+} usb_phy_t;
+
+struct _usb_phy_port {
+	uint32_t port_id;
+	uint32_t mode;
+	uint32_t enabled;
+	usb_phy_t *p;
+};
+
+struct u2_phy_ext_fsm {
+	uint32_t pll_ctrl_reg;
+	uint32_t phy_ctrl_reg;
+	uint32_t phy_iddq;
+	uint32_t pwr_ctrl_reg;
+	uint32_t pwr_okin;
+	uint32_t pwr_onin;
+};
+
+#endif /* USB_PHY_H */
diff --git a/plat/brcm/board/stingray/platform.mk b/plat/brcm/board/stingray/platform.mk
index 7fcf373..aa2fe86 100644
--- a/plat/brcm/board/stingray/platform.mk
+++ b/plat/brcm/board/stingray/platform.mk
@@ -73,6 +73,12 @@
 BOARD_CFG := bcm958742t
 endif
 
+# Use USB
+ifeq (${USE_USB},yes)
+$(info Using USB)
+$(eval $(call add_define,USE_USB))
+endif
+
 # Use PAXB
 ifeq (${USE_PAXB},yes)
 $(info Using PAXB)
@@ -197,11 +203,15 @@
 PLAT_BL_COMMON_SOURCES	+=	drivers/brcm/chimp.c
 endif
 
+ifeq (${USE_USB},yes)
+PLAT_BL_COMMON_SOURCES	+=	plat/${SOC_DIR}/driver/usb.c \
+				plat/${SOC_DIR}/driver/usb_phy.c
+endif
+
 BL2_SOURCES		+=	plat/${SOC_DIR}/driver/ihost_pll_config.c \
 				plat/${SOC_DIR}/src/bl2_setup.c \
 				plat/${SOC_DIR}/driver/swreg.c
 
-
 ifeq (${USE_DDR},yes)
 PLAT_INCLUDES		+=	-Iplat/${SOC_DIR}/driver/ddr/soc/include
 else
diff --git a/plat/brcm/board/stingray/src/bl31_setup.c b/plat/brcm/board/stingray/src/bl31_setup.c
index a2a274d..04df6a0 100644
--- a/plat/brcm/board/stingray/src/bl31_setup.c
+++ b/plat/brcm/board/stingray/src/bl31_setup.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015 - 2020, Broadcom
+ * Copyright (c) 2015 - 2021, Broadcom
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -28,6 +28,9 @@
 #include <paxb.h>
 #include <paxc.h>
 #include <platform_def.h>
+#ifdef USE_USB
+#include <platform_usb.h>
+#endif
 #include <sdio.h>
 #include <sr_utils.h>
 #include <timer_sync.h>