Add BL31 support for Broadcom stingray platform

Change-Id: Icfef5b6923dc292e637001045a334c499d346fe9
Signed-off-by: Sheetal Tigadoli <sheetal.tigadoli@broadcom.com>
diff --git a/plat/brcm/board/common/board_common.mk b/plat/brcm/board/common/board_common.mk
index 3a879de..a0112c5 100644
--- a/plat/brcm/board/common/board_common.mk
+++ b/plat/brcm/board/common/board_common.mk
@@ -80,6 +80,10 @@
 $(eval $(call add_define,BL2_LOG_LEVEL))
 endif
 
+ifneq (${BL31_LOG_LEVEL},)
+$(eval $(call add_define,BL31_LOG_LEVEL))
+endif
+
 # Use CRMU SRAM from iHOST
 ifneq (${USE_CRMU_SRAM},)
 $(eval $(call add_define,USE_CRMU_SRAM))
@@ -123,6 +127,7 @@
 ifeq (${BCM_ELOG},yes)
 ELOG_SOURCES		+= 	plat/brcm/board/common/bcm_elog.c
 BL2_SOURCES		+= 	${ELOG_SOURCES}
+BL31_SOURCES		+= 	${ELOG_SOURCES}
 endif
 
 ifeq (${DRIVER_OCOTP_ENABLE},1)
diff --git a/plat/brcm/board/stingray/include/bl33_info.h b/plat/brcm/board/stingray/include/bl33_info.h
new file mode 100644
index 0000000..1dac48c
--- /dev/null
+++ b/plat/brcm/board/stingray/include/bl33_info.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2019-2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef BL33_INFO_H
+#define BL33_INFO_H
+
+/* Increase version number each time this file is modified */
+#define BL33_INFO_VERSION	4
+
+struct chip_info {
+	unsigned int chip_id;
+	unsigned int rev_id;
+};
+
+struct boot_time_info {
+	unsigned int bl1_start;
+	unsigned int bl1_end;
+	unsigned int bl2_start;
+	unsigned int bl2_end;
+	unsigned int bl31_start;
+	unsigned int bl31_end;
+	unsigned int bl32_start;
+	unsigned int bl32_end;
+	unsigned int bl33_start;
+	unsigned int bl33_prompt;
+	unsigned int bl33_end;
+};
+
+struct bl33_info {
+	unsigned int version;
+	struct chip_info chip;
+	struct boot_time_info boot_time_info;
+};
+
+#endif
diff --git a/plat/brcm/board/stingray/include/fsx.h b/plat/brcm/board/stingray/include/fsx.h
new file mode 100644
index 0000000..c52ff0a
--- /dev/null
+++ b/plat/brcm/board/stingray/include/fsx.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2017 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef FSX_H
+#define FSX_H
+
+#include <stdbool.h>
+
+typedef enum FSX_TYPE {
+	eFS4_RAID,
+	eFS4_CRYPTO,
+	eFS6_PKI,
+} eFSX_TYPE;
+
+void fsx_init(eFSX_TYPE fsx_type,
+	      unsigned int ring_count,
+	      unsigned int dme_count,
+	      unsigned int ae_count,
+	      unsigned int start_stream_id,
+	      unsigned int msi_dev_id,
+	      uintptr_t idm_io_control_direct,
+	      uintptr_t idm_reset_control,
+	      uintptr_t base,
+	      uintptr_t dme_base);
+
+void fsx_meminit(const char *name,
+		 uintptr_t idm_io_control_direct,
+		 uintptr_t idm_io_status);
+
+void fs4_disable_clocks(bool disable_sram,
+			bool disable_crypto,
+			bool disable_raid);
+
+#endif /* FSX_H */
diff --git a/plat/brcm/board/stingray/include/iommu.h b/plat/brcm/board/stingray/include/iommu.h
new file mode 100644
index 0000000..e7b2985
--- /dev/null
+++ b/plat/brcm/board/stingray/include/iommu.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2016 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef IOMMU_H
+#define IOMMU_H
+
+enum iommu_domain {
+	PCIE_PAXC,
+	DOMAIN_CRMU,
+};
+
+void arm_smmu_create_identity_map(enum iommu_domain dom);
+void arm_smmu_reserve_secure_cntxt(void);
+void arm_smmu_enable_secure_client_port(void);
+
+#endif /* IOMMU_H */
diff --git a/plat/brcm/board/stingray/include/ncsi.h b/plat/brcm/board/stingray/include/ncsi.h
new file mode 100644
index 0000000..04dd640
--- /dev/null
+++ b/plat/brcm/board/stingray/include/ncsi.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2019-2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef NCSI_H
+#define NCSI_H
+
+/*
+ * There are 10 registers for NCSI IO drivers.
+ */
+#define NITRO_NCSI_IOPAD_CONTROL_NUM	10
+#define NITRO_NCSI_IOPAD_CONTROL_BASE	0x60e05080
+
+/*
+ * NCSI IO Drive strength
+ *   000 - Drives 2mA
+ *   001 - Drives 4mA
+ *   010 - Drives 6mA
+ *   011 - Drives 8mA
+ *   100 - Drives 10mA
+ *   101 - Drives 12mA
+ *   110 - Drives 14mA
+ *   111 - Drives 16mA
+ */
+#define PAD_SELX_VALUE(selx)	((selx) << 1)
+#define PAD_SELX_MASK		(0x7 << 1)
+
+void brcm_stingray_ncsi_init(void);
+
+#endif
diff --git a/plat/brcm/board/stingray/include/paxb.h b/plat/brcm/board/stingray/include/paxb.h
new file mode 100644
index 0000000..c64c8a6
--- /dev/null
+++ b/plat/brcm/board/stingray/include/paxb.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2016 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PAXB_H
+#define PAXB_H
+
+/* total number of PCIe cores */
+#define NUM_OF_SR_PCIE_CORES           8
+#define NUM_OF_NS3Z_PCIE_CORES         1
+
+/*
+ * List of PCIe core and PAXB wrapper memory power registers
+ */
+#define PCIE_CORE_BASE                   0x40000800
+#define PCIE_CORE_SOFT_RST_CFG_BASE      (PCIE_CORE_BASE + 0x40)
+#define PCIE_CORE_SOFT_RST               0x1
+#define PCIE_CORE_ISO_CFG_BASE           (PCIE_CORE_BASE + 0x54)
+#define PCIE_CORE_MEM_ISO                0x2
+#define PCIE_CORE_ISO                    0x1
+
+#define PCIE_CORE_MEM_PWR_BASE           (PCIE_CORE_BASE + 0x58)
+#define PCIE_PAXB_MEM_PWR_BASE           (PCIE_CORE_BASE + 0x5c)
+#define PCIE_CORE_PMI_CFG_BASE           (PCIE_CORE_BASE + 0x64)
+#define PCIE_CORE_RESERVED_CFG           (PCIE_CORE_BASE + 0x6c)
+#define PCIE_CORE_MEM_PWR_STATUS_BASE    (PCIE_CORE_BASE + 0x74)
+#define PCIE_PAXB_MEM_PWR_STATUS_BASE    (PCIE_CORE_BASE + 0x78)
+#define PCIE_CORE_PWR_OFFSET           0x100
+
+#define SR_A0_DEVICE_ID                 0xd713
+#define SR_B0_DEVICE_ID                 0xd714
+/* TODO: Modify device ID once available */
+#define NS3Z_DEVICE_ID                  0xd715
+
+/* FIXME: change link speed to GEN3 when it's ready */
+#define GEN1_LINK_SPEED               1
+#define GEN2_LINK_SPEED               2
+#define GEN3_LINK_SPEED               3
+
+typedef struct {
+	uint32_t type;
+	uint32_t device_id;
+	uint32_t pipemux_idx;
+	uint32_t num_cores;
+	int (*pipemux_init)(void);
+	int (*phy_init)(void);
+	int (*core_needs_enable)(unsigned int core_idx);
+	unsigned int (*get_link_width)(unsigned int core_idx);
+	unsigned int (*get_link_speed)(void);
+} paxb_cfg;
+
+enum paxb_type {
+	PAXB_SR,
+	PAXB_NS3Z,
+};
+
+extern const paxb_cfg *paxb;
+
+#ifdef USE_PAXB
+void paxb_init(void);
+void paxb_rc_cfg_write(unsigned int core_idx, unsigned int where,
+		       uint32_t val);
+unsigned int paxb_rc_cfg_read(unsigned int core_idx, unsigned int where);
+int pcie_core_needs_enable(unsigned int core_idx);
+const paxb_cfg *paxb_get_sr_config(void);
+#else
+static inline void paxb_init(void)
+{
+}
+#endif
+
+#endif /* PAXB_H */
diff --git a/plat/brcm/board/stingray/include/paxc.h b/plat/brcm/board/stingray/include/paxc.h
new file mode 100644
index 0000000..ae1af2e
--- /dev/null
+++ b/plat/brcm/board/stingray/include/paxc.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2017 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PAXC_H
+#define PAXC_H
+
+#ifdef USE_PAXC
+void paxc_init(void);
+void paxc_mhb_ns_init(void);
+#else
+static inline void paxc_init(void)
+{
+}
+
+static inline void paxc_mhb_ns_init(void)
+{
+}
+#endif
+
+#endif /* PAXC_H */
diff --git a/plat/brcm/board/stingray/include/sdio.h b/plat/brcm/board/stingray/include/sdio.h
new file mode 100644
index 0000000..e08904e
--- /dev/null
+++ b/plat/brcm/board/stingray/include/sdio.h
@@ -0,0 +1,247 @@
+/*
+ * Copyright (c) 2019-2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SDIO_H
+#define SDIO_H
+
+#include <stdbool.h>
+
+#define SR_IPROC_SDIO0_CFG_BASE      0x689006e4
+#define SR_IPROC_SDIO0_SID_BASE      0x68900b00
+#define SR_IPROC_SDIO0_PAD_BASE      0x68a4017c
+#define SR_IPROC_SDIO0_IOCTRL_BASE   0x68e02408
+
+#define SR_IPROC_SDIO1_CFG_BASE      0x68900734
+#define SR_IPROC_SDIO1_SID_BASE      0x68900b08
+#define SR_IPROC_SDIO1_PAD_BASE      0x68a401b4
+#define SR_IPROC_SDIO1_IOCTRL_BASE   0x68e03408
+
+#define NS3Z_IPROC_SDIO0_CFG_BASE    0x68a20540
+#define NS3Z_IPROC_SDIO0_SID_BASE    0x68900b00
+#define NS3Z_IPROC_SDIO0_TP_OUT_SEL  0x68a20308
+#define NS3Z_IPROC_SDIO0_PAD_BASE    0x68a20500
+#define NS3Z_IPROC_SDIO0_IOCTRL_BASE 0x68e02408
+
+#define PHY_BYPASS      BIT(14)
+#define LEGACY_EN       BIT(31)
+#define PHY_DISABLE     (LEGACY_EN | PHY_BYPASS)
+
+#define NS3Z_IPROC_SDIO1_CFG_BASE    0x68a30540
+#define NS3Z_IPROC_SDIO1_SID_BASE    0x68900b08
+#define NS3Z_IPROC_SDIO1_PAD_BASE    0x68a30500
+#define NS3Z_IPROC_SDIO1_IOCTRL_BASE 0x68e03408
+
+#define ICFG_SDIO_CAP0          0x10
+#define ICFG_SDIO_CAP1          0x14
+#define ICFG_SDIO_STRAPSTATUS_0 0x0
+#define ICFG_SDIO_STRAPSTATUS_1 0x4
+#define ICFG_SDIO_STRAPSTATUS_2 0x8
+#define ICFG_SDIO_STRAPSTATUS_3 0xc
+#define ICFG_SDIO_STRAPSTATUS_4 0x18
+
+#define ICFG_SDIO_SID_ARADDR    0x0
+#define ICFG_SDIO_SID_AWADDR    0x4
+
+#define ICFG_SDIOx_CAP0__SLOT_TYPE_MASK         0x3
+#define ICFG_SDIOx_CAP0__SLOT_TYPE_SHIFT        27
+#define ICFG_SDIOx_CAP0__INT_MODE_SHIFT         26
+#define ICFG_SDIOx_CAP0__SYS_BUS_64BIT_SHIFT    25
+#define ICFG_SDIOx_CAP0__VOLTAGE_1P8V_SHIFT     24
+#define ICFG_SDIOx_CAP0__VOLTAGE_3P0V_SHIFT     23
+#define ICFG_SDIOx_CAP0__VOLTAGE_3P3V_SHIFT     22
+#define ICFG_SDIOx_CAP0__SUSPEND_RESUME_SHIFT   21
+#define ICFG_SDIOx_CAP0__SDMA_SHIFT             20
+#define ICFG_SDIOx_CAP0__HIGH_SPEED_SHIFT       19
+#define ICFG_SDIOx_CAP0__ADMA2_SHIFT            18
+#define ICFG_SDIOx_CAP0__EXTENDED_MEDIA_SHIFT   17
+#define ICFG_SDIOx_CAP0__MAX_BLOCK_LEN_MASK     0x3
+#define ICFG_SDIOx_CAP0__MAX_BLOCK_LEN_SHIFT    15
+#define ICFG_SDIOx_CAP0__BASE_CLK_FREQ_MASK     0xff
+#define ICFG_SDIOx_CAP0__BASE_CLK_FREQ_SHIFT    7
+#define ICFG_SDIOx_CAP0__TIMEOUT_UNIT_SHIFT     6
+#define ICFG_SDIOx_CAP0__TIMEOUT_CLK_FREQ_MASK  0x3f
+#define ICFG_SDIOx_CAP0__TIMEOUT_CLK_FREQ_SHIFT 0
+
+#define ICFG_SDIOx_CAP1__SPI_BLOCK_MODE_SHIFT   22
+#define ICFG_SDIOx_CAP1__SPI_MODE_SHIFT         21
+#define ICFG_SDIOx_CAP1__CLK_MULT_MASK          0xff
+#define ICFG_SDIOx_CAP1__CLK_MULT_SHIFT         13
+#define ICFG_SDIOx_CAP1__RETUNING_MODE_MASK     0x3
+#define ICFG_SDIOx_CAP1__RETUNING_MODE_SHIFT    11
+#define ICFG_SDIOx_CAP1__TUNE_SDR50_SHIFT       10
+#define ICFG_SDIOx_CAP1__TIME_RETUNE_MASK       0xf
+#define ICFG_SDIOx_CAP1__TIME_RETUNE_SHIFT      6
+#define ICFG_SDIOx_CAP1__DRIVER_D_SHIFT         5
+#define ICFG_SDIOx_CAP1__DRIVER_C_SHIFT         4
+#define ICFG_SDIOx_CAP1__DRIVER_A_SHIFT         3
+#define ICFG_SDIOx_CAP1__DDR50_SHIFT            2
+#define ICFG_SDIOx_CAP1__SDR104_SHIFT           1
+#define ICFG_SDIOx_CAP1__SDR50_SHIFT            0
+
+#ifdef USE_DDR
+#define SDIO_DMA  1
+#else
+#define SDIO_DMA  0
+#endif
+
+#define SDIO0_CAP0_CFG  \
+	(0x1 << ICFG_SDIOx_CAP0__SLOT_TYPE_SHIFT) \
+	| (0x0 << ICFG_SDIOx_CAP0__INT_MODE_SHIFT) \
+	| (0x0 << ICFG_SDIOx_CAP0__SYS_BUS_64BIT_SHIFT) \
+	| (0x1 << ICFG_SDIOx_CAP0__VOLTAGE_1P8V_SHIFT) \
+	| (0x1 << ICFG_SDIOx_CAP0__VOLTAGE_3P0V_SHIFT) \
+	| (0x1 << ICFG_SDIOx_CAP0__VOLTAGE_3P3V_SHIFT) \
+	| (0x1 << ICFG_SDIOx_CAP0__SUSPEND_RESUME_SHIFT) \
+	| (SDIO_DMA << ICFG_SDIOx_CAP0__SDMA_SHIFT) \
+	| (SDIO_DMA << ICFG_SDIOx_CAP0__ADMA2_SHIFT) \
+	| (0x1 << ICFG_SDIOx_CAP0__HIGH_SPEED_SHIFT) \
+	| (0x1 << ICFG_SDIOx_CAP0__EXTENDED_MEDIA_SHIFT) \
+	| (0x2 << ICFG_SDIOx_CAP0__MAX_BLOCK_LEN_SHIFT) \
+	| (0xc8 << ICFG_SDIOx_CAP0__BASE_CLK_FREQ_SHIFT) \
+	| (0x1 << ICFG_SDIOx_CAP0__TIMEOUT_UNIT_SHIFT) \
+	| (0x30 << ICFG_SDIOx_CAP0__TIMEOUT_CLK_FREQ_SHIFT)
+
+#define SDIO0_CAP1_CFG  \
+	(0x1 << ICFG_SDIOx_CAP1__SPI_BLOCK_MODE_SHIFT)\
+	| (0x1 << ICFG_SDIOx_CAP1__SPI_MODE_SHIFT)\
+	| (0x0 << ICFG_SDIOx_CAP1__CLK_MULT_SHIFT)\
+	| (0x2 << ICFG_SDIOx_CAP1__RETUNING_MODE_SHIFT)\
+	| (0x1 << ICFG_SDIOx_CAP1__TUNE_SDR50_SHIFT)\
+	| (0x0 << ICFG_SDIOx_CAP1__DRIVER_D_SHIFT)\
+	| (0x0 << ICFG_SDIOx_CAP1__DRIVER_C_SHIFT)\
+	| (0x1 << ICFG_SDIOx_CAP1__DRIVER_A_SHIFT)\
+	| (0x1 << ICFG_SDIOx_CAP1__DDR50_SHIFT)\
+	| (0x1 << ICFG_SDIOx_CAP1__SDR104_SHIFT)\
+	| (0x1 << ICFG_SDIOx_CAP1__SDR50_SHIFT)
+
+#define SDIO1_CAP0_CFG  \
+	(0x0 << ICFG_SDIOx_CAP0__SLOT_TYPE_SHIFT) \
+	| (0x0 << ICFG_SDIOx_CAP0__INT_MODE_SHIFT) \
+	| (0x0 << ICFG_SDIOx_CAP0__SYS_BUS_64BIT_SHIFT) \
+	| (0x1 << ICFG_SDIOx_CAP0__VOLTAGE_1P8V_SHIFT) \
+	| (0x1 << ICFG_SDIOx_CAP0__VOLTAGE_3P0V_SHIFT) \
+	| (0x1 << ICFG_SDIOx_CAP0__VOLTAGE_3P3V_SHIFT) \
+	| (0x1 << ICFG_SDIOx_CAP0__SUSPEND_RESUME_SHIFT) \
+	| (SDIO_DMA << ICFG_SDIOx_CAP0__SDMA_SHIFT) \
+	| (SDIO_DMA << ICFG_SDIOx_CAP0__ADMA2_SHIFT) \
+	| (0x1 << ICFG_SDIOx_CAP0__HIGH_SPEED_SHIFT) \
+	| (0x1 << ICFG_SDIOx_CAP0__EXTENDED_MEDIA_SHIFT) \
+	| (0x2 << ICFG_SDIOx_CAP0__MAX_BLOCK_LEN_SHIFT) \
+	| (0xc8 << ICFG_SDIOx_CAP0__BASE_CLK_FREQ_SHIFT) \
+	| (0x1 << ICFG_SDIOx_CAP0__TIMEOUT_UNIT_SHIFT) \
+	| (0x30 << ICFG_SDIOx_CAP0__TIMEOUT_CLK_FREQ_SHIFT)
+
+#define SDIO1_CAP1_CFG  \
+	(0x1 << ICFG_SDIOx_CAP1__SPI_BLOCK_MODE_SHIFT)\
+	| (0x1 << ICFG_SDIOx_CAP1__SPI_MODE_SHIFT)\
+	| (0x0 << ICFG_SDIOx_CAP1__CLK_MULT_SHIFT)\
+	| (0x2 << ICFG_SDIOx_CAP1__RETUNING_MODE_SHIFT)\
+	| (0x1 << ICFG_SDIOx_CAP1__TUNE_SDR50_SHIFT)\
+	| (0x0 << ICFG_SDIOx_CAP1__DRIVER_D_SHIFT)\
+	| (0x0 << ICFG_SDIOx_CAP1__DRIVER_C_SHIFT)\
+	| (0x1 << ICFG_SDIOx_CAP1__DRIVER_A_SHIFT)\
+	| (0x1 << ICFG_SDIOx_CAP1__DDR50_SHIFT)\
+	| (0x1 << ICFG_SDIOx_CAP1__SDR104_SHIFT)\
+	| (0x1 << ICFG_SDIOx_CAP1__SDR50_SHIFT)
+
+#define PAD_SDIO_CLK      0x4
+#define PAD_SDIO_DATA0    0x8
+#define PAD_SDIO_DATA1    0xc
+#define PAD_SDIO_DATA2    0x10
+#define PAD_SDIO_DATA3    0x14
+#define PAD_SDIO_DATA4    0x18
+#define PAD_SDIO_DATA5    0x1c
+#define PAD_SDIO_DATA6    0x20
+#define PAD_SDIO_DATA7    0x24
+#define PAD_SDIO_CMD      0x28
+
+/* 12mA Drive strength*/
+#define PAD_SDIO_SELX     (0x5 << 1)
+#define PAD_SDIO_SRC      (1 << 0)
+#define PAD_SDIO_MASK     (0xF << 0)
+#define PAD_SDIO_VALUE    (PAD_SDIO_SELX | PAD_SDIO_SRC)
+
+/*
+ * SDIO_PRESETVAL0
+ *
+ * Each 13 Bit filed consists:
+ * drivestrength - 12:11
+ * clkgensel - b10
+ * sdkclkfreqsel - 9:0
+ * Field		Bit(s)		Description
+ * ============================================================
+ * SDR25_PRESET		25:13		Preset Value for SDR25
+ * SDR50_PRESET		12:0		Preset Value for SDR50
+ */
+#define SDIO_PRESETVAL0		0x01005001
+
+/*
+ * SDIO_PRESETVAL1
+ *
+ * Each 13 Bit filed consists:
+ * drivestrength - 12:11
+ * clkgensel - b10
+ * sdkclkfreqsel - 9:0
+ * Field		Bit(s)		Description
+ * ============================================================
+ * SDR104_PRESET		25:13		Preset Value for SDR104
+ * SDR12_PRESET		12:0		Preset Value for SDR12
+ */
+#define SDIO_PRESETVAL1		0x03000004
+
+/*
+ * SDIO_PRESETVAL2
+ *
+ * Each 13 Bit filed consists:
+ * drivestrength - 12:11
+ * clkgensel - b10
+ * sdkclkfreqsel - 9:0
+ * Field		Bit(s)		Description
+ * ============================================================
+ * HIGH_SPEED_PRESET	25:13		Preset Value for High Speed
+ * INIT_PRESET		12:0		Preset Value for Initialization
+ */
+#define SDIO_PRESETVAL2		0x010040FA
+
+/*
+ * SDIO_PRESETVAL3
+ *
+ * Each 13 Bit filed consists:
+ * drivestrength - 12:11
+ * clkgensel - b10
+ * sdkclkfreqsel - 9:0
+ * Field		Bit(s)		Description
+ * ============================================================
+ * DDR50_PRESET		25:13		Preset Value for DDR50
+ * DEFAULT_PRESET	12:0		Preset Value for Default Speed
+ */
+#define SDIO_PRESETVAL3		0x01004004
+
+/*
+ * SDIO_PRESETVAL4
+ *
+ * Field			Bit(s)		Description
+ * ============================================================
+ * FORCE_USE_IP_TUNE_CLK	30		Force use IP clock
+ * TUNING_COUNT			29:24		Tuning count
+ * OVERRIDE_1P8V		23:16
+ * OVERRIDE_3P3V		15:8
+ * OVERRIDE_3P0V		7:0
+ */
+#define SDIO_PRESETVAL4		0x20010101
+
+#define SDIO_SID_SHIFT		5
+
+typedef struct {
+	uintptr_t cfg_base;
+	uintptr_t sid_base;
+	uintptr_t io_ctrl_base;
+	uintptr_t pad_base;
+} SDIO_CFG;
+
+void brcm_stingray_sdio_init(void);
+
+#endif /* SDIO_H */
diff --git a/plat/brcm/board/stingray/platform.mk b/plat/brcm/board/stingray/platform.mk
index f4b665c..cc7ae53 100644
--- a/plat/brcm/board/stingray/platform.mk
+++ b/plat/brcm/board/stingray/platform.mk
@@ -27,8 +27,21 @@
 # BL31 is in DRAM
 ARM_BL31_IN_DRAM	:=	1
 
+ifneq (${USE_EMULATOR},yes)
+STINGRAY_EMULATION_SETUP	:=	0
+ifeq (${FASTBOOT_TYPE},)
+override FASTBOOT_TYPE		:=	0
+endif
+USE_PAXB := yes
+USE_PAXC := yes
+USE_CHIMP := yes
+endif
+
 USE_CRMU_SRAM := yes
 
+# Disable FS4 clocks - they can be reenabled when needed by linux
+FS4_DISABLE_CLOCK := yes
+
 # Enable error logging by default for Stingray
 BCM_ELOG := yes
 
@@ -53,6 +66,35 @@
 BOARD_CFG := bcm958742k
 endif
 
+# Use PAXB
+ifeq (${USE_PAXB},yes)
+$(info Using PAXB)
+$(eval $(call add_define,USE_PAXB))
+endif
+
+# Use FS4
+ifeq (${USE_FS4},yes)
+$(info Using FS4)
+$(eval $(call add_define,USE_FS4))
+endif
+
+# Use FS6
+ifeq (${USE_FS6},yes)
+$(info Using FS6)
+$(eval $(call add_define,USE_FS6))
+endif
+
+# Disable FS4 clock
+ifeq (${FS4_DISABLE_CLOCK},yes)
+$(info Using FS4_DISABLE_CLOCK)
+$(eval $(call add_define,FS4_DISABLE_CLOCK))
+endif
+
+ifneq (${NCSI_IO_DRIVE_STRENGTH_MA},)
+$(info Using NCSI_IO_DRIVE_STRENGTH_MA)
+$(eval $(call add_define,NCSI_IO_DRIVE_STRENGTH_MA))
+endif
+
 # Use NAND
 ifeq (${USE_NAND},$(filter yes, ${USE_NAND}))
 $(info Using NAND)
@@ -71,6 +113,44 @@
 $(info Using RESET_TO_BL31)
 endif
 
+# BL31 force full frequency for all CPUs
+ifeq (${BL31_FORCE_CPU_FULL_FREQ},yes)
+$(info Using BL31_FORCE_CPU_FULL_FREQ)
+$(eval $(call add_define,BL31_FORCE_CPU_FULL_FREQ))
+endif
+
+# Enable non-secure accesses to CCN registers
+ifeq (${BL31_CCN_NONSECURE},yes)
+$(info Using BL31_CCN_NONSECURE)
+$(eval $(call add_define,BL31_CCN_NONSECURE))
+endif
+
+# Use ChiMP
+ifeq (${USE_CHIMP},yes)
+$(info Using ChiMP)
+$(eval $(call add_define,USE_CHIMP))
+endif
+
+# Use PAXC
+ifeq (${USE_PAXC},yes)
+$(info Using PAXC)
+$(eval $(call add_define,USE_PAXC))
+ifeq (${CHIMPFW_USE_SIDELOAD},yes)
+$(info Using ChiMP FW sideload)
+$(eval $(call add_define,CHIMPFW_USE_SIDELOAD))
+endif
+$(eval $(call add_define,FASTBOOT_TYPE))
+$(eval $(call add_define,CHIMP_FB1_ENTRY))
+endif
+
+ifeq (${DEFAULT_SWREG_CONFIG}, 1)
+$(eval $(call add_define,DEFAULT_SWREG_CONFIG))
+endif
+
+ifeq (${CHIMP_ALWAYS_NEEDS_QSPI},yes)
+$(eval $(call add_define,CHIMP_ALWAYS_NEEDS_QSPI))
+endif
+
 # For testing purposes, use memsys stubs.  Remove once memsys is fully tested.
 USE_MEMSYS_STUBS := yes
 
@@ -100,6 +180,10 @@
 				drivers/arm/tzc/tzc400.c \
 				plat/${SOC_DIR}/src/topology.c
 
+ifeq (${USE_CHIMP},yes)
+PLAT_BL_COMMON_SOURCES	+=	drivers/brcm/chimp.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
@@ -125,8 +209,25 @@
 				plat/brcm/common/brcm_ccn.c \
 				plat/common/plat_psci_common.c \
 				plat/${SOC_DIR}/driver/ihost_pll_config.c \
+				plat/${SOC_DIR}/src/bl31_setup.c \
+				plat/${SOC_DIR}/src/fsx.c \
+				plat/${SOC_DIR}/src/iommu.c \
+				plat/${SOC_DIR}/src/sdio.c \
 				${BRCM_GIC_SOURCES}
 
+ifneq (${NCSI_IO_DRIVE_STRENGTH_MA},)
+BL31_SOURCES   +=      plat/${SOC_DIR}/src/ncsi.c
+endif
+
+ifeq (${USE_PAXB},yes)
+BL31_SOURCES   +=      plat/${SOC_DIR}/src/paxb.c
+BL31_SOURCES   +=      plat/${SOC_DIR}/src/sr_paxb_phy.c
+endif
+
+ifeq (${USE_PAXC},yes)
+BL31_SOURCES   +=      plat/${SOC_DIR}/src/paxc.c
+endif
+
 ifdef SCP_BL2
 PLAT_INCLUDES		+=	-Iplat/brcm/common/
 
@@ -150,6 +251,24 @@
 endif
 endif
 
+ifeq (${BL31_BOOT_PRELOADED_SCP}, 1)
+ifdef SCP_BL2
+SCP_CFG_DIR=$(dir ${SCP_BL2})
+PLAT_INCLUDES	+=	-I${SCP_CFG_DIR}
+endif
+PLAT_INCLUDES	+=	-Iplat/brcm/common/
+
+# By default use OPTEE Assigned memory
+PRELOADED_SCP_BASE ?= 0x8E000000
+PRELOADED_SCP_SIZE ?= 0x10000
+$(eval $(call add_define,PRELOADED_SCP_BASE))
+$(eval $(call add_define,PRELOADED_SCP_SIZE))
+$(eval $(call add_define,BL31_BOOT_PRELOADED_SCP))
+BL31_SOURCES += plat/${SOC_DIR}/src/scp_utils.c \
+		plat/${SOC_DIR}/src/scp_cmd.c \
+		drivers/brcm/scp.c
+endif
+
 # Do not execute the startup code on warm reset.
 PROGRAMMABLE_RESET_ADDRESS	:=	1
 
diff --git a/plat/brcm/board/stingray/src/bl31_setup.c b/plat/brcm/board/stingray/src/bl31_setup.c
new file mode 100644
index 0000000..d947551
--- /dev/null
+++ b/plat/brcm/board/stingray/src/bl31_setup.c
@@ -0,0 +1,1068 @@
+/*
+ * Copyright (c) 2015 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <errno.h>
+
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <cortex_a72.h>
+#include <drivers/arm/sp805.h>
+#include <drivers/console.h>
+#include <drivers/delay_timer.h>
+#include <drivers/ti/uart/uart_16550.h>
+#include <lib/mmio.h>
+#include <lib/utils_def.h>
+#include <plat/common/common_def.h>
+#include <plat/common/platform.h>
+
+#include <bl33_info.h>
+#include <chimp.h>
+#include <cmn_plat_util.h>
+#include <dmu.h>
+#include <fsx.h>
+#include <iommu.h>
+#include <ncsi.h>
+#include <paxb.h>
+#include <paxc.h>
+#include <platform_def.h>
+#include <sdio.h>
+#include <sr_utils.h>
+#include <timer_sync.h>
+
+/*******************************************************************************
+ * Perform any BL3-1 platform setup common to ARM standard platforms
+ ******************************************************************************/
+
+static void brcm_stingray_gain_qspi_control(void)
+{
+	if (boot_source_get() != BOOT_SOURCE_QSPI) {
+		if (bcm_chimp_is_nic_mode() &&
+		(!bcm_chimp_handshake_done())) {
+			/*
+			 * Last chance to wait for ChiMP firmware to report
+			 * "I am done" before grabbing the QSPI
+			 */
+			WARN("ChiMP still not booted\n");
+#ifndef CHIMP_ALWAYS_NEEDS_QSPI
+			WARN("ChiMP is given the last chance to boot (%d s)\n",
+				CHIMP_HANDSHAKE_TIMEOUT_MS / 1000);
+
+			if (!bcm_chimp_wait_handshake()) {
+				ERROR("ChiMP failed to boot\n");
+			} else {
+				INFO("ChiMP booted successfully\n");
+			}
+#endif
+		}
+
+#ifndef CHIMP_ALWAYS_NEEDS_QSPI
+		INFO("AP grabs QSPI\n");
+		/*
+		 * For QSPI boot sbl/bl1 has already taken care.
+		 * For other boot sources QSPI needs to be muxed to
+		 * AP for exclusive use
+		 */
+		brcm_stingray_set_qspi_mux(1);
+		INFO("AP (bl31) gained control over QSPI\n");
+#endif
+	}
+}
+
+static void brcm_stingray_dma_pl330_init(void)
+{
+	unsigned int val;
+
+	VERBOSE("dma pl330 init start\n");
+
+	/* Set DMAC boot_manager_ns = 0x1 */
+	VERBOSE(" - configure boot security state\n");
+	mmio_setbits_32(DMAC_M0_IDM_IO_CONTROL_DIRECT, BOOT_MANAGER_NS);
+	/* Set boot_peripheral_ns[n:0] = 0xffffffff */
+	mmio_write_32(ICFG_DMAC_CONFIG_2, BOOT_PERIPHERAL_NS);
+	/* Set boot_irq_ns[n:0] = 0x0000ffff */
+	mmio_write_32(ICFG_DMAC_CONFIG_3, BOOT_IRQ_NS);
+
+	/* Set DMAC stream_id */
+	VERBOSE(" - configure stream_id = 0x6000\n");
+	val = (DMAC_STREAM_ID << DMAC_SID_SHIFT);
+	mmio_write_32(ICFG_DMAC_SID_ARADDR_CONTROL, val);
+	mmio_write_32(ICFG_DMAC_SID_AWADDR_CONTROL, val);
+
+	/* Reset DMAC */
+	VERBOSE(" - reset dma pl330\n");
+
+	mmio_setbits_32(DMAC_M0_IDM_RESET_CONTROL, 0x1);
+	udelay(500);
+
+	mmio_clrbits_32(DMAC_M0_IDM_RESET_CONTROL, 0x1);
+	udelay(500);
+
+	INFO("dma pl330 init done\n");
+}
+
+static void brcm_stingray_spi_pl022_init(uintptr_t idm_reset_control)
+{
+	VERBOSE("spi pl022 init start\n");
+
+	/* Reset APB SPI bridge */
+	VERBOSE(" - reset apb spi bridge\n");
+	mmio_setbits_32(idm_reset_control, 0x1);
+	udelay(500);
+
+	mmio_clrbits_32(idm_reset_control, 0x1);
+	udelay(500);
+
+	INFO("spi pl022 init done\n");
+}
+
+#define CDRU_SATA_RESET_N \
+	BIT(CDRU_MISC_RESET_CONTROL__CDRU_SATA_RESET_N_R)
+#define CDRU_MISC_CLK_SATA \
+	BIT(CDRU_MISC_CLK_ENABLE_CONTROL__CDRU_SATA_CLK_EN_R)
+#define CCN_CONFIG_CLK_ENABLE		(1 << 2)
+#define MMU_CONFIG_CLK_ENABLE		(0x3F << 16)
+
+#define SATA_SATA_TOP_CTRL_BUS_CTRL	(SATA_BASE + 0x2044)
+#define DMA_BIT_CTRL_MASK		0x003
+#define DMA_DESCR_ENDIAN_CTRL		(DMA_BIT_CTRL_MASK << 0x002)
+#define DMA_DATA_ENDIAN_CTRL		(DMA_BIT_CTRL_MASK << 0x004)
+
+#define SATA_PORT_SATA3_PCB_REG8	(SATA_BASE + 0x2320)
+#define SATA_PORT_SATA3_PCB_REG11	(SATA_BASE + 0x232c)
+#define SATA_PORT_SATA3_PCB_BLOCK_ADDR	(SATA_BASE + 0x233c)
+
+#define SATA3_AFE_TXRX_ACTRL		0x1d0
+/* TXDriver swing setting is 800mV */
+#define DFS_SWINGNOPE_VALUE		(0x0 << 6)
+#define DFS_SWINGNOPE_MASK		(0x3 << 6)
+
+#define DFS_SWINGPE_VALUE		(0x1 << 4)
+#define DFS_SWINGPE_MASK		(0x3 << 4)
+
+#define DFS_INJSTRENGTH_VALUE		(0x0 << 4)
+#define DFS_INJSTRENGTH_MASK		(0x3 << 4)
+
+#define DFS_INJEN			(0x1 << 3)
+
+#define SATA_CORE_MEM_CTRL		(SATA_BASE + 0x3a08)
+#define SATA_CORE_MEM_CTRL_ISO		BIT(0)
+#define SATA_CORE_MEM_CTRL_ARRPOWEROKIN	BIT(1)
+#define SATA_CORE_MEM_CTRL_ARRPOWERONIN	BIT(2)
+#define SATA_CORE_MEM_CTRL_POWEROKIN	BIT(3)
+#define SATA_CORE_MEM_CTRL_POWERONIN	BIT(4)
+
+#define SATA0_IDM_RESET_CONTROL			(SATA_BASE + 0x500800)
+#define SATA_APBT0_IDM_IO_CONTROL_DIRECT	(SATA_BASE + 0x51a408)
+#define IO_CONTROL_DIRECT_CLK_ENABLE		BIT(0)
+#define SATA_APBT0_IDM_RESET_CONTROL		(SATA_BASE + 0x51a800)
+#define IDM_RESET_CONTROL_RESET			BIT(0)
+
+#define NIC400_SATA_NOC_SECURITY1	0x6830000c
+#define SATA_NOC_SECURITY1_FIELD	0xf
+#define NIC400_SATA_NOC_SECURITY2	0x68300010
+#define SATA_NOC_SECURITY2_FIELD	0xf
+#define NIC400_SATA_NOC_SECURITY3	0x68300014
+#define SATA_NOC_SECURITY3_FIELD	0x1
+#define NIC400_SATA_NOC_SECURITY4	0x68300018
+#define SATA_NOC_SECURITY4_FIELD	0x1
+#define NIC400_SATA_NOC_SECURITY5	0x6830001c
+#define SATA_NOC_SECURITY5_FIELD	0xf
+#define NIC400_SATA_NOC_SECURITY6	0x68300020
+#define SATA_NOC_SECURITY6_FIELD	0x1
+#define NIC400_SATA_NOC_SECURITY7	0x68300024
+#define SATA_NOC_SECURITY7_FIELD	0xf
+#define NIC400_SATA_NOC_SECURITY8	0x68300028
+#define SATA_NOC_SECURITY8_FIELD	0xf
+#define NIC400_SATA_NOC_SECURITY9	0x6830002c
+#define SATA_NOC_SECURITY9_FIELD	0x1
+
+#define SATA_APBT_IDM_PORT_REG(port, reg) \
+	(((port/4) << 12) + reg)
+
+#define SATA_IDM_PORT_REG(port, reg)	((port << 12) + reg)
+
+#define SATA_PORT_REG(port, reg) \
+	(((port%4) << 16) + ((port/4) << 20) + reg)
+
+#define MAX_SATA_PORTS	8
+#define USE_SATA_PORTS	8
+
+#ifdef USE_SATA
+static const uint8_t sr_b0_sata_port[MAX_SATA_PORTS] = {
+	0, 1, 2, 3, 4, 5, 6, 7
+};
+
+static uint32_t brcm_stingray_get_sata_port(unsigned int port)
+{
+	return sr_b0_sata_port[port];
+}
+
+static void brcm_stingray_sata_init(void)
+{
+	unsigned int port = 0;
+	uint32_t sata_port;
+
+	mmio_setbits_32(CDRU_MISC_CLK_ENABLE_CONTROL,
+			CDRU_MISC_CLK_SATA);
+
+	mmio_clrbits_32(CDRU_MISC_RESET_CONTROL, CDRU_SATA_RESET_N);
+	mmio_setbits_32(CDRU_MISC_RESET_CONTROL, CDRU_SATA_RESET_N);
+
+	for (port = 0; port < USE_SATA_PORTS; port++) {
+
+		sata_port = brcm_stingray_get_sata_port(port);
+		mmio_write_32(SATA_APBT_IDM_PORT_REG(sata_port,
+					SATA_APBT0_IDM_RESET_CONTROL),
+			      0x0);
+		mmio_setbits_32(SATA_APBT_IDM_PORT_REG(sata_port,
+					SATA_APBT0_IDM_IO_CONTROL_DIRECT),
+				IO_CONTROL_DIRECT_CLK_ENABLE);
+		mmio_write_32(SATA_IDM_PORT_REG(sata_port,
+						SATA0_IDM_RESET_CONTROL),
+			      0x0);
+
+		mmio_setbits_32(SATA_PORT_REG(sata_port, SATA_CORE_MEM_CTRL),
+				SATA_CORE_MEM_CTRL_ARRPOWERONIN);
+		mmio_setbits_32(SATA_PORT_REG(sata_port, SATA_CORE_MEM_CTRL),
+				SATA_CORE_MEM_CTRL_ARRPOWEROKIN);
+		mmio_setbits_32(SATA_PORT_REG(sata_port, SATA_CORE_MEM_CTRL),
+				SATA_CORE_MEM_CTRL_POWERONIN);
+		mmio_setbits_32(SATA_PORT_REG(sata_port, SATA_CORE_MEM_CTRL),
+				SATA_CORE_MEM_CTRL_POWEROKIN);
+		mmio_clrbits_32(SATA_PORT_REG(sata_port, SATA_CORE_MEM_CTRL),
+				SATA_CORE_MEM_CTRL_ISO);
+
+		mmio_clrbits_32(SATA_PORT_REG(sata_port,
+					      SATA_SATA_TOP_CTRL_BUS_CTRL),
+				(DMA_DESCR_ENDIAN_CTRL | DMA_DATA_ENDIAN_CTRL));
+	}
+
+	mmio_setbits_32(NIC400_SATA_NOC_SECURITY1, SATA_NOC_SECURITY1_FIELD);
+	mmio_setbits_32(NIC400_SATA_NOC_SECURITY2, SATA_NOC_SECURITY2_FIELD);
+	mmio_setbits_32(NIC400_SATA_NOC_SECURITY3, SATA_NOC_SECURITY3_FIELD);
+	mmio_setbits_32(NIC400_SATA_NOC_SECURITY4, SATA_NOC_SECURITY4_FIELD);
+	mmio_setbits_32(NIC400_SATA_NOC_SECURITY5, SATA_NOC_SECURITY5_FIELD);
+	mmio_setbits_32(NIC400_SATA_NOC_SECURITY6, SATA_NOC_SECURITY6_FIELD);
+	mmio_setbits_32(NIC400_SATA_NOC_SECURITY7, SATA_NOC_SECURITY7_FIELD);
+	mmio_setbits_32(NIC400_SATA_NOC_SECURITY8, SATA_NOC_SECURITY8_FIELD);
+	mmio_setbits_32(NIC400_SATA_NOC_SECURITY9, SATA_NOC_SECURITY9_FIELD);
+
+	INFO("sata init done\n");
+}
+#else
+static void poweroff_sata_pll(void)
+{
+	/*
+	 * SATA subsystem is clocked by LCPLL0 which is enabled by
+	 * default by bootrom. Poweroff the PLL if SATA is not used
+	 */
+
+	/* enable isolation */
+	mmio_setbits_32(CRMU_AON_CTRL1,
+			BIT(CRMU_AON_CTRL1__LCPLL0_ISO_IN));
+
+	/* Power off the SATA PLL/LDO */
+	mmio_clrbits_32(CRMU_AON_CTRL1,
+			(BIT(CRMU_AON_CTRL1__LCPLL0_PWRON_LDO) |
+			 BIT(CRMU_AON_CTRL1__LCPLL0_PWR_ON)));
+}
+#endif
+
+#ifdef USE_AMAC
+#ifdef EMULATION_SETUP
+#define ICFG_AMAC_STRAP_CONFIG		(HSLS_ICFG_REGS_BASE + 0xa5c)
+#define ICFG_AMAC_STRAP_DLL_BYPASS	(1 << 2)
+#endif
+#define ICFG_AMAC_MAC_CTRL_REG		(HSLS_ICFG_REGS_BASE + 0xa6c)
+#define ICFG_AMAC_MAC_FULL_DUPLEX	(1 << 1)
+#define ICFG_AMAC_RGMII_PHY_CONFIG	(HSLS_ICFG_REGS_BASE + 0xa60)
+#define ICFG_AMAC_SID_CONTROL		(HSLS_ICFG_REGS_BASE + 0xb10)
+#define ICFG_AMAC_SID_SHIFT		5
+#define ICFG_AMAC_SID_AWADDR_OFFSET	0x0
+#define ICFG_AMAC_SID_ARADDR_OFFSET	0x4
+#define AMAC_RPHY_1000_DATARATE		(1 << 20)
+#define AMAC_RPHY_FULL_DUPLEX		(1 << 5)
+#define AMAC_RPHY_SPEED_OFFSET		2
+#define AMAC_RPHY_SPEED_MASK		(7 << AMAC_RPHY_SPEED_OFFSET)
+#define AMAC_RPHY_1G_SPEED		(2 << AMAC_RPHY_SPEED_OFFSET)
+#define ICFG_AMAC_MEM_PWR_CTRL		(HSLS_ICFG_REGS_BASE + 0xa68)
+#define AMAC_ISO			BIT(9)
+#define AMAC_STDBY			BIT(8)
+#define AMAC_ARRPOWEROKIN		BIT(7)
+#define AMAC_ARRPOWERONIN		BIT(6)
+#define AMAC_POWEROKIN			BIT(5)
+#define AMAC_POWERONIN			BIT(4)
+
+#define AMAC_IDM0_IO_CONTROL_DIRECT	(HSLS_IDM_REGS_BASE + 0x4408)
+#define AMAC_IDM0_ARCACHE_OFFSET	16
+#define AMAC_IDM0_AWCACHE_OFFSET	7
+#define AMAC_IDM0_ARCACHE_MASK		(0xF << AMAC_IDM0_ARCACHE_OFFSET)
+#define AMAC_IDM0_AWCACHE_MASK		(0xF << AMAC_IDM0_AWCACHE_OFFSET)
+/* ARCACHE - AWCACHE is 0xB7 for write-back no allocate */
+#define AMAC_IDM0_ARCACHE_VAL		(0xb << AMAC_IDM0_ARCACHE_OFFSET)
+#define AMAC_IDM0_AWCACHE_VAL		(0x7 << AMAC_IDM0_AWCACHE_OFFSET)
+
+static void brcm_stingray_amac_init(void)
+{
+	unsigned int val;
+	uintptr_t icfg_amac_sid = ICFG_AMAC_SID_CONTROL;
+
+	VERBOSE("amac init start\n");
+
+	val = SR_SID_VAL(0x3, 0x0, 0x4) << ICFG_AMAC_SID_SHIFT;
+	mmio_write_32(icfg_amac_sid + ICFG_AMAC_SID_AWADDR_OFFSET, val);
+	mmio_write_32(icfg_amac_sid + ICFG_AMAC_SID_ARADDR_OFFSET, val);
+
+	mmio_setbits_32(ICFG_AMAC_MEM_PWR_CTRL, AMAC_ARRPOWEROKIN);
+	mmio_setbits_32(ICFG_AMAC_MEM_PWR_CTRL, AMAC_ARRPOWERONIN);
+	mmio_setbits_32(ICFG_AMAC_MEM_PWR_CTRL, AMAC_POWEROKIN);
+	mmio_setbits_32(ICFG_AMAC_MEM_PWR_CTRL, AMAC_POWERONIN);
+	mmio_clrbits_32(ICFG_AMAC_MEM_PWR_CTRL, AMAC_ISO);
+	mmio_write_32(APBR_IDM_RESET_CONTROL, 0x0);
+	mmio_clrsetbits_32(ICFG_AMAC_RGMII_PHY_CONFIG, AMAC_RPHY_SPEED_MASK,
+				AMAC_RPHY_1G_SPEED); /*1 Gbps line rate*/
+	/* 1000 datarate set */
+	mmio_setbits_32(ICFG_AMAC_RGMII_PHY_CONFIG, AMAC_RPHY_1000_DATARATE);
+	/* full duplex */
+	mmio_setbits_32(ICFG_AMAC_RGMII_PHY_CONFIG, AMAC_RPHY_FULL_DUPLEX);
+#ifdef EMULATION_SETUP
+	/* DLL bypass */
+	mmio_setbits_32(ICFG_AMAC_STRAP_CONFIG, ICFG_AMAC_STRAP_DLL_BYPASS);
+#endif
+	/* serdes full duplex */
+	mmio_setbits_32(ICFG_AMAC_MAC_CTRL_REG, ICFG_AMAC_MAC_FULL_DUPLEX);
+	mmio_clrsetbits_32(AMAC_IDM0_IO_CONTROL_DIRECT, AMAC_IDM0_ARCACHE_MASK,
+				AMAC_IDM0_ARCACHE_VAL);
+	mmio_clrsetbits_32(AMAC_IDM0_IO_CONTROL_DIRECT, AMAC_IDM0_AWCACHE_MASK,
+				AMAC_IDM0_AWCACHE_VAL);
+	INFO("amac init done\n");
+}
+#endif    /* USE_AMAC */
+
+static void brcm_stingray_pka_meminit(void)
+{
+	uintptr_t icfg_mem_ctrl = ICFG_PKA_MEM_PWR_CTRL;
+
+	VERBOSE("pka meminit start\n");
+
+	VERBOSE(" - arrpoweron\n");
+	mmio_setbits_32(icfg_mem_ctrl,
+			ICFG_PKA_MEM_PWR_CTRL__ARRPOWERONIN);
+	while (!(mmio_read_32(icfg_mem_ctrl) &
+		 ICFG_PKA_MEM_PWR_CTRL__ARRPOWERONOUT))
+		;
+
+	VERBOSE(" - arrpowerok\n");
+	mmio_setbits_32(icfg_mem_ctrl,
+			ICFG_PKA_MEM_PWR_CTRL__ARRPOWEROKIN);
+	while (!(mmio_read_32(icfg_mem_ctrl) &
+		 ICFG_PKA_MEM_PWR_CTRL__ARRPOWEROKOUT))
+		;
+
+	VERBOSE(" - poweron\n");
+	mmio_setbits_32(icfg_mem_ctrl,
+			ICFG_PKA_MEM_PWR_CTRL__POWERONIN);
+	while (!(mmio_read_32(icfg_mem_ctrl) &
+		 ICFG_PKA_MEM_PWR_CTRL__POWERONOUT))
+		;
+
+	VERBOSE(" - powerok\n");
+	mmio_setbits_32(icfg_mem_ctrl,
+			ICFG_PKA_MEM_PWR_CTRL__POWEROKIN);
+	while (!(mmio_read_32(icfg_mem_ctrl) &
+		 ICFG_PKA_MEM_PWR_CTRL__POWEROKOUT))
+		;
+
+	/* Wait sometime */
+	mdelay(1);
+
+	VERBOSE(" - remove isolation\n");
+	mmio_clrbits_32(icfg_mem_ctrl, ICFG_PKA_MEM_PWR_CTRL__ISO);
+
+	INFO("pka meminit done\n");
+}
+
+static void brcm_stingray_smmu_init(void)
+{
+	unsigned int val;
+	uintptr_t smmu_base = SMMU_BASE;
+
+	VERBOSE("smmu init start\n");
+
+	/* Configure SCR0 */
+	VERBOSE(" - configure scr0\n");
+	val = mmio_read_32(smmu_base + 0x0);
+	val |= (0x1 << 12);
+	mmio_write_32(smmu_base + 0x0, val);
+
+	/* Reserve context banks for secure masters */
+	arm_smmu_reserve_secure_cntxt();
+
+	/* Print configuration */
+	VERBOSE(" - scr0=0x%x scr1=0x%x scr2=0x%x\n",
+		mmio_read_32(smmu_base + 0x0),
+		mmio_read_32(smmu_base + 0x4),
+		mmio_read_32(smmu_base + 0x8));
+
+	VERBOSE(" - idr0=0x%x idr1=0x%x idr2=0x%x\n",
+		mmio_read_32(smmu_base + 0x20),
+		mmio_read_32(smmu_base + 0x24),
+		mmio_read_32(smmu_base + 0x28));
+
+	VERBOSE(" - idr3=0x%x idr4=0x%x idr5=0x%x\n",
+		mmio_read_32(smmu_base + 0x2c),
+		mmio_read_32(smmu_base + 0x30),
+		mmio_read_32(smmu_base + 0x34));
+
+	VERBOSE(" - idr6=0x%x idr7=0x%x\n",
+		mmio_read_32(smmu_base + 0x38),
+		mmio_read_32(smmu_base + 0x3c));
+
+	INFO("smmu init done\n");
+}
+
+static void brcm_stingray_dma_pl330_meminit(void)
+{
+	uintptr_t icfg_mem_ctrl = ICFG_DMAC_MEM_PWR_CTRL;
+
+	VERBOSE("dmac meminit start\n");
+
+	VERBOSE(" - arrpoweron\n");
+	mmio_setbits_32(icfg_mem_ctrl,
+			ICFG_DMAC_MEM_PWR_CTRL__ARRPOWERONIN);
+	while (!(mmio_read_32(icfg_mem_ctrl) &
+		 ICFG_DMAC_MEM_PWR_CTRL__ARRPOWERONOUT))
+		;
+
+	VERBOSE(" - arrpowerok\n");
+	mmio_setbits_32(icfg_mem_ctrl,
+			ICFG_DMAC_MEM_PWR_CTRL__ARRPOWEROKIN);
+	while (!(mmio_read_32(icfg_mem_ctrl) &
+		 ICFG_DMAC_MEM_PWR_CTRL__ARRPOWEROKOUT))
+		;
+
+	VERBOSE(" - poweron\n");
+	mmio_setbits_32(icfg_mem_ctrl,
+			ICFG_DMAC_MEM_PWR_CTRL__POWERONIN);
+	while (!(mmio_read_32(icfg_mem_ctrl) &
+		 ICFG_DMAC_MEM_PWR_CTRL__POWERONOUT))
+		;
+
+	VERBOSE(" - powerok\n");
+	mmio_setbits_32(icfg_mem_ctrl,
+			ICFG_DMAC_MEM_PWR_CTRL__POWEROKIN);
+	while (!(mmio_read_32(icfg_mem_ctrl) &
+		 ICFG_DMAC_MEM_PWR_CTRL__POWEROKOUT))
+		;
+
+	/* Wait sometime */
+	mdelay(1);
+
+	VERBOSE(" - remove isolation\n");
+	mmio_clrbits_32(icfg_mem_ctrl, ICFG_DMAC_MEM_PWR_CTRL__ISO);
+
+	INFO("dmac meminit done\n");
+}
+
+/* program the crmu access ranges for allowing non sec access*/
+static void brcm_stingray_crmu_access_init(void)
+{
+	/* Enable 0x6641c001 - 0x6641c701 for non secure access */
+	mmio_write_32(CRMU_CORE_ADDR_RANGE0_LOW, 0x6641c001);
+	mmio_write_32(CRMU_CORE_ADDR_RANGE0_LOW + 0x4, 0x6641c701);
+
+	/* Enable 0x6641d001 - 0x66424b01 for non secure access */
+	mmio_write_32(CRMU_CORE_ADDR_RANGE1_LOW, 0x6641d001);
+	mmio_write_32(CRMU_CORE_ADDR_RANGE1_LOW + 0x4, 0x66424b01);
+
+	/* Enable 0x66425001 - 0x66425f01 for non secure access */
+	mmio_write_32(CRMU_CORE_ADDR_RANGE2_LOW, 0x66425001);
+	mmio_write_32(CRMU_CORE_ADDR_RANGE2_LOW + 0x4, 0x66425f01);
+
+	INFO("crmu access init done\n");
+}
+
+static void brcm_stingray_scr_init(void)
+{
+	unsigned int val;
+	uintptr_t scr_base = SCR_BASE;
+	unsigned int clr_mask = SCR_AXCACHE_CONFIG_MASK;
+	unsigned int set_mask = SCR_TBUX_AXCACHE_CONFIG;
+
+	VERBOSE("scr init start\n");
+
+	/* awdomain=0x1 and ardomain=0x1 */
+	mmio_clrsetbits_32(scr_base + 0x0, clr_mask, set_mask);
+	val = mmio_read_32(scr_base + 0x0);
+	VERBOSE(" - set tbu0_config=0x%x\n", val);
+
+	/* awdomain=0x1 and ardomain=0x1 */
+	mmio_clrsetbits_32(scr_base + 0x4, clr_mask, set_mask);
+	val = mmio_read_32(scr_base + 0x4);
+	VERBOSE(" - set tbu1_config=0x%x\n", val);
+
+	/* awdomain=0x1 and ardomain=0x1 */
+	mmio_clrsetbits_32(scr_base + 0x8, clr_mask, set_mask);
+	val = mmio_read_32(scr_base + 0x8);
+	VERBOSE(" - set tbu2_config=0x%x\n", val);
+
+	/* awdomain=0x1 and ardomain=0x1 */
+	mmio_clrsetbits_32(scr_base + 0xc, clr_mask, set_mask);
+	val = mmio_read_32(scr_base + 0xc);
+	VERBOSE(" - set tbu3_config=0x%x\n", val);
+
+	/* awdomain=0x1 and ardomain=0x1 */
+	mmio_clrsetbits_32(scr_base + 0x10, clr_mask, set_mask);
+	val = mmio_read_32(scr_base + 0x10);
+	VERBOSE(" - set tbu4_config=0x%x\n", val);
+
+	/* awdomain=0x0 and ardomain=0x0 */
+	mmio_clrbits_32(scr_base + 0x14, clr_mask);
+	val = mmio_read_32(scr_base + 0x14);
+	VERBOSE(" - set gic_config=0x%x\n", val);
+
+	INFO("scr init done\n");
+}
+
+static void brcm_stingray_hsls_tzpcprot_init(void)
+{
+	unsigned int val;
+	uintptr_t tzpcdecprot_base = HSLS_TZPC_BASE;
+
+	VERBOSE("hsls tzpcprot init start\n");
+
+	/* Treat third-party masters as non-secured */
+	val = 0;
+	val |= BIT(6); /* SDIO1 */
+	val |= BIT(5); /* SDIO0 */
+	val |= BIT(0); /* AMAC */
+	mmio_write_32(tzpcdecprot_base + 0x810, val);
+
+	/* Print TZPC decode status registers */
+	VERBOSE(" - tzpcdecprot0=0x%x\n",
+		mmio_read_32(tzpcdecprot_base + 0x800));
+
+	VERBOSE(" - tzpcdecprot1=0x%x\n",
+		mmio_read_32(tzpcdecprot_base + 0x80c));
+
+	INFO("hsls tzpcprot init done\n");
+}
+
+#ifdef USE_I2S
+#define ICFG_AUDIO_POWER_CTRL			(HSLS_ICFG_REGS_BASE + 0xaa8)
+#define ICFG_AUDIO_POWER_CTRL__POWERONIN	BIT(0)
+#define ICFG_AUDIO_POWER_CTRL__POWEROKIN	BIT(1)
+#define ICFG_AUDIO_POWER_CTRL__ARRPOWERONIN	BIT(2)
+#define ICFG_AUDIO_POWER_CTRL__ARRPOWEROKIN	BIT(3)
+#define ICFG_AUDIO_POWER_CTRL__POWERONOUT	BIT(4)
+#define ICFG_AUDIO_POWER_CTRL__POWEROKOUT	BIT(5)
+#define ICFG_AUDIO_POWER_CTRL__ARRPOWERONOUT	BIT(6)
+#define ICFG_AUDIO_POWER_CTRL__ARRPOWEROKOUT	BIT(7)
+#define ICFG_AUDIO_POWER_CTRL__ISO		BIT(8)
+#define ICFG_AUDIO_SID_CONTROL			(HSLS_ICFG_REGS_BASE + 0xaf8)
+#define ICFG_AUDIO_SID_SHIFT			5
+#define ICFG_AUDIO_SID_AWADDR_OFFSET		0x0
+#define ICFG_AUDIO_SID_ARADDR_OFFSET		0x4
+
+#define I2S_RESET_CONTROL        (HSLS_IDM_REGS_BASE + 0x1800)
+#define I2S_IDM_IO_CONTROL       (HSLS_IDM_REGS_BASE + 0x1408)
+#define IO_CONTROL_CLK_ENABLE    BIT(0)
+#define I2S_IDM0_ARCACHE_OFFSET  16
+#define I2S_IDM0_AWCACHE_OFFSET  20
+#define I2S_IDM0_ARCACHE_MASK    (0xF << I2S_IDM0_ARCACHE_OFFSET)
+#define I2S_IDM0_AWCACHE_MASK    (0xF << I2S_IDM0_AWCACHE_OFFSET)
+/* ARCACHE - AWCACHE is 0x22 Normal Non-cacheable Non-bufferable. */
+#define I2S_IDM0_ARCACHE_VAL     (0x2 << I2S_IDM0_ARCACHE_OFFSET)
+#define I2S_IDM0_AWCACHE_VAL     (0x2 << I2S_IDM0_AWCACHE_OFFSET)
+
+static void brcm_stingray_audio_init(void)
+{
+	unsigned int val;
+	uintptr_t icfg_mem_ctrl = ICFG_AUDIO_POWER_CTRL;
+	uintptr_t icfg_audio_sid = ICFG_AUDIO_SID_CONTROL;
+
+	mmio_write_32(I2S_RESET_CONTROL, 0x0);
+
+	mmio_clrsetbits_32(I2S_IDM_IO_CONTROL, I2S_IDM0_ARCACHE_MASK,
+			   I2S_IDM0_ARCACHE_VAL);
+
+	mmio_clrsetbits_32(I2S_IDM_IO_CONTROL, I2S_IDM0_AWCACHE_MASK,
+			   I2S_IDM0_AWCACHE_VAL);
+
+	mmio_setbits_32(I2S_IDM_IO_CONTROL, IO_CONTROL_CLK_ENABLE);
+
+	VERBOSE("audio meminit start\n");
+
+	VERBOSE(" - configure stream_id = 0x6001\n");
+	val = SR_SID_VAL(0x3, 0x0, 0x1) << ICFG_AUDIO_SID_SHIFT;
+	mmio_write_32(icfg_audio_sid + ICFG_AUDIO_SID_AWADDR_OFFSET, val);
+	mmio_write_32(icfg_audio_sid + ICFG_AUDIO_SID_ARADDR_OFFSET, val);
+
+	VERBOSE(" - arrpoweron\n");
+	mmio_setbits_32(icfg_mem_ctrl,
+			ICFG_AUDIO_POWER_CTRL__ARRPOWERONIN);
+	while (!(mmio_read_32(icfg_mem_ctrl) &
+		 ICFG_AUDIO_POWER_CTRL__ARRPOWERONOUT))
+		;
+
+	VERBOSE(" - arrpowerok\n");
+	mmio_setbits_32(icfg_mem_ctrl,
+			ICFG_AUDIO_POWER_CTRL__ARRPOWEROKIN);
+	while (!(mmio_read_32(icfg_mem_ctrl) &
+		 ICFG_AUDIO_POWER_CTRL__ARRPOWEROKOUT))
+		;
+
+	VERBOSE(" - poweron\n");
+	mmio_setbits_32(icfg_mem_ctrl,
+			ICFG_AUDIO_POWER_CTRL__POWERONIN);
+	while (!(mmio_read_32(icfg_mem_ctrl) &
+		 ICFG_AUDIO_POWER_CTRL__POWERONOUT))
+		;
+
+	VERBOSE(" - powerok\n");
+	mmio_setbits_32(icfg_mem_ctrl,
+			ICFG_AUDIO_POWER_CTRL__POWEROKIN);
+	while (!(mmio_read_32(icfg_mem_ctrl) &
+		 ICFG_AUDIO_POWER_CTRL__POWEROKOUT))
+		;
+
+	/* Wait sometime */
+	mdelay(1);
+
+	VERBOSE(" - remove isolation\n");
+	mmio_clrbits_32(icfg_mem_ctrl, ICFG_AUDIO_POWER_CTRL__ISO);
+
+	INFO("audio meminit done\n");
+}
+#endif    /* USE_I2S */
+
+/*
+ * These defines do not match the regfile but they are renamed in a way such
+ * that they are much more readible
+ */
+
+#define SCR_GPV_SMMU_NS			(SCR_GPV_BASE + 0x28)
+#define SCR_GPV_GIC500_NS		(SCR_GPV_BASE + 0x34)
+#define HSLS_GPV_NOR_S0_NS		(HSLS_GPV_BASE + 0x14)
+#define HSLS_GPV_IDM1_NS		(HSLS_GPV_BASE + 0x18)
+#define HSLS_GPV_IDM2_NS		(HSLS_GPV_BASE + 0x1c)
+#define HSLS_SDIO0_SLAVE_NS		(HSLS_GPV_BASE + 0x20)
+#define HSLS_SDIO1_SLAVE_NS		(HSLS_GPV_BASE + 0x24)
+#define HSLS_GPV_APBY_NS		(HSLS_GPV_BASE + 0x2c)
+#define HSLS_GPV_APBZ_NS		(HSLS_GPV_BASE + 0x30)
+#define HSLS_GPV_APBX_NS		(HSLS_GPV_BASE + 0x34)
+#define HSLS_GPV_APBS_NS		(HSLS_GPV_BASE + 0x38)
+#define HSLS_GPV_QSPI_S0_NS		(HSLS_GPV_BASE + 0x68)
+#define HSLS_GPV_APBR_NS		(HSLS_GPV_BASE + 0x6c)
+#define FS4_CRYPTO_GPV_RM_SLAVE_NS	(FS4_CRYPTO_GPV_BASE + 0x8)
+#define FS4_CRYPTO_GPV_APB_SWITCH_NS	(FS4_CRYPTO_GPV_BASE + 0xc)
+#define FS4_RAID_GPV_RM_SLAVE_NS	(FS4_RAID_GPV_BASE + 0x8)
+#define FS4_RAID_GPV_APB_SWITCH_NS	(FS4_RAID_GPV_BASE + 0xc)
+#define FS4_CRYPTO_IDM_NS		(NIC400_FS_NOC_ROOT + 0x1c)
+#define FS4_RAID_IDM_NS			(NIC400_FS_NOC_ROOT + 0x28)
+
+#define FS4_CRYPTO_RING_COUNT          32
+#define FS4_CRYPTO_DME_COUNT           10
+#define FS4_CRYPTO_AE_COUNT            10
+#define FS4_CRYPTO_START_STREAM_ID     0x4000
+#define FS4_CRYPTO_MSI_DEVICE_ID       0x4100
+
+#define FS4_RAID_RING_COUNT            32
+#define FS4_RAID_DME_COUNT             8
+#define FS4_RAID_AE_COUNT              8
+#define FS4_RAID_START_STREAM_ID       0x4200
+#define FS4_RAID_MSI_DEVICE_ID         0x4300
+
+#define FS6_PKI_AXI_SLAVE_NS \
+		(NIC400_FS_NOC_ROOT + NIC400_FS_NOC_SECURITY2_OFFSET)
+
+#define FS6_PKI_AE_DME_APB_NS \
+		(NIC400_FS_NOC_ROOT + NIC400_FS_NOC_SECURITY7_OFFSET)
+#define FS6_PKI_IDM_IO_CONTROL_DIRECT	0x0
+#define FS6_PKI_IDM_RESET_CONTROL	0x0
+#define FS6_PKI_RING_COUNT		32
+#define FS6_PKI_DME_COUNT		1
+#define FS6_PKI_AE_COUNT		4
+#define FS6_PKI_START_STREAM_ID		0x4000
+#define FS6_PKI_MSI_DEVICE_ID		0x4100
+
+static void brcm_stingray_security_init(void)
+{
+	unsigned int val;
+
+	val = mmio_read_32(SCR_GPV_SMMU_NS);
+	val |= BIT(0);				/* SMMU NS = 1 */
+	mmio_write_32(SCR_GPV_SMMU_NS, val);
+
+	val = mmio_read_32(SCR_GPV_GIC500_NS);
+	val |= BIT(0);				/* GIC-500 NS = 1 */
+	mmio_write_32(SCR_GPV_GIC500_NS, val);
+
+	val = mmio_read_32(HSLS_GPV_NOR_S0_NS);
+	val |= BIT(0);				/* NOR SLAVE NS = 1 */
+	mmio_write_32(HSLS_GPV_NOR_S0_NS, val);
+
+	val = mmio_read_32(HSLS_GPV_IDM1_NS);
+	val |= BIT(0);				/* DMA IDM NS = 1 */
+	val |= BIT(1);				/* I2S IDM NS = 1 */
+	val |= BIT(2);				/* AMAC IDM NS = 1 */
+	val |= BIT(3);				/* SDIO0 IDM NS = 1 */
+	val |= BIT(4);				/* SDIO1 IDM NS = 1 */
+	val |= BIT(5);				/* DS_3 IDM NS = 1 */
+	mmio_write_32(HSLS_GPV_IDM1_NS, val);
+
+	val = mmio_read_32(HSLS_GPV_IDM2_NS);
+	val |= BIT(2);				/* QSPI IDM NS = 1 */
+	val |= BIT(1);				/* NOR IDM NS = 1 */
+	val |= BIT(0);				/* NAND IDM NS = 1 */
+	mmio_write_32(HSLS_GPV_IDM2_NS, val);
+
+	val = mmio_read_32(HSLS_GPV_APBY_NS);
+	val |= BIT(10);				/* I2S NS = 1 */
+	val |= BIT(4);				/* IOPAD NS = 1 */
+	val |= 0xf;				/* UARTx NS = 1 */
+	mmio_write_32(HSLS_GPV_APBY_NS, val);
+
+	val = mmio_read_32(HSLS_GPV_APBZ_NS);
+	val |= BIT(2);			/* RNG NS = 1 */
+	mmio_write_32(HSLS_GPV_APBZ_NS, val);
+
+	val = mmio_read_32(HSLS_GPV_APBS_NS);
+	val |= 0x3;				/* SPIx NS = 1 */
+	mmio_write_32(HSLS_GPV_APBS_NS, val);
+
+	val = mmio_read_32(HSLS_GPV_APBR_NS);
+	val |= BIT(7);				/* QSPI APB NS = 1 */
+	val |= BIT(6);				/* NAND APB NS = 1 */
+	val |= BIT(5);				/* NOR APB NS = 1 */
+	val |= BIT(4);				/* AMAC APB NS = 1 */
+	val |= BIT(1);				/* DMA S1 APB NS = 1 */
+	mmio_write_32(HSLS_GPV_APBR_NS, val);
+
+	val = mmio_read_32(HSLS_SDIO0_SLAVE_NS);
+	val |= BIT(0);				/* SDIO0 NS = 1 */
+	mmio_write_32(HSLS_SDIO0_SLAVE_NS, val);
+
+	val = mmio_read_32(HSLS_SDIO1_SLAVE_NS);
+	val |= BIT(0);				/* SDIO1 NS = 1 */
+	mmio_write_32(HSLS_SDIO1_SLAVE_NS, val);
+
+	val = mmio_read_32(HSLS_GPV_APBX_NS);
+	val |= BIT(14);				/* SMBUS1 NS = 1 */
+	val |= BIT(13);				/* GPIO NS = 1 */
+	val |= BIT(12);				/* WDT NS = 1 */
+	val |= BIT(11);				/* SMBUS0 NS = 1 */
+	val |= BIT(10);				/* Timer7 NS = 1 */
+	val |= BIT(9);				/* Timer6 NS = 1 */
+	val |= BIT(8);				/* Timer5 NS = 1 */
+	val |= BIT(7);				/* Timer4 NS = 1 */
+	val |= BIT(6);				/* Timer3 NS = 1 */
+	val |= BIT(5);				/* Timer2 NS = 1 */
+	val |= BIT(4);				/* Timer1 NS = 1 */
+	val |= BIT(3);				/* Timer0 NS = 1 */
+	val |= BIT(2);				/* MDIO NS = 1 */
+	val |= BIT(1);				/* PWM NS = 1 */
+	mmio_write_32(HSLS_GPV_APBX_NS, val);
+
+	val = mmio_read_32(HSLS_GPV_QSPI_S0_NS);
+	val |= BIT(0);				/* QSPI NS = 1 */
+	mmio_write_32(HSLS_GPV_QSPI_S0_NS, val);
+
+#ifdef USE_FS4
+	val = 0x1;				/* FS4 Crypto rm_slave */
+	mmio_write_32(FS4_CRYPTO_GPV_RM_SLAVE_NS, val);
+	val = 0x1;				/* FS4 Crypto apb_switch */
+	mmio_write_32(FS4_CRYPTO_GPV_APB_SWITCH_NS, val);
+
+	val = 0x1;				/* FS4 Raid rm_slave */
+	mmio_write_32(FS4_RAID_GPV_RM_SLAVE_NS, val);
+	val = 0x1;				/* FS4 Raid apb_switch */
+	mmio_write_32(FS4_RAID_GPV_APB_SWITCH_NS, val);
+
+	val = 0x1;				/* FS4 Crypto IDM */
+	mmio_write_32(FS4_CRYPTO_IDM_NS, val);
+	val = 0x1;				/* FS4 RAID IDM */
+	mmio_write_32(FS4_RAID_IDM_NS, val);
+#endif
+
+#ifdef BL31_CCN_NONSECURE
+	/* Enable non-secure access to CCN registers */
+	mmio_write_32(OLY_MN_REGISTERS_NODE0_SECURE_ACCESS, 0x1);
+#endif
+
+#ifdef DDR_CTRL_PHY_NONSECURE
+	mmio_write_32(SCR_NOC_DDR_REGISTER_ACCESS, 0x1);
+#endif
+
+	paxc_mhb_ns_init();
+
+	/* unlock scr idm for non secure access */
+	mmio_write_32(SCR_NOC_SECURITY0, 0xffffffff);
+
+	INFO("security init done\r\n");
+}
+
+void brcm_gpio_pad_ns_init(void)
+{
+	/* configure all GPIO pads for non secure world access*/
+	mmio_write_32(GPIO_S_CNTRL_REG, 0xffffffff); /* 128-140 gpio pads */
+	mmio_write_32(GPIO_S_CNTRL_REG + 0x4, 0xffffffff); /* 96-127 gpio pad */
+	mmio_write_32(GPIO_S_CNTRL_REG + 0x8, 0xffffffff); /* 64-95 gpio pad */
+	mmio_write_32(GPIO_S_CNTRL_REG + 0xc, 0xffffffff); /* 32-63 gpio pad */
+	mmio_write_32(GPIO_S_CNTRL_REG + 0x10, 0xffffffff); /* 0-31 gpio pad */
+}
+
+#ifndef USE_DDR
+static void brcm_stingray_sram_ns_init(void)
+{
+	uintptr_t sram_root = TZC400_FS_SRAM_ROOT;
+	uintptr_t noc_root = NIC400_FS_NOC_ROOT;
+
+	mmio_write_32(sram_root + GATE_KEEPER_OFFSET, 1);
+	mmio_write_32(sram_root + REGION_ATTRIBUTES_0_OFFSET, 0xc0000000);
+	mmio_write_32(sram_root + REGION_ID_ACCESS_0_OFFSET, 0x00010001);
+	mmio_write_32(noc_root + NIC400_FS_NOC_SECURITY4_OFFSET, 0x1);
+	INFO(" stingray sram ns init done.\n");
+}
+#endif
+
+static void ccn_pre_init(void)
+{
+	/*
+	 * Set WFC bit of RN-I nodes where FS4 is connected.
+	 * This is required inorder to wait for read/write requests
+	 * completion acknowledgment. Otherwise FS4 Ring Manager is
+	 * getting stale data because of re-ordering of read/write
+	 * requests at CCN level
+	 */
+	mmio_setbits_32(OLY_RNI3PDVM_REGISTERS_NODE8_AUX_CTL,
+			OLY_RNI3PDVM_REGISTERS_NODE8_AUX_CTL_WFC);
+}
+
+static void ccn_post_init(void)
+{
+	mmio_setbits_32(OLY_HNI_REGISTERS_NODE0_PCIERC_RNI_NODEID_LIST,
+			SRP_RNI_PCIE_CONNECTED);
+	mmio_setbits_32(OLY_HNI_REGISTERS_NODE0_SA_AUX_CTL,
+			SA_AUX_CTL_SER_DEVNE_WR);
+
+	mmio_clrbits_32(OLY_HNI_REGISTERS_NODE0_POS_CONTROL,
+			POS_CONTROL_HNI_POS_EN);
+	mmio_clrbits_32(OLY_HNI_REGISTERS_NODE0_SA_AUX_CTL,
+			SA_AUX_CTL_POS_EARLY_WR_COMP_EN);
+}
+
+#ifndef BL31_BOOT_PRELOADED_SCP
+static void crmu_init(void)
+{
+	/*
+	 * Configure CRMU for using SMMU
+	 */
+
+	/*Program CRMU Stream ID */
+	mmio_write_32(CRMU_MASTER_AXI_ARUSER_CONFIG,
+			(CRMU_STREAM_ID << CRMU_SID_SHIFT));
+	mmio_write_32(CRMU_MASTER_AXI_AWUSER_CONFIG,
+			(CRMU_STREAM_ID << CRMU_SID_SHIFT));
+
+	/* Create Identity mapping */
+	arm_smmu_create_identity_map(DOMAIN_CRMU);
+
+	/* Enable Client Port for Secure Masters*/
+	arm_smmu_enable_secure_client_port();
+}
+#endif
+
+static void brcm_fsx_init(void)
+{
+#if defined(USE_FS4) && defined(USE_FS6)
+	#error "USE_FS4 and USE_FS6 should not be used together"
+#endif
+
+#ifdef USE_FS4
+	fsx_init(eFS4_CRYPTO, FS4_CRYPTO_RING_COUNT, FS4_CRYPTO_DME_COUNT,
+		FS4_CRYPTO_AE_COUNT, FS4_CRYPTO_START_STREAM_ID,
+		FS4_CRYPTO_MSI_DEVICE_ID, FS4_CRYPTO_IDM_IO_CONTROL_DIRECT,
+		FS4_CRYPTO_IDM_RESET_CONTROL, FS4_CRYPTO_BASE,
+		FS4_CRYPTO_DME_BASE);
+
+	fsx_init(eFS4_RAID, FS4_RAID_RING_COUNT, FS4_RAID_DME_COUNT,
+		FS4_RAID_AE_COUNT, FS4_RAID_START_STREAM_ID,
+		FS4_RAID_MSI_DEVICE_ID, FS4_RAID_IDM_IO_CONTROL_DIRECT,
+		FS4_RAID_IDM_RESET_CONTROL, FS4_RAID_BASE,
+		FS4_RAID_DME_BASE);
+
+	fsx_meminit("raid",
+		FS4_RAID_IDM_IO_CONTROL_DIRECT,
+		FS4_RAID_IDM_IO_STATUS);
+#endif
+}
+
+static void bcm_bl33_pass_info(void)
+{
+	struct bl33_info *info = (struct bl33_info *)BL33_SHARED_DDR_BASE;
+
+	if (sizeof(*info) > BL33_SHARED_DDR_SIZE)
+		WARN("bl33 shared area not reserved\n");
+
+	info->version = BL33_INFO_VERSION;
+	info->chip.chip_id = PLAT_CHIP_ID_GET;
+	info->chip.rev_id = PLAT_CHIP_REV_GET;
+}
+
+DEFINE_RENAME_SYSREG_RW_FUNCS(l2ctlr_el1, CORTEX_A72_L2CTLR_EL1)
+
+void plat_bcm_bl31_early_platform_setup(void *from_bl2,
+					bl_params_t *plat_params_from_bl2)
+{
+#ifdef BL31_BOOT_PRELOADED_SCP
+	image_info_t scp_image_info;
+
+	scp_image_info.image_base = PRELOADED_SCP_BASE;
+	scp_image_info.image_size = PRELOADED_SCP_SIZE;
+	bcm_bl2_plat_handle_scp_bl2(&scp_image_info);
+#endif
+	/*
+	 * In BL31, logs are saved to DDR and we have much larger space to
+	 * store logs. We can now afford to save all logs >= the 'INFO' level
+	 */
+	bcm_elog_init((void *)BCM_ELOG_BL31_BASE, BCM_ELOG_BL31_SIZE,
+		      LOG_LEVEL_INFO);
+
+	INFO("L2CTLR = 0x%lx\n", read_l2ctlr_el1());
+
+	brcm_timer_sync_init();
+
+	brcm_stingray_dma_pl330_init();
+
+	brcm_stingray_dma_pl330_meminit();
+
+	brcm_stingray_spi_pl022_init(APBS_IDM_IDM_RESET_CONTROL);
+
+#ifdef USE_AMAC
+	brcm_stingray_amac_init();
+#endif
+
+	brcm_stingray_sdio_init();
+
+#ifdef NCSI_IO_DRIVE_STRENGTH_MA
+	brcm_stingray_ncsi_init();
+#endif
+
+#ifdef USE_USB
+	xhci_phy_init();
+#endif
+
+#ifdef USE_SATA
+	brcm_stingray_sata_init();
+#else
+	poweroff_sata_pll();
+#endif
+
+	ccn_pre_init();
+
+	brcm_fsx_init();
+
+	brcm_stingray_smmu_init();
+
+	brcm_stingray_pka_meminit();
+
+	brcm_stingray_crmu_access_init();
+
+	brcm_stingray_scr_init();
+
+	brcm_stingray_hsls_tzpcprot_init();
+
+#ifdef USE_I2S
+	brcm_stingray_audio_init();
+#endif
+
+	ccn_post_init();
+
+	paxb_init();
+
+	paxc_init();
+
+#ifndef BL31_BOOT_PRELOADED_SCP
+	crmu_init();
+#endif
+
+	/* Note: this should be last thing because
+	 * FS4 GPV registers only work after FS4 block
+	 * (i.e. crypto,raid,cop) is out of reset.
+	 */
+	brcm_stingray_security_init();
+
+	brcm_gpio_pad_ns_init();
+
+#ifndef USE_DDR
+	brcm_stingray_sram_ns_init();
+#endif
+
+#ifdef BL31_FORCE_CPU_FULL_FREQ
+	bcm_set_ihost_pll_freq(0x0, PLL_FREQ_FULL);
+#endif
+
+	brcm_stingray_gain_qspi_control();
+
+#ifdef USE_PAXC
+	/*
+	 * Check that the handshake has occurred and report ChiMP status.
+	 * This is required. Otherwise (especially on Palladium)
+	 * Linux might have booted to the pcie stage whereas
+	 * ChiMP has not yet booted. Note that nic_mode case has already
+	 * been considered above.
+	 */
+	if ((boot_source_get() != BOOT_SOURCE_QSPI) &&
+	    (!bcm_chimp_is_nic_mode()) &&
+	    (!bcm_chimp_wait_handshake())
+	   ) {
+		/* Does ChiMP report an error ? */
+		uint32_t err;
+
+		err = bcm_chimp_read_ctrl(CHIMP_REG_CTRL_BPE_STAT_REG);
+		if ((err & CHIMP_ERROR_MASK) == 0)
+		/* ChiMP has not booted yet, but no error reported */
+			WARN("ChiMP not booted yet, but no error reported.\n");
+	}
+
+#if DEBUG
+	if (boot_source_get() != BOOT_SOURCE_QSPI)
+		INFO("Current ChiMP Status: 0x%x; bpe_mod reg: 0x%x\n"
+		     "fastboot register: 0x%x; handshake register 0x%x\n",
+		     bcm_chimp_read_ctrl(CHIMP_REG_CTRL_BPE_STAT_REG),
+		     bcm_chimp_read_ctrl(CHIMP_REG_CTRL_BPE_MODE_REG),
+		     bcm_chimp_read_ctrl(CHIMP_REG_CTRL_FSTBOOT_PTR_REG),
+		     bcm_chimp_read(CHIMP_REG_ECO_RESERVED));
+#endif /* DEBUG */
+#endif
+
+#ifdef FS4_DISABLE_CLOCK
+	flush_dcache_range(
+		PLAT_BRCM_TRUSTED_SRAM_BASE,
+		PLAT_BRCM_TRUSTED_SRAM_SIZE);
+	fs4_disable_clocks(true, true, true);
+#endif
+
+	/* pass information to BL33 through shared DDR region */
+	bcm_bl33_pass_info();
+
+	/*
+	 * We are not yet at the end of BL31, but we can stop log here so we do
+	 * not need to add 'bcm_elog_exit' to the standard BL31 code. The
+	 * benefit of capturing BL31 logs after this is very minimal in a
+	 * production system
+	 */
+	bcm_elog_exit();
+
+#if !BRCM_DISABLE_TRUSTED_WDOG
+	/*
+	 * Secure watchdog was started earlier in BL2, now it's time to stop
+	 * it
+	 */
+	sp805_stop(ARM_SP805_TWDG_BASE);
+#endif
+}
diff --git a/plat/brcm/board/stingray/src/brcm_pm_ops.c b/plat/brcm/board/stingray/src/brcm_pm_ops.c
index 81d2ccf..090fbca 100644
--- a/plat/brcm/board/stingray/src/brcm_pm_ops.c
+++ b/plat/brcm/board/stingray/src/brcm_pm_ops.c
@@ -16,9 +16,11 @@
 #include <lib/spinlock.h>
 
 #include <brcm_scpi.h>
+#include <chimp.h>
 #include <cmn_plat_util.h>
 #include <plat_brcm.h>
 #include <platform_def.h>
+#include <sr_utils.h>
 
 #include "m0_cfg.h"
 
@@ -280,7 +282,14 @@
 
 static void __dead2 brcm_system_reset(void)
 {
-	brcm_scp_sys_reset(SOFT_SYS_RESET_L1);
+	unsigned int reset_type;
+
+	if (bcm_chimp_is_nic_mode())
+		reset_type = SOFT_RESET_L3;
+	else
+		reset_type = SOFT_SYS_RESET_L1;
+
+	brcm_scp_sys_reset(reset_type);
 }
 
 static int brcm_system_reset2(int is_vendor, int reset_type,
@@ -289,6 +298,11 @@
 	if (!is_vendor) {
 		/* Architectural warm boot: only warm reset is supported */
 		reset_type = SOFT_RESET_L3;
+	} else {
+		uint32_t boot_source = (uint32_t)cookie;
+
+		boot_source &= BOOT_SOURCE_MASK;
+		brcm_stingray_set_straps(boot_source);
 	}
 	brcm_scp_sys_reset(reset_type);
 
diff --git a/plat/brcm/board/stingray/src/fsx.c b/plat/brcm/board/stingray/src/fsx.c
new file mode 100644
index 0000000..5725a2e
--- /dev/null
+++ b/plat/brcm/board/stingray/src/fsx.c
@@ -0,0 +1,477 @@
+/*
+ * Copyright (c) 2019-2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <drivers/console.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+#include <plat/common/common_def.h>
+
+#include <fsx.h>
+#include <platform_def.h>
+#include <sr_utils.h>
+
+#define FS4_IDM_IO_CONTROL_DIRECT__SRAM_CLK_EN		0
+
+#define FS4_IDM_IO_CONTROL_DIRECT__MEM_POWERON		11
+#define FS4_IDM_IO_CONTROL_DIRECT__MEM_POWEROK		12
+#define FS4_IDM_IO_CONTROL_DIRECT__MEM_ARRPOWERON	13
+#define FS4_IDM_IO_CONTROL_DIRECT__MEM_ARRPOWEROK	14
+#define FS4_IDM_IO_CONTROL_DIRECT__MEM_ISO		15
+#define FS4_IDM_IO_CONTROL_DIRECT__CLK_EN		31
+
+#define FS4_IDM_IO_STATUS__MEM_POWERON			0
+#define FS4_IDM_IO_STATUS__MEM_POWEROK			1
+#define FS4_IDM_IO_STATUS__MEM_ARRPOWERON		2
+#define FS4_IDM_IO_STATUS__MEM_ARRPOWEROK		3
+#define FS4_IDM_IO_STATUS__MEM_ALLOK			0xf
+
+#define FS4_IDM_RESET_CONTROL__RESET			0
+
+#define FSX_RINGx_BASE(__b, __i)			\
+		((__b) + (__i) * 0x10000)
+
+#define FSX_RINGx_VERSION_NUMBER(__b, __i)		\
+		(FSX_RINGx_BASE(__b, __i) + 0x0)
+
+#define FSX_RINGx_MSI_DEV_ID(__b, __i)			\
+		(FSX_RINGx_BASE(__b, __i) + 0x44)
+
+#define FSX_COMM_RINGx_BASE(__b, __i)			\
+		((__b) + 0x200000 + (__i) * 0x100)
+
+#define FSX_COMM_RINGx_CONTROL(__b, __i)		\
+		(FSX_COMM_RINGx_BASE(__b, __i) + 0x0)
+#define FSX_COMM_RINGx_CONTROL__AXI_ID			8
+#define FSX_COMM_RINGx_CONTROL__AXI_ID_MASK		0x1f
+#define FSX_COMM_RINGx_CONTROL__PRIORITY		4
+#define FSX_COMM_RINGx_CONTROL__PRIORITY_MASK		0x7
+#define FSX_COMM_RINGx_CONTROL__AE_GROUP		0
+#define FSX_COMM_RINGx_CONTROL__AE_GROUP_MASK		0x7
+
+#define FSX_COMM_RINGx_MSI_DEV_ID(__b, __i)		\
+		(FSX_COMM_RINGx_BASE(__b, __i) + 0x4)
+
+#define FSX_AEx_BASE(__b, __i)				\
+		((__b) + 0x202000 + (__i) * 0x100)
+
+#define FSX_AEx_CONTROL_REGISTER(__b, __i)		\
+		(FSX_AEx_BASE(__b, __i) + 0x0)
+#define FSX_AEx_CONTROL_REGISTER__ACTIVE		4
+#define FSX_AEx_CONTROL_REGISTER__GROUP_ID		0
+#define FSX_AEx_CONTROL_REGISTER__GROUP_ID_MASK		0x7
+
+#define FSX_COMM_RM_RING_SECURITY_SETTING		0x0
+
+#define FSX_COMM_RM_SSID_CONTROL			0x4
+#define FSX_COMM_RM_SSID_CONTROL__RING_BITS		5
+#define FSX_COMM_RM_SSID_CONTROL__MASK			0x3ff
+
+#define FSX_COMM_RM_CONTROL_REGISTER			0x8
+#define FSX_COMM_RM_CONTROL_REGISTER__CONFIG_DONE	2
+#define FSX_COMM_RM_CONTROL_REGISTER__AE_TIMEOUT	5
+#define FSX_COMM_RM_CONTROL_REGISTER__AE_LOCKING	7
+
+#define FSX_COMM_RM_TIMER_CONTROL_0			0xc
+#define FSX_COMM_RM_TIMER_CONTROL_0__FAST		16
+#define FSX_COMM_RM_TIMER_CONTROL_0__MEDIUM		0
+
+#define FSX_COMM_RM_TIMER_CONTROL_1			0x10
+#define FSX_COMM_RM_TIMER_CONTROL_1__SLOW		16
+#define FSX_COMM_RM_TIMER_CONTROL_1__IDLE		0
+
+#define FSX_COMM_RM_BURST_BD_THRESHOLD			0x14
+#define FSX_COMM_RM_BURST_BD_THRESHOLD_LOW		0
+#define FSX_COMM_RM_BURST_BD_THRESHOLD_HIGH		16
+
+#define FSX_COMM_RM_BURST_LENGTH			0x18
+#define FSX_COMM_RM_BURST_LENGTH__FOR_DDR_ADDR_GEN	16
+#define FSX_COMM_RM_BURST_LENGTH__FOR_DDR_ADDR_GEN_MASK	0x1ff
+#define FSX_COMM_RM_BURST_LENGTH__FOR_TOGGLE		0
+#define FSX_COMM_RM_BURST_LENGTH__FOR_TOGGLE_MASK	0x1ff
+
+#define FSX_COMM_RM_FIFO_THRESHOLD			0x1c
+#define FSX_COMM_RM_FIFO_THRESHOLD__BD_FIFO_FULL	16
+#define FSX_COMM_RM_FIFO_THRESHOLD__BD_FIFO_FULL_MASK	0x1ff
+#define FSX_COMM_RM_FIFO_THRESHOLD__AE_FIFO_FULL	0
+#define FSX_COMM_RM_FIFO_THRESHOLD__AE_FIFO_FULL_MASK	0x1f
+
+#define FSX_COMM_RM_AE_TIMEOUT				0x24
+
+#define FSX_COMM_RM_RING_FLUSH_TIMEOUT			0x2c
+
+#define FSX_COMM_RM_MEMORY_CONFIGURATION		0x30
+#define FSX_COMM_RM_MEMORY_CONFIGURATION__ARRPOWERONIN	12
+#define FSX_COMM_RM_MEMORY_CONFIGURATION__ARRPOWEROKIN	13
+#define FSX_COMM_RM_MEMORY_CONFIGURATION__POWERONIN	14
+#define FSX_COMM_RM_MEMORY_CONFIGURATION__POWEROKIN	15
+
+#define FSX_COMM_RM_AXI_CONTROL				0x34
+#define FSX_COMM_RM_AXI_CONTROL__WRITE_CHANNEL_EN	28
+#define FSX_COMM_RM_AXI_CONTROL__READ_CHANNEL_EN	24
+#define FSX_COMM_RM_AXI_CONTROL__AWQOS			20
+#define FSX_COMM_RM_AXI_CONTROL__ARQOS			16
+#define FSX_COMM_RM_AXI_CONTROL__AWPROT			12
+#define FSX_COMM_RM_AXI_CONTROL__ARPROT			8
+#define FSX_COMM_RM_AXI_CONTROL__AWCACHE		4
+#define FSX_COMM_RM_AXI_CONTROL__ARCACHE		0
+
+#define FSX_COMM_RM_CONFIG_INTERRUPT_STATUS_CLEAR	0x48
+
+#define FSX_COMM_RM_GROUP_PKT_EXTENSION_SUPPORT		0xc0
+
+#define FSX_COMM_RM_AXI_READ_BURST_THRESHOLD		0xc8
+#define FSX_COMM_RM_AXI_READ_BURST_THRESHOLD__MASK	0x1ff
+#define FSX_COMM_RM_AXI_READ_BURST_THRESHOLD__MAX	16
+#define FSX_COMM_RM_AXI_READ_BURST_THRESHOLD__MIN	0
+
+#define FSX_COMM_RM_GROUP_RING_COUNT			0xcc
+
+#define FSX_COMM_RM_MAIN_HW_INIT_DONE			0x12c
+#define FSX_COMM_RM_MAIN_HW_INIT_DONE__MASK		0x1
+
+#define FSX_DMEx_BASE(__b, __i)				\
+		((__b) + (__i) * 0x1000)
+
+#define FSX_DMEx_AXI_CONTROL(__b, __i)			\
+		(FSX_DMEx_BASE(__b, __i) + 0x4)
+#define FSX_DMEx_AXI_CONTROL__WRITE_CHANNEL_EN		28
+#define FSX_DMEx_AXI_CONTROL__READ_CHANNEL_EN		24
+#define FSX_DMEx_AXI_CONTROL__AWQOS			20
+#define FSX_DMEx_AXI_CONTROL__ARQOS			16
+#define FSX_DMEx_AXI_CONTROL__AWCACHE			4
+#define FSX_DMEx_AXI_CONTROL__ARCACHE			0
+
+#define FSX_DMEx_WR_FIFO_THRESHOLD(__b, __i)		\
+		(FSX_DMEx_BASE(__b, __i) + 0xc)
+#define FSX_DMEx_WR_FIFO_THRESHOLD__MASK		0x3ff
+#define FSX_DMEx_WR_FIFO_THRESHOLD__MAX			10
+#define FSX_DMEx_WR_FIFO_THRESHOLD__MIN			0
+
+#define FSX_DMEx_RD_FIFO_THRESHOLD(__b, __i)		\
+		(FSX_DMEx_BASE(__b, __i) + 0x14)
+#define FSX_DMEx_RD_FIFO_THRESHOLD__MASK		0x3ff
+#define FSX_DMEx_RD_FIFO_THRESHOLD__MAX			10
+#define FSX_DMEx_RD_FIFO_THRESHOLD__MIN			0
+
+#define FS6_SUB_TOP_BASE				0x66D8F800
+#define FS6_PKI_DME_RESET				0x4
+#define PKI_DME_RESET					1
+
+char *fsx_type_names[] = {
+	"fs4-raid",
+	"fs4-crypto",
+	"fs6-pki",
+};
+
+void fsx_init(eFSX_TYPE fsx_type,
+	      unsigned int ring_count,
+	      unsigned int dme_count,
+	      unsigned int ae_count,
+	      unsigned int start_stream_id,
+	      unsigned int msi_dev_id,
+	      uintptr_t idm_io_control_direct,
+	      uintptr_t idm_reset_control,
+	      uintptr_t base,
+	      uintptr_t dme_base)
+{
+	int try;
+	unsigned int i, v, data;
+	uintptr_t fs4_idm_io_control_direct = idm_io_control_direct;
+	uintptr_t fs4_idm_reset_control = idm_reset_control;
+	uintptr_t fsx_comm_rm = (base + 0x203000);
+
+	VERBOSE("fsx %s init start\n", fsx_type_names[fsx_type]);
+
+	if (fsx_type == eFS4_RAID || fsx_type == eFS4_CRYPTO) {
+		/* Enable FSx engine clock */
+		VERBOSE(" - enable fsx clock\n");
+		mmio_write_32(fs4_idm_io_control_direct,
+		      (1U << FS4_IDM_IO_CONTROL_DIRECT__CLK_EN));
+		udelay(500);
+
+		/* Reset FSx engine */
+		VERBOSE(" - reset fsx\n");
+		v = mmio_read_32(fs4_idm_reset_control);
+		v |= (1 << FS4_IDM_RESET_CONTROL__RESET);
+		mmio_write_32(fs4_idm_reset_control, v);
+		udelay(500);
+		v = mmio_read_32(fs4_idm_reset_control);
+		v &= ~(1 << FS4_IDM_RESET_CONTROL__RESET);
+		mmio_write_32(fs4_idm_reset_control, v);
+	} else {
+		/*
+		 * Default RM and AE are out of reset,
+		 * So only DME Reset added here
+		 */
+		v = mmio_read_32(FS6_SUB_TOP_BASE + FS6_PKI_DME_RESET);
+		v &= ~(PKI_DME_RESET);
+		mmio_write_32(FS6_SUB_TOP_BASE + FS6_PKI_DME_RESET, v);
+	}
+
+	/* Wait for HW-init done */
+	VERBOSE(" - wait for HW-init done\n");
+	try = 10000;
+	do {
+		udelay(1);
+		data = mmio_read_32(fsx_comm_rm +
+				    FSX_COMM_RM_MAIN_HW_INIT_DONE);
+		try--;
+	} while (!(data & FSX_COMM_RM_MAIN_HW_INIT_DONE__MASK) && (try > 0));
+
+	if (try <= 0)
+		ERROR("fsx_comm_rm + 0x%x: 0x%x\n",
+		      data, FSX_COMM_RM_MAIN_HW_INIT_DONE);
+
+	/* Make all rings non-secured */
+	VERBOSE(" - make all rings non-secured\n");
+	v = 0xffffffff;
+	mmio_write_32(fsx_comm_rm + FSX_COMM_RM_RING_SECURITY_SETTING, v);
+
+	/* Set start stream-id for rings to */
+	VERBOSE(" - set start stream-id for rings to 0x%x\n",
+		start_stream_id);
+	v = start_stream_id >> FSX_COMM_RM_SSID_CONTROL__RING_BITS;
+	v &= FSX_COMM_RM_SSID_CONTROL__MASK;
+	mmio_write_32(fsx_comm_rm + FSX_COMM_RM_SSID_CONTROL, v);
+
+	/* Set timer configuration */
+	VERBOSE(" - set timer configuration\n");
+	v = 0x0271 << FSX_COMM_RM_TIMER_CONTROL_0__MEDIUM;
+	v |= (0x0138 << FSX_COMM_RM_TIMER_CONTROL_0__FAST);
+	mmio_write_32(fsx_comm_rm + FSX_COMM_RM_TIMER_CONTROL_0, v);
+	v = 0x09c4 << FSX_COMM_RM_TIMER_CONTROL_1__IDLE;
+	v |= (0x04e2 << FSX_COMM_RM_TIMER_CONTROL_1__SLOW);
+	mmio_write_32(fsx_comm_rm + FSX_COMM_RM_TIMER_CONTROL_1, v);
+	v = 0x0000f424;
+	mmio_write_32(fsx_comm_rm + FSX_COMM_RM_RING_FLUSH_TIMEOUT, v);
+
+	/* Set burst length and fifo threshold */
+	VERBOSE(" - set burst length, fifo and bd threshold\n");
+	v = 0x0;
+	v |= (0x8 << FSX_COMM_RM_BURST_LENGTH__FOR_DDR_ADDR_GEN);
+	v |= (0x8 << FSX_COMM_RM_BURST_LENGTH__FOR_TOGGLE);
+	mmio_write_32(fsx_comm_rm + FSX_COMM_RM_BURST_LENGTH, v);
+	v = 0x0;
+	v |= (0x67 << FSX_COMM_RM_FIFO_THRESHOLD__BD_FIFO_FULL);
+	v |= (0x18 << FSX_COMM_RM_FIFO_THRESHOLD__AE_FIFO_FULL);
+	mmio_write_32(fsx_comm_rm + FSX_COMM_RM_FIFO_THRESHOLD, v);
+	v = 0x0;
+	v |= (0x8 << FSX_COMM_RM_BURST_BD_THRESHOLD_LOW);
+	v |= (0x8 << FSX_COMM_RM_BURST_BD_THRESHOLD_HIGH);
+	mmio_write_32(fsx_comm_rm + FSX_COMM_RM_BURST_BD_THRESHOLD, v);
+
+	/* Set memory configuration */
+	VERBOSE(" - set memory configuration\n");
+	v = 0x0;
+	v |= (1 << FSX_COMM_RM_MEMORY_CONFIGURATION__POWERONIN);
+	v |= (1 << FSX_COMM_RM_MEMORY_CONFIGURATION__POWEROKIN);
+	v |= (1 << FSX_COMM_RM_MEMORY_CONFIGURATION__ARRPOWERONIN);
+	v |= (1 << FSX_COMM_RM_MEMORY_CONFIGURATION__ARRPOWEROKIN);
+	mmio_write_32(fsx_comm_rm + FSX_COMM_RM_MEMORY_CONFIGURATION, v);
+
+	/* AXI configuration for RM */
+	v = 0;
+	v |= (0x1 << FSX_COMM_RM_AXI_CONTROL__WRITE_CHANNEL_EN);
+	v |= (0x1 << FSX_COMM_RM_AXI_CONTROL__READ_CHANNEL_EN);
+	v |= (0xe << FSX_COMM_RM_AXI_CONTROL__AWQOS);
+	v |= (0xa << FSX_COMM_RM_AXI_CONTROL__ARQOS);
+	v |= (0x2 << FSX_COMM_RM_AXI_CONTROL__AWPROT);
+	v |= (0x2 << FSX_COMM_RM_AXI_CONTROL__ARPROT);
+	v |= (0xf << FSX_COMM_RM_AXI_CONTROL__AWCACHE);
+	v |= (0xf << FSX_COMM_RM_AXI_CONTROL__ARCACHE);
+	mmio_write_32(fsx_comm_rm + FSX_COMM_RM_AXI_CONTROL, v);
+	VERBOSE(" - set AXI control = 0x%x\n",
+		mmio_read_32(fsx_comm_rm + FSX_COMM_RM_AXI_CONTROL));
+	v = 0x0;
+	v |= (0x10 << FSX_COMM_RM_AXI_READ_BURST_THRESHOLD__MAX);
+	v |= (0x10 << FSX_COMM_RM_AXI_READ_BURST_THRESHOLD__MIN);
+	mmio_write_32(fsx_comm_rm + FSX_COMM_RM_AXI_READ_BURST_THRESHOLD, v);
+	VERBOSE(" - set AXI read burst threshold = 0x%x\n",
+	mmio_read_32(fsx_comm_rm + FSX_COMM_RM_AXI_READ_BURST_THRESHOLD));
+
+	/* Configure group ring count for all groups */
+	/* By default we schedule extended packets
+	 * on all AEs/DMEs in a group.
+	 */
+	v = (dme_count & 0xf) << 0;
+	v |= (dme_count & 0xf) << 4;
+	v |= (dme_count & 0xf) << 8;
+	v |= (dme_count & 0xf) << 12;
+	v |= (dme_count & 0xf) << 16;
+	v |= (dme_count & 0xf) << 20;
+	v |= (dme_count & 0xf) << 24;
+	v |= (dme_count & 0xf) << 28;
+	mmio_write_32(fsx_comm_rm + FSX_COMM_RM_GROUP_RING_COUNT, v);
+
+	/*
+	 * Due to HW issue spurious interrupts are getting generated.
+	 * To fix sw needs to clear the config status interrupts
+	 * before setting CONFIG_DONE.
+	 */
+	mmio_write_32(fsx_comm_rm +
+		      FSX_COMM_RM_CONFIG_INTERRUPT_STATUS_CLEAR,
+		      0xffffffff);
+
+	/* Configure RM control */
+	VERBOSE(" - configure RM control\n");
+	v = mmio_read_32(fsx_comm_rm + FSX_COMM_RM_CONTROL_REGISTER);
+	v |= (1 << FSX_COMM_RM_CONTROL_REGISTER__AE_LOCKING);
+	mmio_write_32(fsx_comm_rm + FSX_COMM_RM_CONTROL_REGISTER, v);
+	v |= (1 << FSX_COMM_RM_CONTROL_REGISTER__CONFIG_DONE);
+	mmio_write_32(fsx_comm_rm + FSX_COMM_RM_CONTROL_REGISTER, v);
+
+	/* Configure AE timeout */
+	VERBOSE(" - configure AE timeout\n");
+	v = 0x00003fff;
+	mmio_write_32(fsx_comm_rm + FSX_COMM_RM_AE_TIMEOUT, v);
+
+	/* Initialize all AEs */
+	for (i = 0; i < ae_count; i++) {
+		VERBOSE(" - initialize AE%d\n", i);
+		v = (0x1 << FSX_AEx_CONTROL_REGISTER__ACTIVE);
+		mmio_write_32(FSX_AEx_CONTROL_REGISTER(base, i), v);
+	}
+
+	/* Initialize all DMEs */
+	for (i = 0; i < dme_count; i++) {
+		VERBOSE(" - initialize DME%d\n", i);
+		v = 0;
+		v |= (0x1 << FSX_DMEx_AXI_CONTROL__WRITE_CHANNEL_EN);
+		v |= (0x1 << FSX_DMEx_AXI_CONTROL__READ_CHANNEL_EN);
+		v |= (0xe << FSX_DMEx_AXI_CONTROL__AWQOS);
+		v |= (0xa << FSX_DMEx_AXI_CONTROL__ARQOS);
+		v |= (0xf << FSX_DMEx_AXI_CONTROL__AWCACHE);
+		v |= (0xf << FSX_DMEx_AXI_CONTROL__ARCACHE);
+		mmio_write_32(FSX_DMEx_AXI_CONTROL(dme_base, i), v);
+		VERBOSE(" -- AXI_CONTROL = 0x%x\n",
+		mmio_read_32(FSX_DMEx_AXI_CONTROL(dme_base, i)));
+		v = 0;
+		v |= (0x4 << FSX_DMEx_WR_FIFO_THRESHOLD__MIN);
+		v |= (0x4 << FSX_DMEx_WR_FIFO_THRESHOLD__MAX);
+		mmio_write_32(FSX_DMEx_WR_FIFO_THRESHOLD(dme_base, i), v);
+		VERBOSE(" -- WR_FIFO_THRESHOLD = 0x%x\n",
+		mmio_read_32(FSX_DMEx_WR_FIFO_THRESHOLD(dme_base, i)));
+		v = 0;
+		v |= (0x4 << FSX_DMEx_RD_FIFO_THRESHOLD__MIN);
+		v |= (0x4 << FSX_DMEx_RD_FIFO_THRESHOLD__MAX);
+		mmio_write_32(FSX_DMEx_RD_FIFO_THRESHOLD(dme_base, i), v);
+		VERBOSE(" -- RD_FIFO_THRESHOLD = 0x%x\n",
+		mmio_read_32(FSX_DMEx_RD_FIFO_THRESHOLD(dme_base, i)));
+	}
+
+	/* Configure ring axi id and msi device id */
+	for (i = 0; i < ring_count; i++) {
+		VERBOSE(" - ring%d version=0x%x\n", i,
+			mmio_read_32(FSX_RINGx_VERSION_NUMBER(base, i)));
+		mmio_write_32(FSX_COMM_RINGx_MSI_DEV_ID(base, i),
+			      msi_dev_id);
+		v = 0;
+		v |= ((i & FSX_COMM_RINGx_CONTROL__AXI_ID_MASK) <<
+		      FSX_COMM_RINGx_CONTROL__AXI_ID);
+		mmio_write_32(FSX_COMM_RINGx_CONTROL(base, i), v);
+	}
+
+	INFO("fsx %s init done\n", fsx_type_names[fsx_type]);
+}
+
+void fsx_meminit(const char *name,
+		 uintptr_t idm_io_control_direct,
+		 uintptr_t idm_io_status)
+{
+	int try;
+	unsigned int val;
+
+	VERBOSE("fsx %s meminit start\n", name);
+
+	VERBOSE(" - arrpoweron\n");
+	mmio_setbits_32(idm_io_control_direct,
+			BIT(FS4_IDM_IO_CONTROL_DIRECT__MEM_ARRPOWERON));
+	while (!(mmio_read_32(idm_io_status) &
+		 BIT(FS4_IDM_IO_STATUS__MEM_ARRPOWERON)))
+		;
+
+	VERBOSE(" - arrpowerok\n");
+	mmio_setbits_32(idm_io_control_direct,
+			(1 << FS4_IDM_IO_CONTROL_DIRECT__MEM_ARRPOWEROK));
+	while (!(mmio_read_32(idm_io_status) &
+		 BIT(FS4_IDM_IO_STATUS__MEM_ARRPOWEROK)))
+		;
+
+	VERBOSE(" - poweron\n");
+	mmio_setbits_32(idm_io_control_direct,
+			(1 << FS4_IDM_IO_CONTROL_DIRECT__MEM_POWERON));
+	while (!(mmio_read_32(idm_io_status) &
+		 BIT(FS4_IDM_IO_STATUS__MEM_POWERON)))
+		;
+
+	VERBOSE(" - powerok\n");
+	mmio_setbits_32(idm_io_control_direct,
+			(1 << FS4_IDM_IO_CONTROL_DIRECT__MEM_POWEROK));
+	while (!(mmio_read_32(idm_io_status) &
+		 BIT(FS4_IDM_IO_STATUS__MEM_POWEROK)))
+		;
+
+	/* Final check on all power bits */
+	try = 10;
+	do {
+		val = mmio_read_32(idm_io_status);
+		if (val == FS4_IDM_IO_STATUS__MEM_ALLOK)
+			break;
+
+		/* Wait sometime */
+		mdelay(1);
+
+		try--;
+	} while (try > 0);
+
+	/* Remove memory isolation if things are fine. */
+	if (try <= 0) {
+		INFO(" - powerup failed\n");
+	} else {
+		VERBOSE(" - remove isolation\n");
+		mmio_clrbits_32(idm_io_control_direct,
+				(1 << FS4_IDM_IO_CONTROL_DIRECT__MEM_ISO));
+		VERBOSE(" - powerup done\n");
+	}
+
+	INFO("fsx %s meminit done\n", name);
+}
+
+void fs4_disable_clocks(bool disable_sram,
+			bool disable_crypto,
+			bool disable_raid)
+{
+	VERBOSE("fs4 disable clocks start\n");
+
+	if (disable_sram) {
+		VERBOSE(" - disable sram clock\n");
+		mmio_clrbits_32(FS4_SRAM_IDM_IO_CONTROL_DIRECT,
+			(1 << FS4_IDM_IO_CONTROL_DIRECT__SRAM_CLK_EN));
+	}
+
+	if (disable_crypto) {
+		VERBOSE(" - disable crypto clock\n");
+		mmio_setbits_32(CDRU_GENPLL5_CONTROL1,
+				CDRU_GENPLL5_CONTROL1__CHNL1_CRYPTO_AE_CLK);
+	}
+
+	if (disable_raid) {
+		VERBOSE(" - disable raid clock\n");
+		mmio_setbits_32(CDRU_GENPLL5_CONTROL1,
+				CDRU_GENPLL5_CONTROL1__CHNL2_RAID_AE_CLK);
+	}
+
+	if (disable_sram && disable_crypto && disable_raid) {
+		VERBOSE(" - disable root clock\n");
+		mmio_setbits_32(CDRU_GENPLL5_CONTROL1,
+				CDRU_GENPLL5_CONTROL1__CHNL0_DME_CLK);
+		mmio_setbits_32(CDRU_GENPLL2_CONTROL1,
+				CDRU_GENPLL2_CONTROL1__CHNL6_FS4_CLK);
+	}
+
+	INFO("fs4 disable clocks done\n");
+}
diff --git a/plat/brcm/board/stingray/src/iommu.c b/plat/brcm/board/stingray/src/iommu.c
new file mode 100644
index 0000000..de8b995
--- /dev/null
+++ b/plat/brcm/board/stingray/src/iommu.c
@@ -0,0 +1,536 @@
+/*
+ * Copyright (c) 2017 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+
+#include <iommu.h>
+#include <platform_def.h>
+
+#define SMMU_BASE		0x64000000
+#define ARM_SMMU_MAX_NUM_CNTXT_BANK	64
+#define SMMU_CTX_BANK_IDX_SECURE_CRMU	63
+#define ARM_SMMU_NUM_SECURE_MASTER	1
+#define ARM_SMMU_NSNUMCBO		(ARM_SMMU_MAX_NUM_CNTXT_BANK - \
+					 ARM_SMMU_NUM_SECURE_MASTER)
+#define ARM_SMMU_NSNUMSMRGO		(ARM_SMMU_MAX_NUM_CNTXT_BANK - \
+					 ARM_SMMU_NUM_SECURE_MASTER)
+/* Reserved Banks. */
+#define SMMU_CTX_BANK_IDX		(SMMU_CTX_BANK_IDX_SECURE_CRMU - \
+					 ARM_SMMU_NUM_SECURE_MASTER)
+#define NUM_OF_SMRS			1
+
+#define STG1_WITH_STG2_BYPASS		1
+#define ARM_LPAE_PGTBL_PHYS_CRMU	0x880000000
+#define ARM_LPAE_PGTBL_PHYS		0x880200000
+#define ARM_LPAE_PGTBL_PTE_CNT		512
+#define ARM_LPAE_PTE_L1_BLOCK_SIZE	0x40000000
+#define ARM_LPAE_PTE_L1_ADDR_MASK	0x0000FFFFC0000000UL
+#define ARM_LPAE_PTE_TABLE		0x2UL
+#define ARM_LPAE_PTE_VALID		0x1UL
+#define ARM_LPAE_PTE_ATTRINDX		2
+#define ARM_LPAE_PTE_NS			5
+#define ARM_LPAE_PTE_AP			6
+#define ARM_LPAE_PTE_AP_EL1_RW		0x0
+#define ARM_LPAE_PTE_AP_EL0_RW		0x1
+#define ARM_LPAE_PTE_SH			8
+#define ARM_LPAE_PTE_SH_NON		0x0
+#define ARM_LPAE_PTE_SH_OUTER		0x2
+#define ARM_LPAE_PTE_SH_INNER		0x3
+#define ARM_LPAE_PTE_AF			10
+#define ARM_SMMU_RES_SIZE		0x80000
+
+#define ARM_LPAE_PTE_NSTABLE		0x8000000000000000UL
+#define ARM_LPAE_PTE_L1_INDEX_SHIFT	30
+#define ARM_LPAE_PTE_L1_INDEX_MASK	0x1ff
+#define ARM_LPAE_PTE_L0_INDEX_SHIFT	39
+#define ARM_LPAE_PTE_L0_INDEX_MASK	0x1ff
+#define ARM_LPAE_PTE_TABLE_MASK		~(0xfffUL)
+/* Configuration registers */
+#define ARM_SMMU_GR0_sCR0	0x0
+#define sCR0_CLIENTPD		(1 << 0)
+#define sCR0_GFRE		(1 << 1)
+#define sCR0_GFIE		(1 << 2)
+#define sCR0_GCFGFRE		(1 << 4)
+#define sCR0_GCFGFIE		(1 << 5)
+#define sCR0_USFCFG		(1 << 10)
+#define sCR0_VMIDPNE		(1 << 11)
+#define sCR0_PTM		(1 << 12)
+#define sCR0_FB			(1 << 13)
+#define sCR0_VMID16EN		(1 << 31)
+#define sCR0_BSU_SHIFT		14
+#define sCR0_BSU_MASK		0x3
+#define ARM_SMMU_SMMU_SCR1	0x4
+#define SCR1_NSNUMCBO_MASK	0xFF
+#define SCR1_NSNUMCBO_SHIFT	0x0
+#define SCR1_NSNUMSMRGO_MASK	0xFF00
+#define SCR1_NSNUMSMRGO_SHIFT	0x8
+
+/* Identification registers */
+#define ARM_SMMU_GR0_ID0		0x20
+#define ARM_SMMU_GR0_ID1		0x24
+#define ARM_SMMU_GR0_ID2		0x28
+#define ARM_SMMU_GR0_ID3		0x2c
+#define ARM_SMMU_GR0_ID4		0x30
+#define ARM_SMMU_GR0_ID5		0x34
+#define ARM_SMMU_GR0_ID6		0x38
+#define ARM_SMMU_GR0_ID7		0x3c
+#define ARM_SMMU_GR0_sGFSR		0x48
+#define ARM_SMMU_GR0_sGFSYNR0		0x50
+#define ARM_SMMU_GR0_sGFSYNR1		0x54
+#define ARM_SMMU_GR0_sGFSYNR2		0x58
+
+#define ID1_PAGESIZE			(1U << 31)
+#define ID1_NUMPAGENDXB_SHIFT		28
+#define ID1_NUMPAGENDXB_MASK		7
+#define ID1_NUMS2CB_SHIFT		16
+#define ID1_NUMS2CB_MASK		0xff
+#define ID1_NUMCB_SHIFT			0
+#define ID1_NUMCB_MASK			0xff
+
+/* SMMU global address space */
+#define ARM_SMMU_GR0(smmu)	((smmu)->base)
+#define ARM_SMMU_GR1(smmu)	((smmu)->base + (1 << (smmu)->pgshift))
+
+/* Stream mapping registers */
+#define ARM_SMMU_GR0_SMR(n)	(0x800 + (n << 2))
+#define SMR_VALID		(1U << 31)
+#define SMR_MASK_SHIFT		16
+#define SMR_ID_SHIFT		0
+
+#define ARM_SMMU_GR0_S2CR(n)	(0xc00 + (n << 2))
+#define S2CR_CBNDX_SHIFT	0
+#define S2CR_CBNDX_MASK		0xff
+#define S2CR_TYPE_SHIFT		16
+#define S2CR_TYPE_MASK		0x3
+
+#define ARM_SMMU_GR1_CBA2R(n)	(0x800 + (n << 2))
+#define CBA2R_RW64_32BIT	(0 << 0)
+#define CBA2R_RW64_64BIT	(1 << 0)
+#define CBA2R_VMID_SHIFT	16
+#define CBA2R_VMID_MASK		0xffff
+
+#define ARM_SMMU_GR1_CBAR(n)	(0x0 + (n << 2))
+#define CBAR_VMID_SHIFT		0
+#define CBAR_VMID_MASK		0xff
+#define CBAR_S1_BPSHCFG_SHIFT	8
+#define CBAR_S1_BPSHCFG_MASK	3
+#define CBAR_S1_BPSHCFG_NSH	3
+#define CBAR_S1_MEMATTR_SHIFT	12
+#define CBAR_S1_MEMATTR_MASK	0xf
+#define CBAR_S1_MEMATTR_WB	0xf
+#define CBAR_TYPE_SHIFT		16
+#define CBAR_TYPE_MASK		0x3
+#define CBAR_TYPE_S2_TRANS		(0 << CBAR_TYPE_SHIFT)
+#define CBAR_TYPE_S1_TRANS_S2_BYPASS	(1 << CBAR_TYPE_SHIFT)
+#define CBAR_TYPE_S1_TRANS_S2_FAULT	(2 << CBAR_TYPE_SHIFT)
+#define CBAR_TYPE_S1_TRANS_S2_TRANS	(3 << CBAR_TYPE_SHIFT)
+#define CBAR_IRPTNDX_SHIFT		24
+#define CBAR_IRPTNDX_MASK		0xff
+
+/* Translation context bank */
+#define ARM_SMMU_CB_BASE(smmu)		((smmu)->base + ((smmu)->size >> 1))
+#define ARM_SMMU_CB(smmu, n)		((n) * (1 << (smmu)->pgshift))
+
+#define ARM_SMMU_CB_SCTLR		0x0
+#define ARM_SMMU_CB_ACTLR		0x4
+#define ARM_SMMU_CB_RESUME		0x8
+#define ARM_SMMU_CB_TTBCR2		0x10
+#define ARM_SMMU_CB_TTBR0		0x20
+#define ARM_SMMU_CB_TTBR1		0x28
+#define ARM_SMMU_CB_TTBCR		0x30
+#define ARM_SMMU_CB_CONTEXTIDR		0x34
+#define ARM_SMMU_CB_S1_MAIR0		0x38
+#define ARM_SMMU_CB_S1_MAIR1		0x3c
+#define ARM_SMMU_CB_PAR			0x50
+#define ARM_SMMU_CB_FSR			0x58
+#define ARM_SMMU_CB_FAR			0x60
+#define ARM_SMMU_CB_FSYNR0		0x68
+#define ARM_SMMU_CB_S1_TLBIVA		0x600
+#define ARM_SMMU_CB_S1_TLBIASID		0x610
+#define ARM_SMMU_CB_S1_TLBIVAL		0x620
+#define ARM_SMMU_CB_S2_TLBIIPAS2	0x630
+#define ARM_SMMU_CB_S2_TLBIIPAS2L	0x638
+#define ARM_SMMU_CB_ATS1PR		0x800
+#define ARM_SMMU_CB_ATSR		0x8f0
+
+#define SCTLR_S1_ASIDPNE		(1 << 12)
+#define SCTLR_CFCFG			(1 << 7)
+#define SCTLR_CFIE			(1 << 6)
+#define SCTLR_CFRE			(1 << 5)
+#define SCTLR_E				(1 << 4)
+#define SCTLR_AFE			(1 << 2)
+#define SCTLR_TRE			(1 << 1)
+#define SCTLR_M				(1 << 0)
+
+/* ARM LPAE configuration. */
+/**************************************************************/
+/* Register bits */
+#define ARM_32_LPAE_TCR_EAE		(1 << 31)
+#define ARM_64_LPAE_S2_TCR_RES1		(1 << 31)
+
+#define ARM_LPAE_TCR_EPD1		(1 << 23)
+
+#define ARM_LPAE_TCR_TG0_4K		(0 << 14)
+#define ARM_LPAE_TCR_TG0_64K		(1 << 14)
+#define ARM_LPAE_TCR_TG0_16K		(2 << 14)
+
+#define ARM_LPAE_TCR_SH0_SHIFT		12
+#define ARM_LPAE_TCR_SH0_MASK		0x3
+#define ARM_LPAE_TCR_SH_NS		0
+#define ARM_LPAE_TCR_SH_OS		2
+#define ARM_LPAE_TCR_SH_IS		3
+
+#define ARM_LPAE_TCR_ORGN0_SHIFT	10
+#define ARM_LPAE_TCR_IRGN0_SHIFT	8
+#define ARM_LPAE_TCR_RGN_MASK		0x3
+#define ARM_LPAE_TCR_RGN_NC		0
+#define ARM_LPAE_TCR_RGN_WBWA		1
+#define ARM_LPAE_TCR_RGN_WT		2
+#define ARM_LPAE_TCR_RGN_WB		3
+
+#define ARM_LPAE_TCR_SL0_SHIFT		6
+#define ARM_LPAE_TCR_SL0_MASK		0x3
+
+#define ARM_LPAE_TCR_T0SZ_SHIFT		0
+#define ARM_LPAE_TCR_SZ_MASK		0xf
+
+#define ARM_LPAE_TCR_PS_SHIFT		16
+#define ARM_LPAE_TCR_PS_MASK		0x7
+
+#define ARM_LPAE_TCR_IPS_SHIFT		32
+#define ARM_LPAE_TCR_IPS_MASK		0x7
+
+#define ARM_LPAE_TCR_PS_32_BIT		0x0ULL
+#define ARM_LPAE_TCR_PS_36_BIT		0x1ULL
+#define ARM_LPAE_TCR_PS_40_BIT		0x2ULL
+#define ARM_LPAE_TCR_PS_42_BIT		0x3ULL
+#define ARM_LPAE_TCR_PS_44_BIT		0x4ULL
+#define ARM_LPAE_TCR_PS_48_BIT		0x5ULL
+
+#define ARM_LPAE_MAIR_ATTR_SHIFT(n)	((n) << 3)
+#define ARM_LPAE_MAIR_ATTR_MASK		0xff
+#define ARM_LPAE_MAIR_ATTR_DEVICE	0x04
+#define ARM_LPAE_MAIR_ATTR_NC		0x44
+#define ARM_LPAE_MAIR_ATTR_WBRWA	0xff
+#define ARM_LPAE_MAIR_ATTR_IDX_NC	0
+#define ARM_LPAE_MAIR_ATTR_IDX_CACHE	1
+#define ARM_LPAE_MAIR_ATTR_IDX_DEV	2
+
+#define TTBRn_ASID_SHIFT		48
+#define TTBCR2_SEP_SHIFT		15
+#define TTBCR2_SEP_UPSTREAM		(0x7 << TTBCR2_SEP_SHIFT)
+#define TTBCR2_AS                       (1 << 4)
+#define TTBCR_T0SZ(ia_bits)		(64 - (ia_bits))
+
+#define S2CR_PRIVCFG_SHIFT		24
+#define S2CR_PRIVCFG_MASK		0x3
+
+/**************************************************************/
+
+uint16_t paxc_stream_ids[] = { 0x2000 };
+
+uint16_t paxc_stream_ids_mask[] = { 0x1fff };
+uint16_t crmu_stream_ids[] = { CRMU_STREAM_ID };
+uint16_t crmu_stream_ids_mask[] = { 0x0 };
+
+enum arm_smmu_s2cr_type {
+	S2CR_TYPE_TRANS,
+	S2CR_TYPE_BYPASS,
+	S2CR_TYPE_FAULT,
+};
+
+enum arm_smmu_s2cr_privcfg {
+	S2CR_PRIVCFG_DEFAULT,
+	S2CR_PRIVCFG_DIPAN,
+	S2CR_PRIVCFG_UNPRIV,
+	S2CR_PRIVCFG_PRIV,
+};
+
+struct arm_smmu_smr {
+	uint16_t mask;
+	uint16_t id;
+	uint32_t valid;
+};
+
+struct arm_smmu_s2cr {
+	int count;
+	enum arm_smmu_s2cr_type type;
+	enum arm_smmu_s2cr_privcfg privcfg;
+	uint8_t cbndx;
+};
+
+struct arm_smmu_cfg {
+	uint8_t cbndx;
+	uint8_t irptndx;
+	uint32_t cbar;
+};
+
+struct arm_smmu_device {
+	uint8_t *base;
+	uint32_t streams;
+	unsigned long size;
+	unsigned long pgshift;
+	unsigned long va_size;
+	unsigned long ipa_size;
+	unsigned long pa_size;
+	struct arm_smmu_smr smr[NUM_OF_SMRS];
+	struct arm_smmu_s2cr s2cr[NUM_OF_SMRS];
+	struct arm_smmu_cfg cfg[NUM_OF_SMRS];
+	uint16_t *stream_ids;
+	uint16_t *stream_ids_mask;
+};
+
+void arm_smmu_enable_secure_client_port(void)
+{
+	uintptr_t smmu_base = SMMU_BASE;
+
+	mmio_clrbits_32(smmu_base, sCR0_CLIENTPD);
+}
+
+void arm_smmu_reserve_secure_cntxt(void)
+{
+	uintptr_t smmu_base = SMMU_BASE;
+
+	mmio_clrsetbits_32(smmu_base + ARM_SMMU_SMMU_SCR1,
+			  (SCR1_NSNUMSMRGO_MASK | SCR1_NSNUMCBO_MASK),
+			  ((ARM_SMMU_NSNUMCBO << SCR1_NSNUMCBO_SHIFT) |
+			  (ARM_SMMU_NSNUMSMRGO << SCR1_NSNUMSMRGO_SHIFT)));
+}
+
+static void arm_smmu_smr_cfg(struct arm_smmu_device *smmu, uint32_t index)
+{
+	uint32_t idx = smmu->cfg[index].cbndx;
+	struct arm_smmu_smr *smr = &smmu->smr[index];
+	uint32_t reg = smr->id << SMR_ID_SHIFT | smr->mask << SMR_MASK_SHIFT;
+
+	if (smr->valid)
+		reg |= SMR_VALID;
+
+	mmio_write_32((uintptr_t) (ARM_SMMU_GR0(smmu) +
+		      ARM_SMMU_GR0_SMR(idx)), reg);
+}
+
+static void arm_smmu_s2cr_cfg(struct arm_smmu_device *smmu, uint32_t index)
+{
+	uint32_t idx = smmu->cfg[index].cbndx;
+	struct arm_smmu_s2cr *s2cr = &smmu->s2cr[index];
+
+	uint32_t reg = (s2cr->type & S2CR_TYPE_MASK) << S2CR_TYPE_SHIFT |
+		  (s2cr->cbndx & S2CR_CBNDX_MASK) << S2CR_CBNDX_SHIFT |
+		  (s2cr->privcfg & S2CR_PRIVCFG_MASK) << S2CR_PRIVCFG_SHIFT;
+
+	mmio_write_32((uintptr_t) (ARM_SMMU_GR0(smmu) +
+		      ARM_SMMU_GR0_S2CR(idx)), reg);
+}
+
+static void smmu_set_pgtbl(struct arm_smmu_device *smmu,
+		    enum iommu_domain dom,
+		    uint64_t *pg_table_base)
+{
+	int i, l0_index, l1_index;
+	uint64_t addr, *pte, *l0_base, *l1_base;
+	uint64_t addr_space_limit;
+
+	if (dom == PCIE_PAXC) {
+		addr_space_limit = 0xffffffffff;
+	} else if (dom == DOMAIN_CRMU) {
+		addr_space_limit = 0xffffffff;
+	} else {
+		ERROR("dom is not supported\n");
+		return;
+	}
+
+	l0_base = pg_table_base;
+	/* clear L0 descriptors. */
+	for (i = 0; i < ARM_LPAE_PGTBL_PTE_CNT; i++)
+		l0_base[i] = 0x0;
+
+	addr = 0x0;
+	while (addr < addr_space_limit) {
+		/* find L0 pte */
+		l0_index = ((addr >> ARM_LPAE_PTE_L0_INDEX_SHIFT) &
+			     ARM_LPAE_PTE_L0_INDEX_MASK);
+		l1_base = l0_base + ((l0_index + 1) * ARM_LPAE_PGTBL_PTE_CNT);
+
+		/* setup L0 pte if required */
+		pte = l0_base + l0_index;
+		if (*pte == 0x0) {
+			*pte |= ((uint64_t)l1_base & ARM_LPAE_PTE_TABLE_MASK);
+			if (dom == PCIE_PAXC)
+				*pte |= ARM_LPAE_PTE_NSTABLE;
+			*pte |= ARM_LPAE_PTE_TABLE;
+			*pte |= ARM_LPAE_PTE_VALID;
+		}
+
+		/* find L1 pte */
+		l1_index = ((addr >> ARM_LPAE_PTE_L1_INDEX_SHIFT) &
+			    ARM_LPAE_PTE_L1_INDEX_MASK);
+		pte = l1_base + l1_index;
+
+		/* setup L1 pte */
+		*pte = 0x0;
+		*pte |= (addr & ARM_LPAE_PTE_L1_ADDR_MASK);
+		if (addr < 0x80000000) {
+			*pte |= (ARM_LPAE_MAIR_ATTR_IDX_DEV <<
+				 ARM_LPAE_PTE_ATTRINDX);
+			if (dom == PCIE_PAXC)
+				*pte |= (1 << ARM_LPAE_PTE_NS);
+		} else {
+			*pte |= (ARM_LPAE_MAIR_ATTR_IDX_CACHE <<
+				 ARM_LPAE_PTE_ATTRINDX);
+			*pte |= (1 << ARM_LPAE_PTE_NS);
+		}
+		*pte |= (ARM_LPAE_PTE_AP_EL0_RW << ARM_LPAE_PTE_AP);
+		*pte |= (ARM_LPAE_PTE_SH_INNER << ARM_LPAE_PTE_SH);
+		*pte |= (1 << ARM_LPAE_PTE_AF);
+		*pte |= ARM_LPAE_PTE_VALID;
+
+		addr += ARM_LPAE_PTE_L1_BLOCK_SIZE;
+	}
+}
+
+void arm_smmu_create_identity_map(enum iommu_domain dom)
+{
+	struct arm_smmu_device iommu;
+	struct arm_smmu_device *smmu = &iommu;
+	uint32_t reg, reg2;
+	unsigned long long reg64;
+	uint32_t idx;
+	uint16_t asid;
+	unsigned int context_bank_index;
+	unsigned long long pg_table_base;
+
+	smmu->base = (uint8_t *) SMMU_BASE;
+	reg = mmio_read_32((uintptr_t) (ARM_SMMU_GR0(smmu) + ARM_SMMU_GR0_ID1));
+	smmu->pgshift = (reg & ID1_PAGESIZE) ? 16 : 12;
+	smmu->size = ARM_SMMU_RES_SIZE;
+	smmu->stream_ids = NULL;
+
+	switch (dom) {
+	case PCIE_PAXC:
+		smmu->stream_ids = &paxc_stream_ids[0];
+		smmu->stream_ids_mask = &paxc_stream_ids_mask[0];
+		smmu->streams = ARRAY_SIZE(paxc_stream_ids);
+		context_bank_index = SMMU_CTX_BANK_IDX;
+		pg_table_base = ARM_LPAE_PGTBL_PHYS;
+		break;
+	case DOMAIN_CRMU:
+		smmu->stream_ids = &crmu_stream_ids[0];
+		smmu->stream_ids_mask = &crmu_stream_ids_mask[0];
+		smmu->streams = ARRAY_SIZE(crmu_stream_ids);
+		context_bank_index = SMMU_CTX_BANK_IDX_SECURE_CRMU;
+		pg_table_base = ARM_LPAE_PGTBL_PHYS_CRMU;
+		break;
+	default:
+		ERROR("domain not supported\n");
+		return;
+	}
+
+	if (smmu->streams > NUM_OF_SMRS) {
+		INFO("can not support more than %d sids\n", NUM_OF_SMRS);
+		return;
+	}
+
+	/* set up iommu dev. */
+	for (idx = 0; idx < smmu->streams; idx++) {
+		/* S2CR. */
+		smmu->s2cr[idx].type = S2CR_TYPE_TRANS;
+		smmu->s2cr[idx].privcfg = S2CR_PRIVCFG_DEFAULT;
+		smmu->s2cr[idx].cbndx = context_bank_index;
+		smmu->cfg[idx].cbndx = context_bank_index;
+		smmu->cfg[idx].cbar = STG1_WITH_STG2_BYPASS << CBAR_TYPE_SHIFT;
+		arm_smmu_s2cr_cfg(smmu, idx);
+
+		/* SMR. */
+		smmu->smr[idx].mask = smmu->stream_ids_mask[idx];
+		smmu->smr[idx].id = smmu->stream_ids[idx];
+		smmu->smr[idx].valid = 1;
+		arm_smmu_smr_cfg(smmu, idx);
+
+		/* CBA2R. 64-bit Translation */
+		mmio_write_32((uintptr_t) (ARM_SMMU_GR1(smmu) +
+			      ARM_SMMU_GR1_CBA2R(smmu->cfg[idx].cbndx)),
+			      0x1);
+		/* CBAR.*/
+		reg = smmu->cfg[idx].cbar;
+		reg |= (CBAR_S1_BPSHCFG_NSH << CBAR_S1_BPSHCFG_SHIFT) |
+		       (CBAR_S1_MEMATTR_WB << CBAR_S1_MEMATTR_SHIFT);
+
+		mmio_write_32((uintptr_t) (ARM_SMMU_GR1(smmu) +
+			      ARM_SMMU_GR1_CBAR(smmu->cfg[idx].cbndx)),
+			      reg);
+
+		/* TTBCR. */
+		reg64 = (ARM_LPAE_TCR_SH_IS << ARM_LPAE_TCR_SH0_SHIFT) |
+		      (ARM_LPAE_TCR_RGN_WBWA << ARM_LPAE_TCR_IRGN0_SHIFT) |
+		      (ARM_LPAE_TCR_RGN_WBWA << ARM_LPAE_TCR_ORGN0_SHIFT);
+		reg64 |= ARM_LPAE_TCR_TG0_4K;
+		reg64 |= (ARM_LPAE_TCR_PS_40_BIT << ARM_LPAE_TCR_IPS_SHIFT);
+		/* ias 40 bits.*/
+		reg64 |= TTBCR_T0SZ(40) << ARM_LPAE_TCR_T0SZ_SHIFT;
+		/* Disable speculative walks through TTBR1 */
+		reg64 |= ARM_LPAE_TCR_EPD1;
+		reg = (uint32_t) reg64;
+		reg2 = (uint32_t) (reg64 >> 32);
+		reg2 |= TTBCR2_SEP_UPSTREAM;
+		reg2 |= TTBCR2_AS;
+
+		mmio_write_32((uintptr_t) (ARM_SMMU_CB_BASE(smmu) +
+			      ARM_SMMU_CB(smmu, smmu->cfg[idx].cbndx) +
+			      ARM_SMMU_CB_TTBCR2), reg2);
+
+		mmio_write_32((uintptr_t) (ARM_SMMU_CB_BASE(smmu) +
+			      ARM_SMMU_CB(smmu, smmu->cfg[idx].cbndx) +
+			      ARM_SMMU_CB_TTBCR), reg);
+
+		/* TTBR0. */
+		asid = smmu->cfg[idx].cbndx;
+		reg64 = pg_table_base;
+		reg64 |= (unsigned long long) asid << TTBRn_ASID_SHIFT;
+
+		mmio_write_64((uintptr_t) (ARM_SMMU_CB_BASE(smmu) +
+			      ARM_SMMU_CB(smmu, smmu->cfg[idx].cbndx) +
+			      ARM_SMMU_CB_TTBR0), reg64);
+		/* TTBR1. */
+		reg64 = 0;
+		reg64 |= (unsigned long long) asid << TTBRn_ASID_SHIFT;
+
+		mmio_write_64((uintptr_t) (ARM_SMMU_CB_BASE(smmu) +
+			      ARM_SMMU_CB(smmu, smmu->cfg[idx].cbndx) +
+			      ARM_SMMU_CB_TTBR1), reg64);
+		/* MAIR. */
+		reg = (ARM_LPAE_MAIR_ATTR_NC
+			<< ARM_LPAE_MAIR_ATTR_SHIFT
+			(ARM_LPAE_MAIR_ATTR_IDX_NC)) |
+			(ARM_LPAE_MAIR_ATTR_WBRWA <<
+			ARM_LPAE_MAIR_ATTR_SHIFT
+			(ARM_LPAE_MAIR_ATTR_IDX_CACHE)) |
+			(ARM_LPAE_MAIR_ATTR_DEVICE <<
+			ARM_LPAE_MAIR_ATTR_SHIFT
+			(ARM_LPAE_MAIR_ATTR_IDX_DEV));
+
+		mmio_write_32((uintptr_t) (ARM_SMMU_CB_BASE(smmu) +
+			      ARM_SMMU_CB(smmu, smmu->cfg[idx].cbndx) +
+			      ARM_SMMU_CB_S1_MAIR0), reg);
+
+		/* MAIR1. */
+		reg = 0;
+		mmio_write_32((uintptr_t) (ARM_SMMU_CB_BASE(smmu) +
+			      ARM_SMMU_CB(smmu, smmu->cfg[idx].cbndx) +
+			      ARM_SMMU_CB_S1_MAIR1), reg);
+		/* SCTLR. */
+		reg = SCTLR_CFIE | SCTLR_CFRE | SCTLR_AFE | SCTLR_TRE | SCTLR_M;
+		/* stage 1.*/
+		reg |= SCTLR_S1_ASIDPNE;
+		mmio_write_32((uintptr_t) (ARM_SMMU_CB_BASE(smmu) +
+			      ARM_SMMU_CB(smmu, smmu->cfg[idx].cbndx) +
+			      ARM_SMMU_CB_SCTLR), reg);
+	}
+	smmu_set_pgtbl(smmu, dom, (uint64_t *)pg_table_base);
+}
diff --git a/plat/brcm/board/stingray/src/ncsi.c b/plat/brcm/board/stingray/src/ncsi.c
new file mode 100644
index 0000000..58ea9e2
--- /dev/null
+++ b/plat/brcm/board/stingray/src/ncsi.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2019-2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdbool.h>
+
+#include <common/debug.h>
+#include <lib/mmio.h>
+
+#include <ncsi.h>
+#include <sr_def.h>
+#include <sr_utils.h>
+
+static const char *const io_drives[] = {
+	"2mA", "4mA", "6mA", "8mA",
+	"10mA", "12mA", "14mA", "16mA"
+};
+
+void brcm_stingray_ncsi_init(void)
+{
+	unsigned int i = 0;
+	unsigned int selx = 0;
+
+#if NCSI_IO_DRIVE_STRENGTH_MA == 2
+	selx = 0x0;
+#elif NCSI_IO_DRIVE_STRENGTH_MA == 4
+	selx = 0x1;
+#elif NCSI_IO_DRIVE_STRENGTH_MA == 6
+	selx = 0x2;
+#elif NCSI_IO_DRIVE_STRENGTH_MA == 8
+	selx = 0x3;
+#elif NCSI_IO_DRIVE_STRENGTH_MA == 10
+	selx = 0x4;
+#elif NCSI_IO_DRIVE_STRENGTH_MA == 12
+	selx = 0x5;
+#elif NCSI_IO_DRIVE_STRENGTH_MA == 14
+	selx = 0x6;
+#elif NCSI_IO_DRIVE_STRENGTH_MA == 16
+	selx = 0x7;
+#else
+	ERROR("Unsupported NCSI_IO_DRIVE_STRENGTH_MA. Please check it.\n");
+	return;
+#endif
+	INFO("ncsi io drives: %s\n", io_drives[selx]);
+
+	for (i = 0; i < NITRO_NCSI_IOPAD_CONTROL_NUM; i++) {
+		mmio_clrsetbits_32((NITRO_NCSI_IOPAD_CONTROL_BASE + (i * 4)),
+				   PAD_SELX_MASK, PAD_SELX_VALUE(selx));
+	}
+
+	INFO("ncsi init done\n");
+}
diff --git a/plat/brcm/board/stingray/src/paxb.c b/plat/brcm/board/stingray/src/paxb.c
new file mode 100644
index 0000000..28065f0
--- /dev/null
+++ b/plat/brcm/board/stingray/src/paxb.c
@@ -0,0 +1,911 @@
+/*
+ * Copyright (c) 2016 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <errno.h>
+#include <stdbool.h>
+
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+
+#include <paxb.h>
+#include <sr_def.h>
+#include <sr_utils.h>
+
+#define PCIE_CORE_PWR_ARR_POWERON        0x8
+#define PCIE_CORE_PWR_ARR_POWEROK        0x4
+#define PCIE_CORE_PWR_POWERON            0x2
+#define PCIE_CORE_PWR_POWEROK            0x1
+
+#define PCIE_CORE_USER_CFG               (PCIE_CORE_BASE + 0x38)
+#define PCIE_PAXB_SMMU_SID_CFG           (PCIE_CORE_BASE + 0x60)
+#ifdef SID_B8_D1_F1
+#define PAXB_SMMU_SID_CFG_BUS_WIDTH      (0x8 << 8)
+#define PAXB_SMMU_SID_CFG_DEV_WIDTH      (0x1 << 12)
+#define PAXB_SMMU_SID_CFG_FUN_WIDTH      (0x1 << 16)
+#else
+#define PAXB_SMMU_SID_CFG_BUS_WIDTH      (0x2 << 8)
+#define PAXB_SMMU_SID_CFG_DEV_WIDTH      (0x5 << 12)
+#define PAXB_SMMU_SID_CFG_FUN_WIDTH      (0x3 << 16)
+#endif
+
+#define PAXB_APB_TIMEOUT_COUNT_OFFSET 0x034
+
+/* allow up to 5 ms for each power switch to stabilize */
+#define PCIE_CORE_PWR_TIMEOUT_MS      5
+
+/* wait 1 microsecond for PCIe core soft reset */
+#define PCIE_CORE_SOFT_RST_DELAY_US 1
+
+/*
+ * List of PAXB APB registers
+ */
+#define PAXB_BASE                        0x48000000
+#define PAXB_BASE_OFFSET                 0x4000
+#define PAXB_OFFSET(core)                (PAXB_BASE + \
+					  (core) * PAXB_BASE_OFFSET)
+
+#define PAXB_CLK_CTRL_OFFSET             0x000
+#define PAXB_EP_PERST_SRC_SEL_MASK       (1 << 2)
+#define PAXB_EP_MODE_PERST_MASK          (1 << 1)
+#define PAXB_RC_PCIE_RST_OUT_MASK        (1 << 0)
+
+#define PAXB_MAX_IMAP_WINDOWS            8
+#define PAXB_IMAP_REG_WIDTH              8
+#define PAXB_IMAP0_REG_WIDTH             4
+#define PAXB_AXUSER_REG_WIDTH            4
+
+#define PAXB_CFG_IND_ADDR_OFFSET         0x120
+#define PAXB_CFG_IND_DATA_OFFSET         0x124
+#define PAXB_CFG_IND_ADDR_MASK           0x1ffc
+#define PAXB_CFG_CFG_TYPE_MASK           0x1
+
+#define PAXB_EP_CFG_ADDR_OFFSET          0x1f8
+#define PAXB_EP_CFG_DATA_OFFSET          0x1fc
+#define PAXB_EP_CFG_ADDR_MASK            0xffc
+#define PAXB_EP_CFG_TYPE_MASK            0x1
+
+#define PAXB_0_DEFAULT_IMAP              0xed0
+#define DEFAULT_ADDR_INVALID             BIT(0)
+#define PAXB_0_DEFAULT_IMAP_AXUSER       0xed8
+#define PAXB_0_DEFAULT_IMAP_AXCACHE      0xedc
+#define IMAP_AXCACHE                     0xff
+#define OARR_VALID                       BIT(0)
+#define IMAP_VALID                       BIT(0)
+
+#define PAXB_IMAP0_BASE_OFFSET           0xc00
+#define PAXB_IARR0_BASE_OFFSET           0xd00
+#define PAXB_IMAP0_OFFSET(idx)           (PAXB_IMAP0_BASE_OFFSET + \
+					  (idx) * PAXB_IMAP0_REG_WIDTH)
+#define PAXB_IMAP0_WINDOW_SIZE           0x1000
+
+#define PAXB_IMAP2_OFFSET                0xcc0
+#define PAXB_IMAP0_REGS_TYPE_OFFSET      0xcd0
+#define PAXB_IARR2_LOWER_OFFSET          0xd10
+
+#define PAXB_IMAP3_BASE_OFFSET           0xe08
+#define PAXB_IMAP3_OFFSET(idx)           (PAXB_IMAP3_BASE_OFFSET + \
+					  (idx) * PAXB_IMAP_REG_WIDTH)
+
+#define PAXB_IMAP3_0_AXUSER_B_OFFSET     0xe48
+#define PAXB_IMAP3_0_AXUSER_OFFSET(idx)  (PAXB_IMAP3_0_AXUSER_B_OFFSET + \
+					  (idx) * PAXB_AXUSER_REG_WIDTH)
+
+#define PAXB_IMAP4_BASE_OFFSET           0xe70
+#define PAXB_IMAP4_OFFSET(idx)           (PAXB_IMAP4_BASE_OFFSET + \
+					  (idx) * PAXB_IMAP_REG_WIDTH)
+
+#define PAXB_IMAP4_0_AXUSER_B_OFFSET     0xeb0
+#define PAXB_IMAP4_0_AXUSER_OFFSET(idx)  (PAXB_IMAP4_0_AXUSER_B_OFFSET + \
+					  (idx) * PAXB_AXUSER_REG_WIDTH)
+
+#define PAXB_CFG_LINK_STATUS_OFFSET      0xf0c
+#define PAXB_CFG_PHYLINKUP_MASK          (1 << 3)
+#define PAXB_CFG_DL_ACTIVE_MASK          (1 << 2)
+
+#define PAXB_IMAP0_0_AXUSER_OFFSET       0xf60
+#define PAXB_IMAP2_AXUSER_OFFSET         0xfe0
+
+/* cacheable write-back, allocate on both reads and writes */
+#define IMAP_ARCACHE                     0x0f0
+#define IMAP_AWCACHE                     0xf00
+/* normal access, nonsecure access, and data access */
+/* AWQOS:0xe and ARQOS:0xa */
+/* AWPROT:0x2 and ARPROT:0x1 */
+#define IMAP_AXUSER                      0x002e002a
+
+/*
+ * List of NIC security and PIPEMUX related registers
+ */
+#define SR_PCIE_NIC_SECURITY_BASE      0x58100000
+#define NS3Z_PCIE_NIC_SECURITY_BASE    0x48100000
+
+#define GITS_TRANSLATER                0x63c30000
+
+#define VENDOR_ID                 0x14e4
+#define CFG_RC_DEV_ID             0x434
+#define CFG_RC_DEV_SUBID          0x438
+#define PCI_BRIDGE_CTRL_REG_OFFSET     0x43c
+#define PCI_CLASS_BRIDGE_MASK          0xffff00
+#define PCI_CLASS_BRIDGE_SHIFT         8
+#define PCI_CLASS_BRIDGE_PCI           0x0604
+
+/*
+ * List of PAXB RC configuration space registers
+ */
+
+/* first capability list entry */
+#define PCI_CAPABILITY_LIST_OFFSET    0x34
+#define PCI_CAPABILITY_SPEED_OFFSET   0xc
+#define PCI_EP_CAPABILITY_OFFSET      0x10
+
+#define CFG_RC_LINK_STATUS_CTRL_2     0x0dc
+#define CFG_RC_LINK_SPEED_SHIFT       0
+#define CFG_RC_LINK_SPEED_MASK        (0xf << CFG_RC_LINK_SPEED_SHIFT)
+
+#define CFG_RC_DEVICE_CAP             0x4d4
+#define CFG_RC_DEVICE_CAP_MPS_SHIFT   0
+#define CFG_RC_DEVICE_CAP_MPS_MASK    (0x7 << CFG_RC_DEVICE_CAP_MPS_SHIFT)
+/* MPS 256 bytes */
+#define CFG_RC_DEVICE_CAP_MPS_256B    (0x1 << CFG_RC_DEVICE_CAP_MPS_SHIFT)
+/* MPS 512 bytes */
+#define CFG_RC_DEVICE_CAP_MPS_512B    (0x2 << CFG_RC_DEVICE_CAP_MPS_SHIFT)
+
+#define CFG_RC_TL_FCIMM_NP_LIMIT       0xa10
+#define CFG_RC_TL_FCIMM_NP_VAL         0x01500000
+#define CFG_RC_TL_FCIMM_P_LIMIT        0xa14
+#define CFG_RC_TL_FCIMM_P_VAL          0x03408080
+
+#define CFG_RC_LINK_CAP               0x4dc
+#define CFG_RC_LINK_CAP_SPEED_SHIFT   0
+#define CFG_RC_LINK_CAP_SPEED_MASK    (0xf << CFG_RC_LINK_CAP_SPEED_SHIFT)
+#define CFG_RC_LINK_CAP_WIDTH_SHIFT   4
+#define CFG_RC_LINK_CAP_WIDTH_MASK    (0x1f << CFG_RC_LINK_CAP_WIDTH_SHIFT)
+
+#define CFG_LINK_CAP_RC               0x4f0
+#define CFG_RC_DL_ACTIVE_SHIFT        0
+#define CFG_RC_DL_ACTIVE_MASK         (0x1 << CFG_RC_DL_ACTIVE_SHIFT)
+#define CFG_RC_SLOT_CLK_SHIFT         1
+#define CFG_RC_SLOT_CLK_MASK          (0x1 << CFG_RC_SLOT_CLK_SHIFT)
+
+#define CFG_ROOT_CAP_RC               0x4f8
+#define CFG_ROOT_CAP_LTR_SHIFT        1
+#define CFG_ROOT_CAP_LTR_MASK         (0x1 << CFG_ROOT_CAP_LTR_SHIFT)
+
+#define CFG_RC_CLKREQ_ENABLED         0x4fc
+#define CFG_RC_CLKREQ_ENABLED_SHIFT   0
+#define CFG_RC_CLKREQ_ENABLED_MASK    (0x1 << CFG_RC_CLKREQ_ENABLED_SHIFT)
+
+#define CFG_RC_COEFF_ADDR             0x638
+
+#define CFG_RC_TL_CTRL_0              0x800
+#define RC_MEM_DW_CHK_MASK            0x03fe
+
+#define CFG_RC_PDL_CTRL_4             0x1010
+#define NPH_FC_INIT_SHIFT             24
+#define NPH_FC_INIT_MASK              (U(0xff) << NPH_FC_INIT_SHIFT)
+#define PD_FC_INIT_SHIFT              12
+#define PD_FC_INIT_MASK               (0xffff << PD_FC_INIT_SHIFT)
+
+#define CFG_RC_PDL_CTRL_5             0x1014
+#define PH_INIT_SHIFT                 0
+#define PH_INIT_MASK                  (0xff << PH_INIT_SHIFT)
+
+#define DL_STATUS_OFFSET              0x1048
+#define PHYLINKUP                     BIT(13)
+
+#define PH_INIT                       0x10
+#define PD_FC_INIT                    0x100
+#define NPH_FC_INIT                   0x8
+
+#define SRP_PH_INIT                   0x7F
+#define SRP_PD_FC_INIT                0x200
+#define SRP_NPH_FC_INIT               0x7F
+
+#define CFG_ADDR_BUS_NUM_SHIFT        20
+#define CFG_ADDR_DEV_NUM_SHIFT        15
+#define CFG_ADDR_FUNC_NUM_SHIFT       12
+#define CFG_ADDR_REG_NUM_SHIFT        2
+#define CFG_ADDR_REG_NUM_MASK         0x00000ffc
+#define CFG_ADDR_CFG_TYPE_MASK        0x00000003
+
+#define DL_LINK_UP_TIMEOUT_MS         1000
+
+#define CFG_RETRY_STATUS              0xffff0001
+#define CRS_TIMEOUT_MS                5000
+
+/* create EP config data to write */
+#define DEF_BUS_NO                    1 /* default bus 1 */
+#define DEF_SLOT_NO                   0 /* default slot 0 */
+#define DEF_FN_NO                     0 /* default fn 0 */
+
+#define EP_CONFIG_VAL(bus_no, slot, fn, where) \
+	(((bus_no) << CFG_ADDR_BUS_NUM_SHIFT) | \
+	((slot) << CFG_ADDR_DEV_NUM_SHIFT) | \
+	((fn) << CFG_ADDR_FUNC_NUM_SHIFT) | \
+	((where) & CFG_ADDR_REG_NUM_MASK) | \
+	(1 & CFG_ADDR_CFG_TYPE_MASK))
+
+/* PAXB security offset */
+#define PAXB_SECURITY_IDM_OFFSET 0x1c
+#define PAXB_SECURITY_APB_OFFSET 0x24
+#define PAXB_SECURITY_ECAM_OFFSET 0x3c
+
+#define paxb_get_config(type) paxb_get_##type##_config()
+
+static unsigned int paxb_sec_reg_offset[] = {
+	0x0c, /* PAXB0 AXI */
+	0x10, /* PAXB1 AXI */
+	0x14, /* PAXB2 AXI */
+	0x18, /* PAXB3 AXI */
+	0x20, /* PAXB4 AXI */
+	0x28, /* PAXB5 AXI */
+	0x2c, /* PAXB6 AXI */
+	0x30, /* PAXB7 AXI */
+	0x24, /* PAXB APB */
+};
+
+const paxb_cfg *paxb;
+
+/*
+ * Given a PIPEMUX strap and PCIe core index, this function returns 1 if a
+ * PCIe core needs to be enabled
+ */
+int pcie_core_needs_enable(unsigned int core_idx)
+{
+	if (paxb->core_needs_enable)
+		return paxb->core_needs_enable(core_idx);
+
+	return 0;
+}
+
+static void pcie_set_default_tx_coeff(uint32_t core_idx, uint32_t link_width)
+{
+	unsigned int lanes = 0;
+	uint32_t data, addr;
+
+	addr = CFG_RC_COEFF_ADDR;
+	for (lanes = 0; lanes < link_width; lanes = lanes + 2) {
+		data = paxb_rc_cfg_read(core_idx, addr);
+		data &= 0xf0f0f0f0;
+		data |= (7 & 0xf);
+		data |= (7 & 0xf) << 8;
+		data |= (7 & 0xf) << 16;
+		data |= (7 & 0xf) << 24;
+
+		paxb_rc_cfg_write(core_idx, addr, data);
+		addr += 4;
+	}
+}
+
+static int paxb_rc_link_init(void)
+{
+	uint32_t val, link_speed;
+	unsigned int link_width;
+	uint32_t core_idx;
+
+	for (core_idx = 0; core_idx < paxb->num_cores; core_idx++) {
+		if (!pcie_core_needs_enable(core_idx))
+			continue;
+
+		link_width = paxb->get_link_width(core_idx);
+		if (!link_width) {
+			ERROR("Unsupported PIPEMUX\n");
+			return -EOPNOTSUPP;
+		}
+
+		link_speed = paxb->get_link_speed();
+		/* program RC's link cap reg to advertise proper link width */
+		val = paxb_rc_cfg_read(core_idx, CFG_RC_LINK_CAP);
+		val &= ~CFG_RC_LINK_CAP_WIDTH_MASK;
+		val |= (link_width << CFG_RC_LINK_CAP_WIDTH_SHIFT);
+		paxb_rc_cfg_write(core_idx, CFG_RC_LINK_CAP, val);
+
+		/* program RC's link cap reg to advertise proper link speed */
+		val = paxb_rc_cfg_read(core_idx, CFG_RC_LINK_CAP);
+		val &= ~CFG_RC_LINK_CAP_SPEED_MASK;
+		val |= link_speed << CFG_RC_LINK_CAP_SPEED_SHIFT;
+		paxb_rc_cfg_write(core_idx, CFG_RC_LINK_CAP, val);
+
+		/* also need to program RC's link status control register */
+		val = paxb_rc_cfg_read(core_idx, CFG_RC_LINK_STATUS_CTRL_2);
+		val &= ~(CFG_RC_LINK_SPEED_MASK);
+		val |= link_speed << CFG_RC_LINK_SPEED_SHIFT;
+		paxb_rc_cfg_write(core_idx, CFG_RC_LINK_STATUS_CTRL_2, val);
+
+#ifdef WAR_PLX_PRESET_PARITY_FAIL
+		/* WAR to avoid crash with PLX switch in GEN3*/
+		/* While PRESET, PLX switch is not fixing parity so disabled */
+		val = paxb_rc_cfg_read(core_idx, CFG_RC_REG_PHY_CTL_10);
+		val &= ~(PHY_CTL_10_GEN3_MATCH_PARITY);
+		paxb_rc_cfg_write(core_idx, CFG_RC_REG_PHY_CTL_10, val);
+#endif
+		pcie_set_default_tx_coeff(core_idx, link_width);
+	}
+	return 0;
+}
+
+#ifdef PAXB_LINKUP
+static void paxb_perst_ctrl(unsigned int core_idx, bool assert)
+{
+	uint32_t clk_ctrl = PAXB_OFFSET(core_idx) + PAXB_CLK_CTRL_OFFSET;
+
+	if (assert) {
+		mmio_clrbits_32(clk_ctrl, PAXB_EP_PERST_SRC_SEL_MASK |
+				PAXB_EP_MODE_PERST_MASK |
+				PAXB_RC_PCIE_RST_OUT_MASK);
+		udelay(250);
+	} else {
+		mmio_setbits_32(clk_ctrl, PAXB_RC_PCIE_RST_OUT_MASK);
+		mdelay(100);
+	}
+}
+
+static void paxb_start_link_up(void)
+{
+	unsigned int core_idx;
+	uint32_t val, timeout;
+
+	for (core_idx = 0; core_idx < paxb->num_cores; core_idx++) {
+		if (!pcie_core_needs_enable(core_idx))
+			continue;
+
+		/* toggle PERST */
+		paxb_perst_ctrl(core_idx, true);
+		paxb_perst_ctrl(core_idx, false);
+
+		timeout = DL_LINK_UP_TIMEOUT_MS;
+		/* wait for Link up */
+		do {
+			val = mmio_read_32(PAXB_OFFSET(core_idx) +
+					   PAXB_CFG_LINK_STATUS_OFFSET);
+			if (val & PAXB_CFG_DL_ACTIVE_MASK)
+				break;
+
+			mdelay(1);
+		} while (--timeout);
+
+		if (!timeout)
+			ERROR("PAXB core %u link is down\n", core_idx);
+	}
+}
+#endif
+
+static void pcie_core_soft_reset(unsigned int core_idx)
+{
+	uint32_t offset = core_idx * PCIE_CORE_PWR_OFFSET;
+	uintptr_t ctrl = (uintptr_t)(PCIE_CORE_SOFT_RST_CFG_BASE + offset);
+
+	/* Put PCIe core in soft reset */
+	mmio_clrbits_32(ctrl, PCIE_CORE_SOFT_RST);
+
+	/* Wait for 1 us before pulling PCIe core out of soft reset */
+	udelay(PCIE_CORE_SOFT_RST_DELAY_US);
+
+	mmio_setbits_32(ctrl, PCIE_CORE_SOFT_RST);
+}
+
+static int pcie_core_pwron_switch(uintptr_t ctrl, uintptr_t status,
+				  uint32_t mask)
+{
+	uint32_t val;
+	unsigned int timeout = PCIE_CORE_PWR_TIMEOUT_MS;
+
+	/* enable switch */
+	mmio_setbits_32(ctrl, mask);
+
+	/* now wait for it to stabilize */
+	do {
+		val = mmio_read_32(status);
+		if ((val & mask) == mask)
+			return 0;
+		mdelay(1);
+	} while (--timeout);
+
+	return -EIO;
+}
+
+static int pcie_core_pwr_seq(uintptr_t ctrl, uintptr_t status)
+{
+	int ret;
+
+	/*
+	 * Enable the switch with the following sequence:
+	 * 1. Array weak switch output switch
+	 * 2. Array strong switch
+	 * 3. Weak switch output acknowledge
+	 * 4. Strong switch output acknowledge
+	 */
+	ret = pcie_core_pwron_switch(ctrl, status, PCIE_CORE_PWR_ARR_POWERON);
+	if (ret)
+		return ret;
+
+	ret = pcie_core_pwron_switch(ctrl, status, PCIE_CORE_PWR_ARR_POWEROK);
+	if (ret)
+		return ret;
+
+	ret = pcie_core_pwron_switch(ctrl, status, PCIE_CORE_PWR_POWERON);
+	if (ret)
+		return ret;
+
+	ret = pcie_core_pwron_switch(ctrl, status, PCIE_CORE_PWR_POWEROK);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+/*
+ * This function enables PCIe core and PAXB memory buffer power, and then
+ * remove the PCIe core from isolation
+ */
+static int pcie_core_pwr_init(unsigned int core_idx)
+{
+	int ret;
+	uint32_t offset = core_idx * PCIE_CORE_PWR_OFFSET;
+	uintptr_t ctrl, status;
+
+	/* enable mem power to PCIe core */
+	ctrl = (uintptr_t)(PCIE_CORE_MEM_PWR_BASE + offset);
+	status = (uintptr_t)(PCIE_CORE_MEM_PWR_STATUS_BASE + offset);
+	ret = pcie_core_pwr_seq(ctrl, status);
+	if (ret) {
+		ERROR("PCIe core mem power failed\n");
+		return ret;
+	}
+
+	/* now enable mem power to PAXB wrapper */
+	ctrl = (uintptr_t)(PCIE_PAXB_MEM_PWR_BASE + offset);
+	status = (uintptr_t)(PCIE_PAXB_MEM_PWR_STATUS_BASE + offset);
+	ret = pcie_core_pwr_seq(ctrl, status);
+	if (ret) {
+		ERROR("PAXB mem power failed\n");
+		return ret;
+	}
+
+	/* now remove power isolation */
+	ctrl = (uintptr_t)(PCIE_CORE_ISO_CFG_BASE + offset);
+	mmio_clrbits_32(ctrl, PCIE_CORE_ISO | PCIE_CORE_MEM_ISO);
+
+	return 0;
+}
+
+static void pcie_ss_reset(void)
+{
+	mmio_setbits_32(CDRU_MISC_RESET_CONTROL,
+			1 << CDRU_MISC_RESET_CONTROL__CDRU_PCIE_RESET_N_R);
+}
+
+/*
+ * This function reads the PIPEMUX strap, figures out all the PCIe cores that
+ * need to be enabled and enable the mem power for those cores
+ */
+static int pcie_cores_init(void)
+{
+	int ret;
+	uint32_t core_idx;
+
+	if (paxb->pipemux_init) {
+		ret = paxb->pipemux_init();
+		if (ret)
+			return ret;
+	}
+
+	/* bring PCIe subsystem out of reset */
+	pcie_ss_reset();
+
+	/* power up all PCIe cores that will be used as RC */
+	for (core_idx = 0; core_idx < paxb->num_cores; core_idx++) {
+		if (!pcie_core_needs_enable(core_idx))
+			continue;
+
+		ret = pcie_core_pwr_init(core_idx);
+		if (ret) {
+			ERROR("PCIe core %u power up failed\n", core_idx);
+			return ret;
+		}
+
+		pcie_core_soft_reset(core_idx);
+
+		VERBOSE("PCIe core %u is powered up\n", core_idx);
+	}
+
+	return ret;
+}
+
+void paxb_rc_cfg_write(unsigned int core_idx, unsigned int where,
+			      uint32_t val)
+{
+	mmio_write_32(PAXB_OFFSET(core_idx) + PAXB_CFG_IND_ADDR_OFFSET,
+		      (where & PAXB_CFG_IND_ADDR_MASK) |
+		      PAXB_CFG_CFG_TYPE_MASK);
+	mmio_write_32(PAXB_OFFSET(core_idx) + PAXB_CFG_IND_DATA_OFFSET, val);
+}
+
+unsigned int paxb_rc_cfg_read(unsigned int core_idx, unsigned int where)
+{
+	unsigned int val;
+
+	mmio_write_32(PAXB_OFFSET(core_idx) + PAXB_CFG_IND_ADDR_OFFSET,
+		      (where & PAXB_CFG_IND_ADDR_MASK) |
+		      PAXB_CFG_CFG_TYPE_MASK);
+	val = mmio_read_32(PAXB_OFFSET(core_idx) + PAXB_CFG_IND_DATA_OFFSET);
+
+	return val;
+}
+
+static void paxb_cfg_mps(void)
+{
+	uint32_t val, core_idx, mps;
+
+	for (core_idx = 0; core_idx < paxb->num_cores; core_idx++) {
+		if (!pcie_core_needs_enable(core_idx))
+			continue;
+
+		val = paxb_rc_cfg_read(core_idx, CFG_RC_DEVICE_CAP);
+		val &= ~CFG_RC_DEVICE_CAP_MPS_MASK;
+		mps = CFG_RC_DEVICE_CAP_MPS_256B;
+		if (core_idx == 0 || core_idx == 1 ||
+		    core_idx == 6 || core_idx == 7) {
+			mps = CFG_RC_DEVICE_CAP_MPS_512B;
+		}
+		val |= mps;
+		paxb_rc_cfg_write(core_idx, CFG_RC_DEVICE_CAP, val);
+	}
+}
+
+static void paxb_cfg_dev_id(void)
+{
+	uint32_t val, core_idx;
+	uint32_t device_id;
+
+	device_id = paxb->device_id;
+
+	for (core_idx = 0; core_idx < paxb->num_cores; core_idx++) {
+		if (!pcie_core_needs_enable(core_idx))
+			continue;
+
+		/* Set Core in RC mode */
+		mmio_setbits_32(PCIE_CORE_USER_CFG +
+				(core_idx * PCIE_CORE_PWR_OFFSET), 1);
+
+		/* force class to PCI_CLASS_BRIDGE_PCI (0x0604) */
+		val = paxb_rc_cfg_read(core_idx, PCI_BRIDGE_CTRL_REG_OFFSET);
+		val &= ~PCI_CLASS_BRIDGE_MASK;
+		val |= (PCI_CLASS_BRIDGE_PCI << PCI_CLASS_BRIDGE_SHIFT);
+		paxb_rc_cfg_write(core_idx, PCI_BRIDGE_CTRL_REG_OFFSET, val);
+
+		val = (VENDOR_ID << 16) | device_id;
+		paxb_rc_cfg_write(core_idx, CFG_RC_DEV_ID, val);
+
+		val = (device_id << 16) | VENDOR_ID;
+		paxb_rc_cfg_write(core_idx, CFG_RC_DEV_SUBID, val);
+	}
+}
+
+static void paxb_cfg_tgt_trn(void)
+{
+	uint32_t val, core_idx;
+
+	/*
+	 * Disable all mem Rd/Wr size check so it allows target read/write
+	 * transactions to be more than stipulated DW. As a result, PAXB root
+	 * complex will not abort these read/write transcations beyond
+	 * stipulated limit
+	 */
+	for (core_idx = 0; core_idx < paxb->num_cores; core_idx++) {
+		if (!pcie_core_needs_enable(core_idx))
+			continue;
+
+		val = paxb_rc_cfg_read(core_idx, CFG_RC_TL_CTRL_0);
+		val &= ~(RC_MEM_DW_CHK_MASK);
+		paxb_rc_cfg_write(core_idx, CFG_RC_TL_CTRL_0, val);
+	}
+}
+
+static void paxb_cfg_pdl_ctrl(void)
+{
+	uint32_t val, core_idx;
+	uint32_t nph, ph, pd;
+
+	/* increase the credit counter to 4 for non-posted header */
+	for (core_idx = 0; core_idx < paxb->num_cores; core_idx++) {
+		if (!pcie_core_needs_enable(core_idx))
+			continue;
+
+		nph = NPH_FC_INIT;
+		ph = PH_INIT;
+		pd = PD_FC_INIT;
+
+		if (core_idx == 0 || core_idx == 1 ||
+		    core_idx == 6 || core_idx == 7) {
+			nph = SRP_NPH_FC_INIT;
+			ph = SRP_PH_INIT;
+			pd = SRP_PD_FC_INIT;
+		}
+		val = paxb_rc_cfg_read(core_idx, CFG_RC_PDL_CTRL_4);
+		val &= ~NPH_FC_INIT_MASK;
+		val &= ~PD_FC_INIT_MASK;
+		val = val | (nph << NPH_FC_INIT_SHIFT);
+		val = val | (pd << PD_FC_INIT_SHIFT);
+		paxb_rc_cfg_write(core_idx, CFG_RC_PDL_CTRL_4, val);
+
+		val = paxb_rc_cfg_read(core_idx, CFG_RC_PDL_CTRL_5);
+		val &= ~PH_INIT_MASK;
+		val = val | (ph << PH_INIT_SHIFT);
+		paxb_rc_cfg_write(core_idx, CFG_RC_PDL_CTRL_5, val);
+
+		/*
+		 * ASIC to give more optmized value after further investigation.
+		 * till then this is important to have to get similar
+		 * performance on all the slots.
+		 */
+		paxb_rc_cfg_write(core_idx, CFG_RC_TL_FCIMM_NP_LIMIT,
+				CFG_RC_TL_FCIMM_NP_VAL);
+
+		paxb_rc_cfg_write(core_idx, CFG_RC_TL_FCIMM_P_LIMIT,
+				CFG_RC_TL_FCIMM_P_VAL);
+	}
+}
+
+static void paxb_cfg_clkreq(void)
+{
+	uint32_t val, core_idx;
+
+	for (core_idx = 0; core_idx < paxb->num_cores; core_idx++) {
+		if (!pcie_core_needs_enable(core_idx))
+			continue;
+
+		val = paxb_rc_cfg_read(core_idx, CFG_RC_CLKREQ_ENABLED);
+		val &= ~CFG_RC_CLKREQ_ENABLED_MASK;
+		paxb_rc_cfg_write(core_idx, CFG_RC_CLKREQ_ENABLED, val);
+	}
+}
+
+static void paxb_cfg_dl_active(bool enable)
+{
+	uint32_t val, core_idx;
+
+	for (core_idx = 0; core_idx < paxb->num_cores; core_idx++) {
+		if (!pcie_core_needs_enable(core_idx))
+			continue;
+
+		val = paxb_rc_cfg_read(core_idx, CFG_LINK_CAP_RC);
+		if (enable)
+			val |= CFG_RC_DL_ACTIVE_MASK;
+		else
+			val &= ~CFG_RC_DL_ACTIVE_MASK;
+		paxb_rc_cfg_write(core_idx, CFG_LINK_CAP_RC, val);
+	}
+}
+
+static void paxb_cfg_LTR(int enable)
+{
+	uint32_t val, core_idx;
+
+	for (core_idx = 0; core_idx < paxb->num_cores; core_idx++) {
+		if (!pcie_core_needs_enable(core_idx))
+			continue;
+
+		val = paxb_rc_cfg_read(core_idx, CFG_ROOT_CAP_RC);
+		if (enable)
+			val |= CFG_ROOT_CAP_LTR_MASK;
+		else
+			val &= ~CFG_ROOT_CAP_LTR_MASK;
+		paxb_rc_cfg_write(core_idx, CFG_ROOT_CAP_RC, val);
+	}
+}
+
+static void paxb_ib_regs_bypass(void)
+{
+	unsigned int i, j;
+
+	for (i = 0; i < paxb->num_cores; i++) {
+		if (!pcie_core_needs_enable(i))
+			continue;
+
+		/* Configure Default IMAP window */
+		mmio_write_32(PAXB_OFFSET(i) + PAXB_0_DEFAULT_IMAP,
+			      DEFAULT_ADDR_INVALID);
+		mmio_write_32(PAXB_OFFSET(i) + PAXB_0_DEFAULT_IMAP_AXUSER,
+			      IMAP_AXUSER);
+		mmio_write_32(PAXB_OFFSET(i) + PAXB_0_DEFAULT_IMAP_AXCACHE,
+			      IMAP_AXCACHE);
+
+		/* Configure MSI IMAP window */
+		mmio_setbits_32(PAXB_OFFSET(i) +
+				PAXB_IMAP0_REGS_TYPE_OFFSET,
+				0x1);
+		mmio_write_32(PAXB_OFFSET(i) + PAXB_IARR0_BASE_OFFSET,
+			      GITS_TRANSLATER | OARR_VALID);
+		for (j = 0; j < PAXB_MAX_IMAP_WINDOWS; j++) {
+			mmio_write_32(PAXB_OFFSET(i) + PAXB_IMAP0_OFFSET(j),
+				      (GITS_TRANSLATER +
+				       (j * PAXB_IMAP0_WINDOW_SIZE)) |
+				      IMAP_VALID);
+		}
+	}
+}
+
+static void paxb_ib_regs_init(void)
+{
+	unsigned int core_idx;
+
+	for (core_idx = 0; core_idx < paxb->num_cores; core_idx++) {
+		if (!pcie_core_needs_enable(core_idx))
+			continue;
+
+		/* initialize IARR2 to zero */
+		mmio_write_32(PAXB_OFFSET(core_idx) + PAXB_IARR2_LOWER_OFFSET,
+			      0x0);
+		mmio_setbits_32(PAXB_OFFSET(core_idx) +
+				PAXB_IMAP0_REGS_TYPE_OFFSET,
+				0x1);
+	}
+}
+
+static void paxb_cfg_apb_timeout(void)
+{
+	unsigned int core_idx;
+
+	for (core_idx = 0; core_idx < paxb->num_cores; core_idx++) {
+		if (!pcie_core_needs_enable(core_idx))
+			continue;
+
+		/* allow unlimited timeout */
+		mmio_write_32(PAXB_OFFSET(core_idx) +
+			PAXB_APB_TIMEOUT_COUNT_OFFSET,
+			0xFFFFFFFF);
+	}
+}
+
+static void paxb_smmu_cfg(void)
+{
+	unsigned int core_idx;
+	uint32_t offset;
+	uint32_t val;
+
+	for (core_idx = 0; core_idx < paxb->num_cores; core_idx++) {
+		if (!pcie_core_needs_enable(core_idx))
+			continue;
+
+		offset = core_idx * PCIE_CORE_PWR_OFFSET;
+		val = mmio_read_32(PCIE_PAXB_SMMU_SID_CFG + offset);
+		val &= ~(0xFFF00);
+		val |= (PAXB_SMMU_SID_CFG_FUN_WIDTH |
+			PAXB_SMMU_SID_CFG_DEV_WIDTH |
+			PAXB_SMMU_SID_CFG_BUS_WIDTH);
+		mmio_write_32(PCIE_PAXB_SMMU_SID_CFG + offset, val);
+		val = mmio_read_32(PCIE_PAXB_SMMU_SID_CFG + offset);
+		VERBOSE("smmu cfg reg 0x%x\n", val);
+	}
+}
+
+static void paxb_cfg_coherency(void)
+{
+	unsigned int i, j;
+
+	for (i = 0; i < paxb->num_cores; i++) {
+		if (!pcie_core_needs_enable(i))
+			continue;
+
+#ifdef USE_DDR
+		mmio_write_32(PAXB_OFFSET(i) + PAXB_IMAP2_OFFSET,
+			      IMAP_ARCACHE | IMAP_AWCACHE);
+#endif
+
+		mmio_write_32(PAXB_OFFSET(i) + PAXB_IMAP0_0_AXUSER_OFFSET,
+			      IMAP_AXUSER);
+
+		mmio_write_32(PAXB_OFFSET(i) + PAXB_IMAP2_AXUSER_OFFSET,
+			      IMAP_AXUSER);
+
+		for (j = 0; j < PAXB_MAX_IMAP_WINDOWS; j++) {
+#ifdef USE_DDR
+			mmio_write_32(PAXB_OFFSET(i) + PAXB_IMAP3_OFFSET(j),
+				      IMAP_ARCACHE | IMAP_AWCACHE);
+			mmio_write_32(PAXB_OFFSET(i) + PAXB_IMAP4_OFFSET(j),
+				      IMAP_ARCACHE | IMAP_AWCACHE);
+#endif
+			/* zero out IMAP0 mapping windows for MSI/MSI-X */
+			mmio_write_32(PAXB_OFFSET(i) + PAXB_IMAP0_OFFSET(j),
+				      0x0);
+
+			mmio_write_32(PAXB_OFFSET(i) +
+				      PAXB_IMAP3_0_AXUSER_OFFSET(j),
+				      IMAP_AXUSER);
+			mmio_write_32(PAXB_OFFSET(i) +
+				      PAXB_IMAP4_0_AXUSER_OFFSET(j),
+				      IMAP_AXUSER);
+		}
+	}
+}
+
+/*
+ * This function configures all PAXB related blocks to allow non-secure access
+ */
+void paxb_ns_init(enum paxb_type type)
+{
+	unsigned int reg;
+
+	switch (type) {
+	case PAXB_SR:
+		for (reg = 0; reg < ARRAY_SIZE(paxb_sec_reg_offset); reg++) {
+
+			mmio_setbits_32(SR_PCIE_NIC_SECURITY_BASE +
+					paxb_sec_reg_offset[reg], 0x1);
+		}
+	/* Enabled all PAXB's relevant IDM blocks access in non-secure mode */
+	mmio_setbits_32(SR_PCIE_NIC_SECURITY_BASE + PAXB_SECURITY_IDM_OFFSET,
+			0xffff);
+		break;
+	case PAXB_NS3Z:
+		mmio_setbits_32(NS3Z_PCIE_NIC_SECURITY_BASE +
+				paxb_sec_reg_offset[0], 0x1);
+		mmio_setbits_32(NS3Z_PCIE_NIC_SECURITY_BASE +
+				PAXB_SECURITY_IDM_OFFSET, 0xffff);
+		mmio_setbits_32(NS3Z_PCIE_NIC_SECURITY_BASE +
+				PAXB_SECURITY_APB_OFFSET, 0x7);
+		mmio_setbits_32(NS3Z_PCIE_NIC_SECURITY_BASE +
+				PAXB_SECURITY_ECAM_OFFSET, 0x1);
+		break;
+	}
+}
+
+static int paxb_set_config(void)
+{
+	paxb = paxb_get_config(sr);
+	if (paxb)
+		return 0;
+
+	return -ENODEV;
+}
+
+void paxb_init(void)
+{
+	int ret;
+
+	ret = paxb_set_config();
+	if (ret)
+		return;
+
+	paxb_ns_init(paxb->type);
+
+	ret = pcie_cores_init();
+	if (ret)
+		return;
+
+	if (paxb->phy_init) {
+		ret = paxb->phy_init();
+		if (ret)
+			return;
+	}
+
+	paxb_cfg_dev_id();
+	paxb_cfg_tgt_trn();
+	paxb_cfg_pdl_ctrl();
+	if (paxb->type == PAXB_SR) {
+		paxb_ib_regs_init();
+		paxb_cfg_coherency();
+	} else
+		paxb_ib_regs_bypass();
+
+	paxb_cfg_apb_timeout();
+	paxb_smmu_cfg();
+	paxb_cfg_clkreq();
+	paxb_rc_link_init();
+
+	/* Stingray Doesn't support LTR */
+	paxb_cfg_LTR(false);
+	paxb_cfg_dl_active(true);
+
+	paxb_cfg_mps();
+
+#ifdef PAXB_LINKUP
+	paxb_start_link_up();
+#endif
+	INFO("PAXB init done\n");
+}
diff --git a/plat/brcm/board/stingray/src/paxc.c b/plat/brcm/board/stingray/src/paxc.c
new file mode 100644
index 0000000..44af4b0
--- /dev/null
+++ b/plat/brcm/board/stingray/src/paxc.c
@@ -0,0 +1,267 @@
+/*
+ * Copyright (c) 2017 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <lib/mmio.h>
+
+#include <iommu.h>
+#include <platform_def.h>
+#include <sr_utils.h>
+
+#define PAXC_BASE                  0x60400000
+#define PAXC_AXI_CFG_PF            0x10
+#define PAXC_AXI_CFG_PF_OFFSET(pf) (PAXC_AXI_CFG_PF + (pf) * 4)
+#define PAXC_ARPROT_PF_CFG         0x40
+#define PAXC_AWPROT_PF_CFG         0x44
+
+#define PAXC_ARQOS_PF_CFG          0x48
+#define PAXC_ARQOS_VAL             0xaaaaaaaa
+
+#define PAXC_AWQOS_PF_CFG          0x4c
+#define PAXC_AWQOS_VAL             0xeeeeeeee
+
+#define PAXC_CFG_IND_ADDR_OFFSET   0x1f0
+#define PAXC_CFG_IND_ADDR_MASK     0xffc
+#define PAXC_CFG_IND_DATA_OFFSET   0x1f4
+
+/* offsets for PAXC root complex configuration space registers */
+
+#define PAXC_CFG_ID_OFFSET           0x434
+#define PAXC_RC_VENDOR_ID            0x14e4
+#define PAXC_RC_VENDOR_ID_SHIFT      16
+
+#define PAXC_RC_DEVICE_ID            0xd750
+
+#define PAXC_CFG_LINK_CAP_OFFSET     0x4dc
+#define PAXC_RC_LINK_CAP_SPD_SHIFT   0
+#define PAXC_RC_LINK_CAP_SPD_MASK    (0xf << PAXC_RC_LINK_CAP_SPD_SHIFT)
+#define PAXC_RC_LINK_CAP_SPD         3
+#define PAXC_RC_LINK_CAP_WIDTH_SHIFT 4
+#define PAXC_RC_LINK_CAP_WIDTH_MASK  (0x1f << PAXC_RC_LINK_CAP_WIDTH_SHIFT)
+#define PAXC_RC_LINK_CAP_WIDTH       16
+
+/* offsets for MHB registers */
+
+#define MHB_BASE                   0x60401000
+#define MHB_MEM_PWR_STATUS_PAXC    (MHB_BASE + 0x1c0)
+#define MHB_PWR_ARR_POWERON        0x8
+#define MHB_PWR_ARR_POWEROK        0x4
+#define MHB_PWR_POWERON            0x2
+#define MHB_PWR_POWEROK            0x1
+#define MHB_PWR_STATUS_MASK        (MHB_PWR_ARR_POWERON | \
+				    MHB_PWR_ARR_POWEROK | \
+				    MHB_PWR_POWERON | \
+				    MHB_PWR_POWEROK)
+
+/* max number of PFs from Nitro that PAXC sees */
+#define MAX_NR_NITRO_PF            8
+
+#ifdef EMULATION_SETUP
+static void paxc_reg_dump(void)
+{
+}
+#else
+/* total number of PAXC registers */
+#define NR_PAXC_REGS               53
+static void paxc_reg_dump(void)
+{
+	uint32_t idx, offset = 0;
+
+	VERBOSE("PAXC register dump start\n");
+	for (idx = 0; idx < NR_PAXC_REGS; idx++, offset += 4)
+		VERBOSE("offset: 0x%x val: 0x%x\n", offset,
+			mmio_read_32(PAXC_BASE + offset));
+	VERBOSE("PAXC register dump end\n");
+}
+#endif /* EMULATION_SETUP */
+
+#ifdef EMULATION_SETUP
+static void mhb_reg_dump(void)
+{
+}
+#else
+#define NR_MHB_REGS                227
+static void mhb_reg_dump(void)
+{
+	uint32_t idx, offset = 0;
+
+	VERBOSE("MHB register dump start\n");
+	for (idx = 0; idx < NR_MHB_REGS; idx++, offset += 4)
+		VERBOSE("offset: 0x%x val: 0x%x\n", offset,
+			mmio_read_32(MHB_BASE + offset));
+	VERBOSE("MHB register dump end\n");
+}
+#endif /* EMULATION_SETUP */
+
+static void paxc_rc_cfg_write(uint32_t where, uint32_t val)
+{
+	mmio_write_32(PAXC_BASE + PAXC_CFG_IND_ADDR_OFFSET,
+		      where & PAXC_CFG_IND_ADDR_MASK);
+	mmio_write_32(PAXC_BASE + PAXC_CFG_IND_DATA_OFFSET, val);
+}
+
+static uint32_t paxc_rc_cfg_read(uint32_t where)
+{
+	mmio_write_32(PAXC_BASE + PAXC_CFG_IND_ADDR_OFFSET,
+		      where & PAXC_CFG_IND_ADDR_MASK);
+	return mmio_read_32(PAXC_BASE + PAXC_CFG_IND_DATA_OFFSET);
+}
+
+/*
+ * Function to program PAXC root complex link capability register
+ */
+static void paxc_cfg_link_cap(void)
+{
+	uint32_t val;
+
+	val = paxc_rc_cfg_read(PAXC_CFG_LINK_CAP_OFFSET);
+	val &= ~(PAXC_RC_LINK_CAP_SPD_MASK | PAXC_RC_LINK_CAP_WIDTH_MASK);
+	val |= (PAXC_RC_LINK_CAP_SPD << PAXC_RC_LINK_CAP_SPD_SHIFT) |
+		(PAXC_RC_LINK_CAP_WIDTH << PAXC_RC_LINK_CAP_WIDTH_SHIFT);
+	paxc_rc_cfg_write(PAXC_CFG_LINK_CAP_OFFSET, val);
+}
+
+/*
+ * Function to program PAXC root complex vendor ID and device ID
+ */
+static void paxc_cfg_id(void)
+{
+	uint32_t val;
+
+	val = (PAXC_RC_VENDOR_ID << PAXC_RC_VENDOR_ID_SHIFT) |
+		PAXC_RC_DEVICE_ID;
+	paxc_rc_cfg_write(PAXC_CFG_ID_OFFSET, val);
+}
+
+void paxc_init(void)
+{
+	unsigned int pf_index;
+	unsigned int val;
+
+	val = mmio_read_32(MHB_MEM_PWR_STATUS_PAXC);
+	if ((val & MHB_PWR_STATUS_MASK) != MHB_PWR_STATUS_MASK) {
+		INFO("PAXC not powered\n");
+		return;
+	}
+
+	paxc_cfg_id();
+	paxc_cfg_link_cap();
+
+	paxc_reg_dump();
+	mhb_reg_dump();
+
+#ifdef USE_DDR
+	/*
+	 * Set AWCACHE and ARCACHE to 0xff (Cacheable write-back,
+	 * allocate on both reads and writes) per
+	 * recommendation from the ASIC team
+	 */
+	val = 0xff;
+#else
+	/* disable IO cache if non-DDR memory is used, e.g., external SRAM */
+	val = 0x0;
+#endif
+	for (pf_index = 0; pf_index < MAX_NR_NITRO_PF; pf_index++)
+		mmio_write_32(PAXC_BASE + PAXC_AXI_CFG_PF_OFFSET(pf_index),
+			      val);
+
+	/*
+	 * Set ARPROT and AWPROT to enable non-secure access from
+	 * PAXC to all PFs, PF0 to PF7
+	 */
+	mmio_write_32(PAXC_BASE + PAXC_ARPROT_PF_CFG, 0x22222222);
+	mmio_write_32(PAXC_BASE + PAXC_AWPROT_PF_CFG, 0x22222222);
+
+	mmio_write_32(PAXC_BASE + PAXC_ARQOS_PF_CFG, PAXC_ARQOS_VAL);
+	mmio_write_32(PAXC_BASE + PAXC_AWQOS_PF_CFG, PAXC_AWQOS_VAL);
+
+	INFO("PAXC init done\n");
+}
+
+/*
+ * These defines do not match the regfile but they are renamed in a way such
+ * that they are much more readible
+ */
+
+#define MHB_NIC_SECURITY_BASE  0x60500000
+#define MHB_NIC_PAXC_AXI_NS    0x0008
+#define MHB_NIC_IDM_NS         0x000c
+#define MHB_NIC_MHB_APB_NS     0x0010
+#define MHB_NIC_NITRO_AXI_NS   0x0014
+#define MHB_NIC_PCIE_AXI_NS    0x0018
+#define MHB_NIC_PAXC_APB_NS    0x001c
+#define MHB_NIC_EP_APB_NS      0x0020
+
+#define MHB_NIC_PAXC_APB_S_IDM_SHIFT     5
+#define MHB_NIC_EP_APB_S_IDM_SHIFT       4
+#define MHB_NIC_MHB_APB_S_IDM_SHIFT      3
+#define MHB_NIC_PAXC_AXI_S_IDM_SHIFT     2
+#define MHB_NIC_PCIE_AXI_S_IDM_SHIFT     1
+#define MHB_NIC_NITRO_AXI_S_IDM_SHIFT    0
+
+#define NIC400_NITRO_TOP_NIC_SECURITY_BASE 0x60d00000
+
+#define NITRO_NIC_SECURITY_3_SHIFT       0x14
+#define NITRO_NIC_SECURITY_4_SHIFT       0x18
+#define NITRO_NIC_SECURITY_5_SHIFT       0x1c
+#define NITRO_NIC_SECURITY_6_SHIFT       0x20
+
+void paxc_mhb_ns_init(void)
+{
+	unsigned int val;
+	uintptr_t mhb_nic_gpv = MHB_NIC_SECURITY_BASE;
+#ifndef NITRO_SECURE_ACCESS
+	uintptr_t nic400_nitro_gpv = NIC400_NITRO_TOP_NIC_SECURITY_BASE;
+#endif /* NITRO_SECURE_ACCESS */
+
+	/* set PAXC AXI to allow non-secure access */
+	val = mmio_read_32(mhb_nic_gpv + MHB_NIC_PAXC_AXI_NS);
+	val |= 0x1;
+	mmio_write_32(mhb_nic_gpv + MHB_NIC_PAXC_AXI_NS, val);
+
+	/* set various MHB IDM interfaces to allow non-secure access */
+	val = mmio_read_32(mhb_nic_gpv + MHB_NIC_IDM_NS);
+	val |= (0x1 << MHB_NIC_PAXC_APB_S_IDM_SHIFT);
+	val |= (0x1 << MHB_NIC_EP_APB_S_IDM_SHIFT);
+	val |= (0x1 << MHB_NIC_MHB_APB_S_IDM_SHIFT);
+	val |= (0x1 << MHB_NIC_PAXC_AXI_S_IDM_SHIFT);
+	val |= (0x1 << MHB_NIC_PCIE_AXI_S_IDM_SHIFT);
+	val |= (0x1 << MHB_NIC_NITRO_AXI_S_IDM_SHIFT);
+	mmio_write_32(mhb_nic_gpv + MHB_NIC_IDM_NS, val);
+
+	/* set MHB APB to allow non-secure access  */
+	val = mmio_read_32(mhb_nic_gpv + MHB_NIC_MHB_APB_NS);
+	val |= 0x1;
+	mmio_write_32(mhb_nic_gpv + MHB_NIC_MHB_APB_NS, val);
+
+	/* set Nitro AXI to allow non-secure access  */
+	val = mmio_read_32(mhb_nic_gpv + MHB_NIC_NITRO_AXI_NS);
+	val |= 0x1;
+	mmio_write_32(mhb_nic_gpv + MHB_NIC_NITRO_AXI_NS, val);
+
+	/* set PCIe AXI to allow non-secure access  */
+	val = mmio_read_32(mhb_nic_gpv + MHB_NIC_PCIE_AXI_NS);
+	val |= 0x1;
+	mmio_write_32(mhb_nic_gpv + MHB_NIC_PCIE_AXI_NS, val);
+
+	/* set PAXC APB to allow non-secure access  */
+	val = mmio_read_32(mhb_nic_gpv + MHB_NIC_PAXC_APB_NS);
+	val |= 0x1;
+	mmio_write_32(mhb_nic_gpv + MHB_NIC_PAXC_APB_NS, val);
+
+	/* set EP APB to allow non-secure access  */
+	val = mmio_read_32(mhb_nic_gpv + MHB_NIC_EP_APB_NS);
+	val |= 0x1;
+	mmio_write_32(mhb_nic_gpv + MHB_NIC_EP_APB_NS, val);
+
+#ifndef NITRO_SECURE_ACCESS
+	/* Set NIC400 to allow non-secure access */
+	mmio_setbits_32(nic400_nitro_gpv + NITRO_NIC_SECURITY_3_SHIFT, 0x1);
+	mmio_setbits_32(nic400_nitro_gpv + NITRO_NIC_SECURITY_4_SHIFT, 0x1);
+	mmio_setbits_32(nic400_nitro_gpv + NITRO_NIC_SECURITY_5_SHIFT, 0x1);
+	mmio_setbits_32(nic400_nitro_gpv + NITRO_NIC_SECURITY_6_SHIFT, 0x1);
+#endif /* NITRO_SECURE_ACCESS */
+}
diff --git a/plat/brcm/board/stingray/src/sdio.c b/plat/brcm/board/stingray/src/sdio.c
new file mode 100644
index 0000000..aa2b71a
--- /dev/null
+++ b/plat/brcm/board/stingray/src/sdio.c
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2019-2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <errno.h>
+#include <stdbool.h>
+
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+
+#include <sdio.h>
+#include <sr_def.h>
+#include <sr_utils.h>
+
+const SDIO_CFG sr_sdio0_cfg = {
+	.cfg_base = SR_IPROC_SDIO0_CFG_BASE,
+	.sid_base = SR_IPROC_SDIO0_SID_BASE,
+	.io_ctrl_base = SR_IPROC_SDIO0_IOCTRL_BASE,
+	.pad_base = SR_IPROC_SDIO0_PAD_BASE,
+};
+const SDIO_CFG sr_sdio1_cfg = {
+	.cfg_base = SR_IPROC_SDIO1_CFG_BASE,
+	.sid_base = SR_IPROC_SDIO1_SID_BASE,
+	.io_ctrl_base = SR_IPROC_SDIO1_IOCTRL_BASE,
+	.pad_base = SR_IPROC_SDIO1_PAD_BASE,
+};
+
+void brcm_stingray_sdio_init(void)
+{
+	unsigned int val;
+	const SDIO_CFG *sdio0_cfg, *sdio1_cfg;
+
+	sdio0_cfg = &sr_sdio0_cfg;
+	sdio1_cfg = &sr_sdio1_cfg;
+
+	INFO("set sdio0 caps\n");
+	/* SDIO0 CAPS0 */
+	val = SDIO0_CAP0_CFG;
+	INFO("caps0 0x%x\n", val);
+	mmio_write_32(sdio0_cfg->cfg_base + ICFG_SDIO_CAP0, val);
+
+	/* SDIO0 CAPS1 */
+	val = SDIO0_CAP1_CFG;
+	INFO("caps1 0x%x\n", val);
+	mmio_write_32(sdio0_cfg->cfg_base + ICFG_SDIO_CAP1, val);
+
+	mmio_write_32(sdio0_cfg->cfg_base + ICFG_SDIO_STRAPSTATUS_0,
+		      SDIO_PRESETVAL0);
+	mmio_write_32(sdio0_cfg->cfg_base + ICFG_SDIO_STRAPSTATUS_1,
+		      SDIO_PRESETVAL1);
+	mmio_write_32(sdio0_cfg->cfg_base + ICFG_SDIO_STRAPSTATUS_2,
+		      SDIO_PRESETVAL2);
+	mmio_write_32(sdio0_cfg->cfg_base + ICFG_SDIO_STRAPSTATUS_3,
+		      SDIO_PRESETVAL3);
+	mmio_write_32(sdio0_cfg->cfg_base + ICFG_SDIO_STRAPSTATUS_4,
+		      SDIO_PRESETVAL4);
+
+	val = SR_SID_VAL(0x3, 0x0, 0x2) << SDIO_SID_SHIFT;
+	mmio_write_32(sdio0_cfg->sid_base + ICFG_SDIO_SID_ARADDR, val);
+	mmio_write_32(sdio0_cfg->sid_base + ICFG_SDIO_SID_AWADDR, val);
+
+	val = mmio_read_32(sdio0_cfg->io_ctrl_base);
+	val &= ~(0xff << 23); /* Clear ARCACHE and AWCACHE */
+	val |= (0xb7 << 23); /* Set ARCACHE and AWCACHE */
+	mmio_write_32(sdio0_cfg->io_ctrl_base, val);
+
+	mmio_clrsetbits_32(sdio0_cfg->pad_base + PAD_SDIO_CLK,
+			   PAD_SDIO_MASK, PAD_SDIO_VALUE);
+	mmio_clrsetbits_32(sdio0_cfg->pad_base + PAD_SDIO_DATA0,
+			   PAD_SDIO_MASK, PAD_SDIO_VALUE);
+	mmio_clrsetbits_32(sdio0_cfg->pad_base + PAD_SDIO_DATA1,
+			   PAD_SDIO_MASK, PAD_SDIO_VALUE);
+	mmio_clrsetbits_32(sdio0_cfg->pad_base + PAD_SDIO_DATA2,
+			   PAD_SDIO_MASK, PAD_SDIO_VALUE);
+	mmio_clrsetbits_32(sdio0_cfg->pad_base + PAD_SDIO_DATA3,
+			   PAD_SDIO_MASK, PAD_SDIO_VALUE);
+	mmio_clrsetbits_32(sdio0_cfg->pad_base + PAD_SDIO_DATA4,
+			   PAD_SDIO_MASK, PAD_SDIO_VALUE);
+	mmio_clrsetbits_32(sdio0_cfg->pad_base + PAD_SDIO_DATA5,
+			   PAD_SDIO_MASK, PAD_SDIO_VALUE);
+	mmio_clrsetbits_32(sdio0_cfg->pad_base + PAD_SDIO_DATA6,
+			   PAD_SDIO_MASK, PAD_SDIO_VALUE);
+	mmio_clrsetbits_32(sdio0_cfg->pad_base + PAD_SDIO_DATA7,
+			   PAD_SDIO_MASK, PAD_SDIO_VALUE);
+	mmio_clrsetbits_32(sdio0_cfg->pad_base + PAD_SDIO_CMD,
+			   PAD_SDIO_MASK, PAD_SDIO_VALUE);
+
+	INFO("set sdio1 caps\n");
+
+	/* SDIO1 CAPS0 */
+	val = SDIO1_CAP0_CFG;
+	INFO("caps0 0x%x\n", val);
+	mmio_write_32(sdio1_cfg->cfg_base + ICFG_SDIO_CAP0, val);
+	/* SDIO1 CAPS1 */
+	val = SDIO1_CAP1_CFG;
+	INFO("caps1 0x%x\n", val);
+	mmio_write_32(sdio1_cfg->cfg_base + ICFG_SDIO_CAP1, val);
+
+	mmio_write_32(sdio1_cfg->cfg_base + ICFG_SDIO_STRAPSTATUS_0,
+		      SDIO_PRESETVAL0);
+	mmio_write_32(sdio1_cfg->cfg_base + ICFG_SDIO_STRAPSTATUS_1,
+		      SDIO_PRESETVAL1);
+	mmio_write_32(sdio1_cfg->cfg_base + ICFG_SDIO_STRAPSTATUS_2,
+		      SDIO_PRESETVAL2);
+	mmio_write_32(sdio1_cfg->cfg_base + ICFG_SDIO_STRAPSTATUS_3,
+		      SDIO_PRESETVAL3);
+	mmio_write_32(sdio1_cfg->cfg_base + ICFG_SDIO_STRAPSTATUS_4,
+		      SDIO_PRESETVAL4);
+
+	val = SR_SID_VAL(0x3, 0x0, 0x3) << SDIO_SID_SHIFT;
+	mmio_write_32(sdio1_cfg->sid_base + ICFG_SDIO_SID_ARADDR, val);
+	mmio_write_32(sdio1_cfg->sid_base + ICFG_SDIO_SID_AWADDR, val);
+
+	val = mmio_read_32(sdio1_cfg->io_ctrl_base);
+	val &= ~(0xff << 23); /* Clear ARCACHE and AWCACHE */
+	val |= (0xb7 << 23); /* Set ARCACHE and AWCACHE */
+	mmio_write_32(sdio1_cfg->io_ctrl_base, val);
+
+	mmio_clrsetbits_32(sdio1_cfg->pad_base + PAD_SDIO_CLK,
+			   PAD_SDIO_MASK, PAD_SDIO_VALUE);
+	mmio_clrsetbits_32(sdio1_cfg->pad_base + PAD_SDIO_DATA0,
+			   PAD_SDIO_MASK, PAD_SDIO_VALUE);
+	mmio_clrsetbits_32(sdio1_cfg->pad_base + PAD_SDIO_DATA1,
+			   PAD_SDIO_MASK, PAD_SDIO_VALUE);
+	mmio_clrsetbits_32(sdio1_cfg->pad_base + PAD_SDIO_DATA2,
+			   PAD_SDIO_MASK, PAD_SDIO_VALUE);
+	mmio_clrsetbits_32(sdio1_cfg->pad_base + PAD_SDIO_DATA3,
+			   PAD_SDIO_MASK, PAD_SDIO_VALUE);
+	mmio_clrsetbits_32(sdio1_cfg->pad_base + PAD_SDIO_DATA4,
+			   PAD_SDIO_MASK, PAD_SDIO_VALUE);
+	mmio_clrsetbits_32(sdio1_cfg->pad_base + PAD_SDIO_DATA5,
+			   PAD_SDIO_MASK, PAD_SDIO_VALUE);
+	mmio_clrsetbits_32(sdio1_cfg->pad_base + PAD_SDIO_DATA6,
+			   PAD_SDIO_MASK, PAD_SDIO_VALUE);
+	mmio_clrsetbits_32(sdio1_cfg->pad_base + PAD_SDIO_DATA7,
+			   PAD_SDIO_MASK, PAD_SDIO_VALUE);
+	mmio_clrsetbits_32(sdio1_cfg->pad_base + PAD_SDIO_CMD,
+			   PAD_SDIO_MASK, PAD_SDIO_VALUE);
+
+	INFO("sdio init done\n");
+}
diff --git a/plat/brcm/board/stingray/src/sr_paxb_phy.c b/plat/brcm/board/stingray/src/sr_paxb_phy.c
new file mode 100644
index 0000000..7380e09
--- /dev/null
+++ b/plat/brcm/board/stingray/src/sr_paxb_phy.c
@@ -0,0 +1,806 @@
+/*
+ * Copyright (c) 2019-2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <errno.h>
+#include <stdbool.h>
+
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+
+#include <paxb.h>
+#include <sr_def.h>
+#include <sr_utils.h>
+
+/* total number of PCIe Phys */
+#define NUM_OF_PCIE_SERDES            8
+
+#define CFG_RC_PMI_ADDR               0x1130
+#define PMI_RX_TERM_SEQ               ((0x1 << 27) | (0x1ff << 16) | (0xd090))
+#define PMI_RX_TERM_VAL               0x4c00
+#define PMI_PLL_CTRL_4                0xd0b4
+#define PMI_SERDES_CLK_ENABLE         (1 << 12)
+
+#define WAR_PLX_PRESET_PARITY_FAIL
+
+#define CFG_RC_REG_PHY_CTL_10         0x1838
+#define PHY_CTL_10_GEN3_MATCH_PARITY  (1 << 15)
+
+#define PMI_X8_CORE0_7_PATCH_SEQ      ((0x1 << 27) | (0x1ff << 16) | (0xd2a5))
+#define PMI_X8_CORE0_7_PATCH_VAL      0xd864
+
+#define PMI_ADDR_BCAST(addr)          ((0x1 << 27) | (0x1ff << 16) | (addr))
+#define PMI_ADDR_LANE0(addr)          ((0x1 << 27) | (addr))
+#define PMI_ADDR_LANE1(addr)          ((0x1 << 27) | (0x1 << 16) | (addr))
+
+#define MERLIN16_PCIE_BLK2_PWRMGMT_7	((0x1 << 27) | (0x1ff << 16) | 0x1208)
+#define MERLIN16_PCIE_BLK2_PWRMGMT_8	((0x1 << 27) | (0x1ff << 16) | 0x1209)
+#define MERLIN16_AMS_TX_CTRL_5		((0x1 << 27) | (0x1ff << 16) | 0xd0a5)
+#define MERLIN16_AMS_TX_CTRL_5_VAL	\
+		((1 << 13) | (1 << 12) | (1 << 11) | (1 << 10))
+#define MERLIN16_PCIE_BLK2_PWRMGMT_7_VAL   0x96
+#define MERLIN16_PCIE_BLK2_PWRMGMT_8_VAL   0x12c
+
+#define CFG_RC_PMI_WDATA              0x1134
+#define CFG_RC_WCMD_SHIFT             31
+#define CFG_RC_WCMD_MASK              ((uint32_t)1U << CFG_RC_WCMD_SHIFT)
+#define CFG_RC_RCMD_SHIFT             30
+#define CFG_RC_RCMD_MASK              ((uint32_t)1U << CFG_RC_RCMD_SHIFT)
+#define CFG_RC_RWCMD_MASK             (CFG_RC_RCMD_MASK | CFG_RC_WCMD_MASK)
+#define CFG_RC_PMI_RDATA              0x1138
+#define CFG_RC_RACK_SHIFT             31
+#define CFG_RC_RACK_MASK              ((uint32_t)1U << CFG_RC_RACK_SHIFT)
+
+/* allow up to 5 ms for PMI write to finish */
+#define PMI_TIMEOUT_MS                5
+
+/* in 2x8 RC mode, one needs to patch up Serdes 3 and 7 for link to come up */
+#define SERDES_PATCH_PIPEMUX_INDEX    0x3
+#define SERDES_PATCH_INDEX            0x8
+
+#define DSC_UC_CTRL                   0xd00d
+#define DSC_UC_CTRL_RDY_CMD           (1 << 7)
+#define LANE_DBG_RST_CTRL             0xd164
+#define UC_A_CLK_CTRL0                0xd200
+#define UC_A_RST_CTRL0                0xd201
+#define UC_A_AHB_CTRL0                0xd202
+#define UC_A_AHB_STAT0                0xd203
+#define UC_A_AHB_WADDR_LSW            0xd204
+#define UC_A_AHB_WADDR_MSW            0xd205
+#define UC_A_AHB_WDATA_LSW            0xd206
+#define UC_A_AHB_WDATA_MSW            0xd207
+#define UC_A_AHB_RADDR_LSW            0xd208
+#define UC_A_AHB_RADDR_MSW            0xd209
+#define UC_A_AHB_RDATA_LSW            0xd20a
+#define UC_A_AHB_RDATA_MSW            0xd20b
+#define UC_VERSION_NUM                0xd230
+#define DSC_SM_CTL22                  0xd267
+#define UC_DBG1                       0xd251
+
+#define LOAD_UC_CHECK                 0
+#define UC_RAM_INIT_TIMEOUT           100
+#define UC_RAM_CONTROL                0xd225
+#define UC_INIT_TIMEOUT               100
+#define SIZE_ALIGN(x, a)              (((x) + (a) - 1) & ~((a) - 1))
+#define SZ_4                          4
+#define GET_2_BYTES(p, i)             ((uint16_t)p[i] | (uint16_t)p[i+1] << 8)
+
+/*
+ * List of PCIe LCPLL related registers
+ *
+ * LCPLL channel 0 provides the Serdes pad clock when running in RC mode
+ */
+#define PCIE_LCPLL_BASE             0x40000000
+
+#define PCIE_LCPLL_CTRL0_OFFSET     0x00
+#define PCIE_LCPLL_RESETB_SHIFT     31
+#define PCIE_LCPLL_RESETB_MASK      BIT(PCIE_LCPLL_RESETB_SHIFT)
+#define PCIE_LCPLL_P_RESETB_SHIFT   30
+#define PCIE_LCPLL_P_RESETB_MASK    BIT(PCIE_LCPLL_P_RESETB_SHIFT)
+
+#define PCIE_LCPLL_CTRL3_OFFSET     0x0c
+#define PCIE_LCPLL_EN_CTRL_SHIFT    16
+#define PCIE_LCPLL_CM_ENA           0x1a
+#define PCIE_LCPLL_CM_BUF_ENA       0x18
+#define PCIE_LCPLL_D2C2_ENA         0x2
+#define PCIE_LCPLL_REF_CLK_SHIFT    1
+#define PCIE_LCPLL_REF_CLK_MASK     BIT(PCIE_LCPLL_REF_CLK_SHIFT)
+#define PCIE_LCPLL_CTRL13_OFFSET    0x34
+#define PCIE_LCPLL_D2C2_CTRL_SHIFT  16
+#define PCIE_LCPLL_D2C2_TERM_DISC   0xe0
+
+#define PCIE_LCPLL_STATUS_OFFSET    0x40
+#define PCIE_LCPLL_LOCK_SHIFT       12
+#define PCIE_LCPLL_LOCK_MASK        BIT(PCIE_LCPLL_LOCK_SHIFT)
+
+#define PCIE_PIPE_MUX_RC_MODE_OVERRIDE_CFG  0x114
+#define PCIE_TX_CLKMASTER_CTRL_OVERRIDE_CFG 0x11c
+
+/* wait 500 microseconds for PCIe LCPLL to power up */
+#define PCIE_LCPLL_DELAY_US         500
+
+/* allow up to 5 ms for PCIe LCPLL VCO to lock */
+#define PCIE_LCPLL_TIMEOUT_MS       5
+
+#define PCIE_PIPE_MUX_CONFIGURATION_CFG  0x4000010c
+
+#define PCIE_PIPEMUX_SHIFT        19
+#define PCIE_PIPEMUX_MASK         0xf
+
+/* keep track of PIPEMUX index to use */
+static unsigned int pipemux_idx;
+
+/*
+ * PCIe PIPEMUX lookup table
+ *
+ * Each array index represents a PIPEMUX strap setting
+ * The array element represents a bitmap where a set bit means the PCIe core
+ * needs to be enabled as RC
+ */
+static uint8_t pipemux_table[] = {
+	/* PIPEMUX = 0, EP 1x16 */
+	0x00,
+	/* PIPEMUX = 1, EP 1x8 + RC 1x8, core 7 */
+	0x80,
+	/* PIPEMUX = 2, EP 4x4 */
+	0x00,
+	/* PIPEMUX = 3, RC 2x8, cores 0, 7 */
+	0x81,
+	/* PIPEMUX = 4, RC 4x4, cores 0, 1, 6, 7 */
+	0xc3,
+	/* PIPEMUX = 5, RC 8x2, all 8 cores */
+	0xff,
+	/* PIPEMUX = 6, RC 3x4 + 2x2, cores 0, 2, 3, 6, 7 */
+	0xcd,
+	/* PIPEMUX = 7, RC 1x4 + 6x2, cores 0, 2, 3, 4, 5, 6, 7 */
+	0xfd,
+	/* PIPEMUX = 8, EP 1x8 + RC 4x2, cores 4, 5, 6, 7 */
+	0xf0,
+	/* PIPEMUX = 9, EP 1x8 + RC 2x4, cores 6, 7 */
+	0xc0,
+	/* PIPEMUX = 10, EP 2x4 + RC 2x4, cores 1, 6 */
+	0x42,
+	/* PIPEMUX = 11, EP 2x4 + RC 4x2, cores 2, 3, 4, 5 */
+	0x3c,
+	/* PIPEMUX = 12, EP 1x4 + RC 6x2, cores 2, 3, 4, 5, 6, 7 */
+	0xfc,
+	/* PIPEMUX = 13, RC 2x4 + RC 1x4 + 2x2, cores 2, 3, 6 */
+	0x4c,
+};
+
+/*
+ * Return 1 if pipemux strap is supported
+ */
+static int pipemux_strap_is_valid(uint32_t pipemux)
+{
+	if (pipemux < ARRAY_SIZE(pipemux_table))
+		return 1;
+	else
+		return 0;
+}
+
+/*
+ * Read the PCIe PIPEMUX from strap
+ */
+static uint32_t pipemux_strap_read(void)
+{
+	uint32_t pipemux;
+
+	pipemux = mmio_read_32(PCIE_PIPE_MUX_CONFIGURATION_CFG);
+	pipemux &= PCIE_PIPEMUX_MASK;
+	if (pipemux == PCIE_PIPEMUX_MASK) {
+		/* read the PCIe PIPEMUX strap setting */
+		pipemux = mmio_read_32(CDRU_CHIP_STRAP_DATA_LSW);
+		pipemux >>= PCIE_PIPEMUX_SHIFT;
+		pipemux &= PCIE_PIPEMUX_MASK;
+	}
+
+	return pipemux;
+}
+
+/*
+ * Store the PIPEMUX index (set for each boot)
+ */
+static void pipemux_save_index(unsigned int idx)
+{
+	pipemux_idx = idx;
+}
+
+static int paxb_sr_core_needs_enable(unsigned int core_idx)
+{
+	return !!((pipemux_table[pipemux_idx] >> core_idx) & 0x1);
+}
+
+static int pipemux_sr_init(void)
+{
+	uint32_t pipemux;
+
+	/* read the PCIe PIPEMUX strap setting */
+	pipemux = pipemux_strap_read();
+	if (!pipemux_strap_is_valid(pipemux)) {
+		ERROR("Invalid PCIe PIPEMUX strap %u\n", pipemux);
+		return -EIO;
+	}
+
+	/* no PCIe RC is needed */
+	if (!pipemux_table[pipemux]) {
+		WARN("PIPEMUX indicates no PCIe RC required\n");
+		return -ENODEV;
+	}
+
+	/* save the PIPEMUX strap */
+	pipemux_save_index(pipemux);
+
+	return 0;
+}
+
+/*
+ * PCIe RC serdes link width
+ *
+ * The array is first organized in rows as indexed by the PIPEMUX setting.
+ * Within each row, eight lane width entries are specified -- one entry
+ * per PCIe core, from 0 to 7.
+ *
+ * Note: The EP lanes/cores are not mapped in this table!  EP cores are
+ *       controlled and thus configured by Nitro.
+ */
+static uint8_t link_width_table[][NUM_OF_SR_PCIE_CORES] = {
+	/* PIPEMUX = 0, EP 1x16 */
+	{0, 0, 0, 0, 0, 0, 0, 0},
+	/* PIPEMUX = 1, EP 1x8 + RC 1x8, core 7 */
+	{0, 0, 0, 0, 0, 0, 0, 8},
+	/* PIPEMUX = 2, EP 4x4 */
+	{0, 0, 0, 0, 0, 0, 0, 0},
+	/* PIPEMUX = 3, RC 2x8, cores 0, 7 */
+	{8, 0, 0, 0, 0, 0, 0, 8},
+	/* PIPEMUX = 4, RC 4x4, cores 0, 1, 6, 7 */
+	{4, 4, 0, 0, 0, 0, 4, 4},
+	/* PIPEMUX = 5, RC 8x2, all 8 cores */
+	{2, 2, 2, 2, 2, 2, 2, 2},
+	/* PIPEMUX = 6, RC 3x4 (cores 0, 6, 7), RC 2x2 (cores 2, 3) */
+	{4, 0, 2, 2, 0, 0, 4, 4},
+	/* PIPEMUX = 7, RC 1x4 (core 0), RC 6x2 (cores 2, 3, 4, 5, 6, 7 */
+	{4, 0, 2, 2, 2, 2, 2, 2},
+	/* PIPEMUX = 8, EP 1x8 + RC 4x2 (cores 4, 5, 6, 7) */
+	{0, 0, 0, 0, 2, 2, 2, 2},
+	/* PIPEMUX = 9, EP 1x8 + RC 2x4 (cores 6, 7) */
+	{0, 0, 0, 0, 0, 0, 4, 4},
+	/* PIPEMUX = 10, EP 2x4 + RC 2x4 (cores 1, 6) */
+	{0, 4, 0, 0, 0, 0, 4, 0},
+	/* PIPEMUX = 11, EP 2x4 + RC 4x2 (cores 2, 3, 4, 5) */
+	{0, 0, 2, 2, 2, 2, 0, 0},
+	/* PIPEMUX = 12, EP 1x4 + RC 6x2 (cores 2, 3, 4, 5, 6, 7) */
+	{0, 0, 2, 2, 2, 2, 2, 2},
+	/* PIPEMUX = 13, EP 2x4 + RC 1x4 (core 6) + RC 2x2 (cores 2, 3) */
+	{0, 0, 2, 2, 0, 0, 4, 0}
+};
+
+/*
+ * function for writes to the Serdes registers through the PMI interface
+ */
+static int paxb_pmi_write(unsigned int core_idx, uint32_t pmi, uint32_t val)
+{
+	uint32_t status;
+	unsigned int timeout = PMI_TIMEOUT_MS;
+
+	paxb_rc_cfg_write(core_idx, CFG_RC_PMI_ADDR, pmi);
+
+	val &= ~CFG_RC_RWCMD_MASK;
+	val |= CFG_RC_WCMD_MASK;
+	paxb_rc_cfg_write(core_idx, CFG_RC_PMI_WDATA, val);
+
+	do {
+		status = paxb_rc_cfg_read(core_idx, CFG_RC_PMI_WDATA);
+
+		/* wait for write command bit to clear */
+		if ((status & CFG_RC_WCMD_MASK) == 0)
+			return 0;
+	} while (--timeout);
+
+	return -EIO;
+}
+
+/*
+ * function for reads from the Serdes registers through the PMI interface
+ */
+static int paxb_pmi_read(unsigned int core_idx, uint32_t pmi, uint32_t *val)
+{
+	uint32_t status;
+	unsigned int timeout = PMI_TIMEOUT_MS;
+
+	paxb_rc_cfg_write(core_idx, CFG_RC_PMI_ADDR, pmi);
+
+	paxb_rc_cfg_write(core_idx, CFG_RC_PMI_WDATA, CFG_RC_RCMD_MASK);
+
+	do {
+		status = paxb_rc_cfg_read(core_idx, CFG_RC_PMI_RDATA);
+
+		/* wait for read ack bit set */
+		if ((status & CFG_RC_RACK_MASK)) {
+			*val = paxb_rc_cfg_read(core_idx, CFG_RC_PMI_RDATA);
+			return 0;
+		}
+	} while (--timeout);
+
+	return -EIO;
+}
+
+
+#ifndef BOARD_PCIE_EXT_CLK
+/*
+ * PCIe Override clock lookup table
+ *
+ * Each array index represents pcie override clock has been done
+ * by CFW or not.
+ */
+static uint8_t pcie_override_clk_table[] = {
+	/* PIPEMUX = 0, EP 1x16 */
+	0x0,
+	/* PIPEMUX = 1, EP 1x8 + RC 1x8, core 7 */
+	0x1,
+	/* PIPEMUX = 2, EP 4x4 */
+	0x0,
+	/* PIPEMUX = 3, RC 2x8, cores 0, 7 */
+	0x0,
+	/* PIPEMUX = 4, RC 4x4, cores 0, 1, 6, 7 */
+	0x0,
+	/* PIPEMUX = 5, RC 8x2, all 8 cores */
+	0x0,
+	/* PIPEMUX = 6, RC 3x4 + 2x2, cores 0, 2, 3, 6, 7 */
+	0x0,
+	/* PIPEMUX = 7, RC 1x4 + 6x2, cores 0, 2, 3, 4, 5, 6, 7 */
+	0x0,
+	/* PIPEMUX = 8, EP 1x8 + RC 4x2, cores 4, 5, 6, 7 */
+	0x0,
+	/* PIPEMUX = 9, EP 1x8 + RC 2x4, cores 6, 7 */
+	0x0,
+	/* PIPEMUX = 10, EP 2x4 + RC 2x4, cores 1, 6 */
+	0x0,
+	/* PIPEMUX = 11, EP 2x4 + RC 4x2, cores 2, 3, 4, 5 */
+	0x0,
+	/* PIPEMUX = 12, EP 1x4 + RC 6x2, cores 2, 3, 4, 5, 6, 7 */
+	0x0,
+	/* PIPEMUX = 13, RC 2x4 + RC 1x4 + 2x2, cores 2, 3, 6 */
+	0x0,
+};
+
+/*
+ * Bring up LCPLL channel 0 reference clock for PCIe serdes used in RC mode
+ */
+static int pcie_lcpll_init(void)
+{
+	uintptr_t reg;
+	unsigned int timeout = PCIE_LCPLL_TIMEOUT_MS;
+	uint32_t val;
+
+	if (pcie_override_clk_table[pipemux_idx]) {
+		/*
+		 * Check rc_mode_override again to avoid halt
+		 * because of cfw uninitialized lcpll.
+		 */
+		reg = (uintptr_t)(PCIE_LCPLL_BASE +
+				  PCIE_PIPE_MUX_RC_MODE_OVERRIDE_CFG);
+		val = mmio_read_32(reg);
+		if (val & 0x1)
+			return 0;
+		else
+			return -ENODEV;
+	}
+
+	/* power on PCIe LCPLL and its LDO */
+	reg = (uintptr_t)CRMU_AON_CTRL1;
+	mmio_setbits_32(reg, CRMU_PCIE_LCPLL_PWR_ON_MASK |
+			     CRMU_PCIE_LCPLL_PWRON_LDO_MASK);
+	udelay(PCIE_LCPLL_DELAY_US);
+
+	/* remove isolation */
+	mmio_clrbits_32(reg, CRMU_PCIE_LCPLL_ISO_IN_MASK);
+	udelay(PCIE_LCPLL_DELAY_US);
+
+	/* disconnect termination */
+	reg = (uintptr_t)(PCIE_LCPLL_BASE + PCIE_LCPLL_CTRL13_OFFSET);
+	mmio_setbits_32(reg, PCIE_LCPLL_D2C2_TERM_DISC <<
+			PCIE_LCPLL_D2C2_CTRL_SHIFT);
+
+	/* enable CML buf1/2 and D2C2 */
+	reg = (uintptr_t)(PCIE_LCPLL_BASE + PCIE_LCPLL_CTRL3_OFFSET);
+	mmio_setbits_32(reg, PCIE_LCPLL_CM_ENA << PCIE_LCPLL_EN_CTRL_SHIFT);
+
+	/* select diff clock mux out as ref clock */
+	mmio_clrbits_32(reg, PCIE_LCPLL_REF_CLK_MASK);
+
+	/* delay for 500 microseconds per ASIC spec for PCIe LCPLL */
+	udelay(PCIE_LCPLL_DELAY_US);
+
+	/* now bring PCIe LCPLL out of reset */
+	reg = (uintptr_t)(PCIE_LCPLL_BASE + PCIE_LCPLL_CTRL0_OFFSET);
+	mmio_setbits_32(reg, PCIE_LCPLL_RESETB_MASK);
+
+	/* wait for PLL to lock */
+	reg = (uintptr_t)(PCIE_LCPLL_BASE + PCIE_LCPLL_STATUS_OFFSET);
+	do {
+		val = mmio_read_32(reg);
+		if ((val & PCIE_LCPLL_LOCK_MASK) == PCIE_LCPLL_LOCK_MASK) {
+			/* now bring the post divider out of reset */
+			reg = (uintptr_t)(PCIE_LCPLL_BASE +
+					  PCIE_LCPLL_CTRL0_OFFSET);
+			mmio_setbits_32(reg, PCIE_LCPLL_P_RESETB_MASK);
+			VERBOSE("PCIe LCPLL locked\n");
+			return 0;
+		}
+		mdelay(1);
+	} while (--timeout);
+
+	ERROR("PCIe LCPLL failed to lock\n");
+	return -EIO;
+}
+#else
+/*
+ * Bring up EXT CLK reference clock for PCIe serdes used in RC mode
+ * XTAL_BYPASS		(3 << 0)
+ * INTR_LC_REF		(5 << 0)
+ * PD_CML_LC_REF_OUT	(1 << 4)
+ * PD_CML_REF_CH_OUT	(1 << 8)
+ * CLK_MASTER_SEL	(1 << 11)
+ * CLK_MASTER_CTRL_A	(1 << 12)
+ * CLK_MASTER_CTRL_B	(2 << 14)
+ */
+static const uint16_t pcie_ext_clk[][NUM_OF_PCIE_SERDES] = {
+	/* PIPEMUX = 0, EP 1x16 */
+	{0},
+	/* PIPEMUX = 1, EP 1x8 + RC 1x8, core 7 */
+	{0},
+	/* PIPEMUX = 2, EP 4x4 */
+	{0},
+	/* PIPEMUX = 3, RC 2x8, cores 0, 7 */
+	{0x8803, 0x9115, 0x9115, 0x1115, 0x8803, 0x9115, 0x9115, 0x1115},
+	/* PIPEMUX = 4, RC 4x4, cores 0, 1, 6, 7 */
+	{0x8803, 0x1115, 0x8915, 0x1115, 0x8803, 0x1115, 0x8915, 0x1115,},
+	/* PIPEMUX = 5, RC 8x2, all 8 cores */
+	{0x0803, 0x0915, 0x0915, 0x0915, 0x0803, 0x0915, 0x0915, 0x0915,},
+	/* PIPEMUX = 6, RC 3x4 + 2x2, cores 0, 2, 3, 6, 7 */
+	{0},
+	/* PIPEMUX = 7, RC 1x4 + 6x2, cores 0, 2, 3, 4, 5, 6, 7 */
+	{0},
+	/* PIPEMUX = 8, EP 1x8 + RC 4x2, cores 4, 5, 6, 7 */
+	{0},
+	/* PIPEMUX = 9, EP 1x8 + RC 2x4, cores 6, 7 */
+	{0},
+	/* PIPEMUX = 10, EP 2x4 + RC 2x4, cores 1, 6 */
+	{0},
+	/* PIPEMUX = 11, EP 2x4 + RC 4x2, cores 2, 3, 4, 5 */
+	{0},
+	/* PIPEMUX = 12, EP 1x4 + RC 6x2, cores 2, 3, 4, 5, 6, 7 */
+	{0},
+	/* PIPEMUX = 13, RC 2x4 + RC 1x4 + 2x2, cores 2, 3, 6 */
+	{0},
+};
+
+static void pcie_ext_clk_init(void)
+{
+	unsigned int serdes;
+	uint32_t val;
+
+	for (serdes = 0; serdes < NUM_OF_PCIE_SERDES; serdes++) {
+		val = pcie_ext_clk[pipemux_idx][serdes];
+		if (!val)
+			return;
+		mmio_write_32(PCIE_CORE_RESERVED_CFG +
+			      serdes * PCIE_CORE_PWR_OFFSET, val);
+	}
+	/* disable CML buf1/2 and enable D2C2 */
+	mmio_clrsetbits_32((PCIE_LCPLL_BASE + PCIE_LCPLL_CTRL3_OFFSET),
+			PCIE_LCPLL_CM_BUF_ENA << PCIE_LCPLL_EN_CTRL_SHIFT,
+			PCIE_LCPLL_D2C2_ENA << PCIE_LCPLL_EN_CTRL_SHIFT);
+	mmio_write_32(PCIE_LCPLL_BASE + PCIE_TX_CLKMASTER_CTRL_OVERRIDE_CFG, 1);
+	INFO("Overriding Clocking - using REF clock from PAD...\n");
+}
+#endif
+
+static int load_uc(unsigned int core_idx)
+{
+	return 0;
+}
+
+static int paxb_serdes_gate_clock(unsigned int core_idx, int gate_clk)
+{
+	unsigned int link_width, serdes, nr_serdes;
+	uintptr_t pmi_base;
+	unsigned int rdata;
+	uint32_t core_offset = core_idx * PCIE_CORE_PWR_OFFSET;
+
+	link_width = paxb->get_link_width(core_idx);
+	if (!link_width) {
+		ERROR("Unsupported PIPEMUX\n");
+		return -EOPNOTSUPP;
+	}
+
+	nr_serdes = link_width / 2;
+	pmi_base = (uintptr_t)(PCIE_CORE_PMI_CFG_BASE + core_offset);
+
+	for (serdes = 0; serdes < nr_serdes; serdes++) {
+		mmio_write_32(pmi_base, serdes);
+		paxb_pmi_read(core_idx, PMI_ADDR_LANE0(PMI_PLL_CTRL_4), &rdata);
+		if (!gate_clk)
+			rdata |= PMI_SERDES_CLK_ENABLE;
+		else
+			rdata &= ~PMI_SERDES_CLK_ENABLE;
+		paxb_pmi_write(core_idx, PMI_ADDR_BCAST(PMI_PLL_CTRL_4), rdata);
+	}
+	return 0;
+}
+
+static int paxb_gen3_serdes_init(unsigned int core_idx, uint32_t nSerdes)
+{
+	uint32_t rdata;
+	int serdes;
+	uintptr_t pmi_base;
+	unsigned int timeout;
+	unsigned int reg_d230, reg_d267;
+
+
+	pmi_base = (uintptr_t)(PCIE_CORE_PMI_CFG_BASE +
+			(core_idx * PCIE_CORE_PWR_OFFSET));
+
+	for (serdes = 0; serdes < nSerdes; serdes++) {
+		/* select the PMI interface */
+		mmio_write_32(pmi_base, serdes);
+
+		/* Clock enable */
+		paxb_pmi_write(core_idx, PMI_ADDR_BCAST(UC_A_CLK_CTRL0),
+				0x3);
+
+		/* Release reset of master */
+		paxb_pmi_write(core_idx, PMI_ADDR_BCAST(UC_A_RST_CTRL0),
+				0x1);
+
+		/* clearing PRAM memory */
+		paxb_pmi_write(core_idx, PMI_ADDR_BCAST(UC_A_AHB_CTRL0),
+				0x100);
+
+		timeout = UC_RAM_INIT_TIMEOUT;
+		do {
+			paxb_pmi_read(core_idx,
+					PMI_ADDR_LANE0(UC_A_AHB_STAT0),
+					&rdata);
+		} while ((rdata & 0x01) == 0 && timeout--);
+
+		if (!timeout)
+			return -EIO;
+
+		timeout = UC_RAM_INIT_TIMEOUT;
+		do {
+			paxb_pmi_read(core_idx,
+					PMI_ADDR_LANE1(UC_A_AHB_STAT0),
+					&rdata);
+		} while ((rdata & 0x01) == 0 && timeout--);
+
+		if (!timeout)
+			return -EIO;
+
+		/* clearing PRAM memory */
+		paxb_pmi_write(core_idx, PMI_ADDR_BCAST(UC_A_AHB_CTRL0),
+				0);
+
+		/* to identify 2 lane serdes */
+		paxb_pmi_write(core_idx, PMI_ADDR_BCAST(UC_DBG1), 0x1);
+
+		/* De-Assert Pram & master resets */
+		paxb_pmi_write(core_idx, PMI_ADDR_BCAST(UC_A_RST_CTRL0),
+				0x9);
+
+		if (load_uc(core_idx))
+			return -EIO;
+
+		/* UC UC ready for command */
+		paxb_pmi_read(core_idx, PMI_ADDR_LANE0(DSC_UC_CTRL),
+				&rdata);
+		rdata |= DSC_UC_CTRL_RDY_CMD;
+		paxb_pmi_write(core_idx, PMI_ADDR_LANE0(DSC_UC_CTRL),
+				rdata);
+
+		paxb_pmi_read(core_idx, PMI_ADDR_LANE1(DSC_UC_CTRL),
+				&rdata);
+		rdata |= DSC_UC_CTRL_RDY_CMD;
+		paxb_pmi_write(core_idx, PMI_ADDR_LANE1(DSC_UC_CTRL),
+				rdata);
+
+		/* Lane reset */
+		paxb_pmi_write(core_idx,
+				PMI_ADDR_BCAST(LANE_DBG_RST_CTRL), 0x3);
+
+		/* De-Assert Core and Master resets */
+		paxb_pmi_write(core_idx, PMI_ADDR_BCAST(UC_A_RST_CTRL0),
+				0x3);
+
+		timeout = UC_INIT_TIMEOUT;
+		while (timeout--) {
+			paxb_pmi_read(core_idx,
+					PMI_ADDR_LANE0(UC_VERSION_NUM),
+					&reg_d230);
+			paxb_pmi_read(core_idx,
+					PMI_ADDR_LANE0(DSC_SM_CTL22),
+					&reg_d267);
+
+			if (((reg_d230 & 0xffff) != 0) &
+					((reg_d267 & 0xc000) == 0xc000)) {
+				break;
+			}
+			mdelay(1);
+		}
+
+		if (!timeout)
+			return -EIO;
+
+		timeout = UC_INIT_TIMEOUT;
+		while (timeout--) {
+			paxb_pmi_read(core_idx,
+					PMI_ADDR_LANE1(UC_VERSION_NUM),
+					&reg_d230);
+			paxb_pmi_read(core_idx,
+					PMI_ADDR_LANE1(DSC_SM_CTL22),
+					&reg_d267);
+
+			if (((reg_d230 & 0xffff) != 0) &
+					((reg_d267 & 0xc000) == 0xc000)) {
+				break;
+			}
+			mdelay(1);
+		}
+
+		if (!timeout)
+			return -EIO;
+	}
+	return 0;
+}
+
+static int pcie_serdes_requires_patch(unsigned int serdes_idx)
+{
+	if (pipemux_idx != SERDES_PATCH_PIPEMUX_INDEX)
+		return 0;
+
+	return !!((SERDES_PATCH_INDEX >> serdes_idx) & 0x1);
+}
+
+static void pcie_tx_coeff_p7(unsigned int core_idx)
+{
+	paxb_pmi_write(core_idx, PMI_ADDR_BCAST(0xd11b), 0x00aa);
+	paxb_pmi_write(core_idx, PMI_ADDR_BCAST(0xd11c), 0x1155);
+	paxb_pmi_write(core_idx, PMI_ADDR_BCAST(0xd11d), 0x2449);
+	paxb_pmi_write(core_idx, PMI_ADDR_BCAST(0xd11e), 0x000f);
+	paxb_pmi_write(core_idx, PMI_ADDR_BCAST(0xd307), 0x0001);
+}
+
+
+static unsigned int paxb_sr_get_rc_link_width(unsigned int core_idx)
+{
+	return link_width_table[pipemux_idx][core_idx];
+}
+
+static uint32_t paxb_sr_get_rc_link_speed(void)
+{
+	return GEN3_LINK_SPEED;
+}
+
+
+static int paxb_serdes_init(unsigned int core_idx, unsigned int nr_serdes)
+{
+	uint32_t core_offset = core_idx * PCIE_CORE_PWR_OFFSET;
+	unsigned int serdes;
+	uintptr_t pmi_base;
+	int ret;
+
+	/*
+	 * Each serdes has a x2 link width
+	 *
+	 * Use PAXB to patch the serdes for proper RX termination through the
+	 * PMI interface
+	 */
+	pmi_base = (uintptr_t)(PCIE_CORE_PMI_CFG_BASE + core_offset);
+	for (serdes = 0; serdes < nr_serdes; serdes++) {
+		/* select the PMI interface */
+		mmio_write_32(pmi_base, serdes);
+
+		/* patch Serdes for RX termination */
+		ret = paxb_pmi_write(core_idx, PMI_RX_TERM_SEQ,
+				     PMI_RX_TERM_VAL);
+		if (ret)
+			goto err_pmi;
+
+		ret = paxb_pmi_write(core_idx, MERLIN16_PCIE_BLK2_PWRMGMT_7,
+				     MERLIN16_PCIE_BLK2_PWRMGMT_7_VAL);
+		if (ret)
+			goto err_pmi;
+
+		ret = paxb_pmi_write(core_idx, MERLIN16_PCIE_BLK2_PWRMGMT_8,
+				     MERLIN16_PCIE_BLK2_PWRMGMT_8_VAL);
+		if (ret)
+			goto err_pmi;
+
+		ret = paxb_pmi_write(core_idx, MERLIN16_AMS_TX_CTRL_5,
+				     MERLIN16_AMS_TX_CTRL_5_VAL);
+		if (ret)
+			goto err_pmi;
+
+		pcie_tx_coeff_p7(core_idx);
+
+		if (pcie_serdes_requires_patch(serdes)) {
+			if (((core_idx == 0) || (core_idx == 7))) {
+				ret = paxb_pmi_write(core_idx,
+						PMI_X8_CORE0_7_PATCH_SEQ,
+						PMI_X8_CORE0_7_PATCH_VAL);
+				if (ret)
+					goto err_pmi;
+			}
+		}
+	}
+
+	return 0;
+
+err_pmi:
+	ERROR("PCIe PMI write failed\n");
+	return ret;
+}
+
+static int paxb_sr_phy_init(void)
+{
+	int ret;
+	unsigned int core_idx;
+
+#ifndef BOARD_PCIE_EXT_CLK
+	ret = pcie_lcpll_init();
+	if (ret)
+		return ret;
+#else
+	pcie_ext_clk_init();
+#endif
+
+	for (core_idx = 0; core_idx < paxb->num_cores; core_idx++) {
+		if (!pcie_core_needs_enable(core_idx))
+			continue;
+		unsigned int link_width;
+
+		paxb_serdes_gate_clock(core_idx, 0);
+
+		link_width = paxb->get_link_width(core_idx);
+		if (!link_width) {
+			ERROR("Unsupported PIPEMUX\n");
+			return -EOPNOTSUPP;
+		}
+
+		ret = paxb_serdes_init(core_idx, link_width / 2);
+		if (ret) {
+			ERROR("PCIe serdes initialization failed for core %u\n",
+			      core_idx);
+			return ret;
+		}
+
+
+		ret = paxb_gen3_serdes_init(core_idx, link_width / 2);
+		if (ret) {
+			ERROR("PCIe GEN3 serdes initialization failed\n");
+			return ret;
+		}
+
+	}
+	return 0;
+}
+
+const paxb_cfg sr_paxb_cfg = {
+	.type = PAXB_SR,
+	.device_id = SR_B0_DEVICE_ID,
+	.pipemux_init = pipemux_sr_init,
+	.phy_init = paxb_sr_phy_init,
+	.core_needs_enable = paxb_sr_core_needs_enable,
+	.num_cores = NUM_OF_SR_PCIE_CORES,
+	.get_link_width = paxb_sr_get_rc_link_width,
+	.get_link_speed = paxb_sr_get_rc_link_speed,
+};
+
+const paxb_cfg *paxb_get_sr_config(void)
+{
+	return &sr_paxb_cfg;
+}