Merge pull request #1653 from JackyBai/master

Add NXP i.MX8MQ basic support 
diff --git a/docs/marvell/build.txt b/docs/marvell/build.txt
index 8a669c1..0682b77 100644
--- a/docs/marvell/build.txt
+++ b/docs/marvell/build.txt
@@ -78,9 +78,11 @@
 		Supported Options:
 			- DDR3 1CS (0): DB-88F3720-DDR3-Modular (512MB); EspressoBIN (512MB)
 			- DDR4 1CS (1): DB-88F3720-DDR4-Modular (512MB)
-			- DDR3 2CS (2): EspressoBIN (1GB)
+			- DDR3 2CS (2): EspressoBIN V3-V5 (1GB)
 			- DDR4 2CS (3): DB-88F3720-DDR4-Modular (4GB)
 			- DDR3 1CS (4): DB-88F3720-DDR3-Modular (1GB)
+			- DDR4 1CS (5): EspressoBin V7 (1GB)
+			- DDR4 2CS (6): EspressoBin V7 (2GB)
 			- CUSTOMER (CUST): Customer board, DDR3 1CS 512MB
 
 	- CLOCKSPRESET: For Armada37x0 only, the clock tree configuration preset including CPU and DDR frequency,
diff --git a/drivers/marvell/ap807_clocks_init.c b/drivers/marvell/ap807_clocks_init.c
new file mode 100644
index 0000000..841e6ae
--- /dev/null
+++ b/drivers/marvell/ap807_clocks_init.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <a8k_plat_def.h>
+#include <aro.h>
+#include <delay_timer.h>
+#include <mmio.h>
+
+/* Notify bootloader on DRAM setup */
+#define AP807_CPU_ARO_CTRL(cluster)	\
+			(MVEBU_RFU_BASE + 0x82A8 + (0xA58 * (cluster)))
+
+/* 0 - ARO clock is enabled, 1 - ARO clock is disabled */
+#define AP807_CPU_ARO_CLK_EN_OFFSET	0
+#define AP807_CPU_ARO_CLK_EN_MASK	(0x1 << AP807_CPU_ARO_CLK_EN_OFFSET)
+
+/* 0 - ARO is the clock source, 1 - PLL is the clock source */
+#define AP807_CPU_ARO_SEL_PLL_OFFSET	5
+#define AP807_CPU_ARO_SEL_PLL_MASK	(0x1 << AP807_CPU_ARO_SEL_PLL_OFFSET)
+
+/* AP807 clusters count */
+#define AP807_CLUSTER_NUM		2
+
+/* PLL frequency values */
+#define PLL_FREQ_1200			0x2AE5F002 /* 1200 */
+#define PLL_FREQ_2000			0x2FC9F002 /* 2000 */
+#define PLL_FREQ_2200			0x2AC57001 /* 2200 */
+#define PLL_FREQ_2400			0x2AE5F001 /* 2400 */
+
+/* CPU PLL control registers */
+#define AP807_CPU_PLL_CTRL(cluster)	\
+			(MVEBU_RFU_BASE + 0x82E0 + (0x8 * (cluster)))
+
+#define AP807_CPU_PLL_PARAM(cluster)	AP807_CPU_PLL_CTRL(cluster)
+#define AP807_CPU_PLL_CFG(cluster)	(AP807_CPU_PLL_CTRL(cluster) + 0x4)
+#define AP807_CPU_PLL_CFG_BYPASS_MODE	(0x1)
+#define AP807_CPU_PLL_CFG_USE_REG_FILE	(0x1 << 9)
+
+static void pll_set_freq(unsigned int freq_val)
+{
+	int i;
+
+	for (i = 0 ; i < AP807_CLUSTER_NUM ; i++) {
+		mmio_write_32(AP807_CPU_PLL_CFG(i),
+			      AP807_CPU_PLL_CFG_USE_REG_FILE);
+		mmio_write_32(AP807_CPU_PLL_CFG(i),
+			      AP807_CPU_PLL_CFG_USE_REG_FILE |
+			      AP807_CPU_PLL_CFG_BYPASS_MODE);
+		mmio_write_32(AP807_CPU_PLL_PARAM(i), freq_val);
+		mmio_write_32(AP807_CPU_PLL_CFG(i),
+			      AP807_CPU_PLL_CFG_USE_REG_FILE);
+	}
+}
+
+/* Switch to ARO from PLL in ap807 */
+static void aro_to_pll(void)
+{
+	unsigned int reg;
+	int i;
+
+	for (i = 0 ; i < AP807_CLUSTER_NUM ; i++) {
+		/* switch from ARO to PLL */
+		reg = mmio_read_32(AP807_CPU_ARO_CTRL(i));
+		reg |= AP807_CPU_ARO_SEL_PLL_MASK;
+		mmio_write_32(AP807_CPU_ARO_CTRL(i), reg);
+
+		mdelay(100);
+
+		/* disable ARO clk driver */
+		reg = mmio_read_32(AP807_CPU_ARO_CTRL(i));
+		reg |= (AP807_CPU_ARO_CLK_EN_MASK);
+		mmio_write_32(AP807_CPU_ARO_CTRL(i), reg);
+	}
+}
+
+/* switch from ARO to PLL
+ * in case of default frequency option, configure PLL registers
+ * to be aligned with new default frequency.
+ */
+void ap807_clocks_init(unsigned int freq_option)
+{
+	/* Switch from ARO to PLL */
+	aro_to_pll();
+
+	/* Modifications in frequency table:
+	 * 0x0: 764x: change to 2000 MHz.
+	 * 0x2: 744x change to 1800 MHz, 764x change to 2200/2400.
+	 * 0x3: 3900/744x/764x change to 1200 MHz.
+	 */
+	switch (freq_option) {
+	case CPU_2000_DDR_1200_RCLK_1200:
+		pll_set_freq(PLL_FREQ_2000);
+		break;
+	default:
+		break;
+	}
+}
diff --git a/drivers/marvell/comphy/phy-comphy-common.h b/drivers/marvell/comphy/phy-comphy-common.h
index 78c7a38..e3b430a 100644
--- a/drivers/marvell/comphy/phy-comphy-common.h
+++ b/drivers/marvell/comphy/phy-comphy-common.h
@@ -18,13 +18,15 @@
 #endif
 
 /* A lane is described by 4 fields:
- *      - bit 1~0 represent comphy polarity invert
- *      - bit 7~2 represent comphy speed
- *      - bit 11~8 represent unit index
- *      - bit 16~12 represent mode
- *      - bit 17 represent comphy indication of clock source
- *      - bit 19-18 represents pcie width (in case of pcie comphy config.)
- *      - bit 31~20 reserved
+ *  - bit 1~0 represent comphy polarity invert
+ *  - bit 7~2 represent comphy speed
+ *  - bit 11~8 represent unit index
+ *  - bit 16~12 represent mode
+ *  - bit 17 represent comphy indication of clock source
+ *  - bit 20~18 represents pcie width (in case of pcie comphy config.)
+ *  - bit 21 represents the source of the request (Linux/Bootloader),
+ *           (reguired only for PCIe!)
+ *  - bit 31~22 reserved
  */
 
 #define COMPHY_INVERT_OFFSET	0
@@ -50,6 +52,11 @@
 #define COMPHY_PCI_WIDTH_LEN	3
 #define COMPHY_PCI_WIDTH_MASK	COMPHY_MASK(COMPHY_PCI_WIDTH_OFFSET, \
 						COMPHY_PCI_WIDTH_LEN)
+#define COMPHY_PCI_CALLER_OFFSET \
+			(COMPHY_PCI_WIDTH_OFFSET + COMPHY_PCI_WIDTH_LEN)
+#define COMPHY_PCI_CALLER_LEN	1
+#define COMPHY_PCI_CALLER_MASK	COMPHY_MASK(COMPHY_PCI_CALLER_OFFSET, \
+						COMPHY_PCI_CALLER_LEN)
 
 #define COMPHY_MASK(offset, len)	(((1 << (len)) - 1) << (offset))
 
@@ -69,6 +76,10 @@
 #define COMPHY_GET_PCIE_WIDTH(x)	(((x) & COMPHY_PCI_WIDTH_MASK) >> \
 						COMPHY_PCI_WIDTH_OFFSET)
 
+/* Macro which extracts the caller for pcie power on from lane description */
+#define COMPHY_GET_CALLER(x)		(((x) & COMPHY_PCI_CALLER_MASK) >> \
+						COMPHY_PCI_CALLER_OFFSET)
+
 /* Macro which extracts the polarity invert from lane description */
 #define COMPHY_GET_POLARITY_INVERT(x)	(((x) & COMPHY_INVERT_MASK) >> \
 						COMPHY_INVERT_OFFSET)
diff --git a/drivers/marvell/comphy/phy-comphy-cp110.c b/drivers/marvell/comphy/phy-comphy-cp110.c
index 25893a9..86e5f1c 100644
--- a/drivers/marvell/comphy/phy-comphy-cp110.c
+++ b/drivers/marvell/comphy/phy-comphy-cp110.c
@@ -208,8 +208,8 @@
 			   */
 			if ((mode == COMPHY_SGMII_MODE ||
 			    mode == COMPHY_HS_SGMII_MODE ||
-			    mode == COMPHY_SFI_MODE) &&
-			    COMPHY_GET_ID(comphy_mode) == 1)
+			    mode == COMPHY_SFI_MODE || mode == COMPHY_XFI_MODE)
+			    && COMPHY_GET_ID(comphy_mode) == 1)
 				reg |= COMMON_SELECTOR_COMPHY4_PORT1 <<
 					comphy_offset;
 			else
@@ -1205,6 +1205,22 @@
 	uint32_t clk_dir;
 	uintptr_t hpipe_addr, comphy_addr, addr;
 	_Bool clk_src = COMPHY_GET_CLK_SRC(comphy_mode);
+	_Bool called_from_uboot = COMPHY_GET_CALLER(comphy_mode);
+
+	/* In Armada 8K DB boards, PCIe initialization can be executed
+	 * only once (PCIe reset performed during chip power on and
+	 * it cannot be executed via GPIO later).
+	 * This means that power on can be executed only once, so let's
+	 * mark if the caller is bootloader or Linux.
+	 * If bootloader -> run power on.
+	 * If Linux -> exit.
+	 *
+	 * TODO: In MacciatoBIN, PCIe reset is connected via GPIO,
+	 * so after GPIO reset is added to Linux Kernel, it can be
+	 * powered-on by Linux.
+	 */
+	if (!called_from_uboot)
+		return ret;
 
 	hpipe_addr = HPIPE_ADDR(COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base),
 				comphy_index);
@@ -2366,14 +2382,45 @@
 	return err;
 }
 
-int mvebu_cp110_comphy_power_off(uint64_t comphy_base, uint8_t comphy_index)
+int mvebu_cp110_comphy_power_off(uint64_t comphy_base, uint8_t comphy_index,
+				 uint64_t comphy_mode)
 {
 	uintptr_t sd_ip_addr, comphy_ip_addr;
 	uint32_t mask, data;
 	uint8_t ap_nr, cp_nr;
+	_Bool called_from_uboot = COMPHY_GET_CALLER(comphy_mode);
 
 	debug_enter();
 
+	/* Power-off might happen because of 2 things:
+	 *	1. Bootloader turns off unconnected lanes
+	 *	2. Linux turns off all lanes during boot
+	 *	   (and then reconfigure it).
+	 *
+	 * For PCIe, there's a problem:
+	 * In Armada 8K DB boards, PCIe initialization can be executed
+	 * only once (PCIe reset performed during chip power on and
+	 * it cannot be executed via GPIO later) so a lane configured to
+	 * PCIe should not be powered off by Linux.
+	 *
+	 * So, check 2 things:
+	 *	1. Is Linux called for power-off?
+	 *	2. Is the comphy configured to PCIe?
+	 * If the answer is YES for both 1 and 2, skip the power-off.
+	 *
+	 * TODO: In MacciatoBIN, PCIe reset is connected via GPIO,
+	 * so after GPIO reset is added to Linux Kernel, it can be
+	 * powered-off.
+	 */
+	if (!called_from_uboot) {
+		data = mmio_read_32(comphy_base +
+				    COMMON_SELECTOR_PIPE_REG_OFFSET);
+		data >>= (COMMON_SELECTOR_COMPHYN_FIELD_WIDTH * comphy_index);
+		data &= COMMON_SELECTOR_COMPHY_MASK;
+		if (data == COMMON_SELECTOR_PIPE_COMPHY_PCIE)
+			return 0;
+	}
+
 	mvebu_cp110_get_ap_and_cp_nr(&ap_nr, &cp_nr, comphy_base);
 
 	if (rx_trainng_done[ap_nr][cp_nr][comphy_index]) {
diff --git a/drivers/marvell/comphy/phy-comphy-cp110.h b/drivers/marvell/comphy/phy-comphy-cp110.h
index 70dbfbf..407909b 100644
--- a/drivers/marvell/comphy/phy-comphy-cp110.h
+++ b/drivers/marvell/comphy/phy-comphy-cp110.h
@@ -82,7 +82,7 @@
 int mvebu_cp110_comphy_is_pll_locked(uint64_t comphy_base,
 				     uint8_t comphy_index);
 int mvebu_cp110_comphy_power_off(uint64_t comphy_base,
-				 uint8_t comphy_index);
+				 uint8_t comphy_index, uint64_t comphy_mode);
 int mvebu_cp110_comphy_power_on(uint64_t comphy_base,
 				uint8_t comphy_index, uint64_t comphy_mode);
 int mvebu_cp110_comphy_xfi_rx_training(uint64_t comphy_base,
diff --git a/include/drivers/marvell/ap807_clocks_init.h b/include/drivers/marvell/ap807_clocks_init.h
new file mode 100644
index 0000000..4353b83
--- /dev/null
+++ b/include/drivers/marvell/ap807_clocks_init.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#ifndef AP807_INIT_CLOCKS_H
+#define AP807_INIT_CLOCKS_H
+
+void ap807_clocks_init(unsigned int freq_option);
+
+#endif /* AP807_INIT_CLOCKS_H */
+
diff --git a/include/plat/arm/common/arm_def.h b/include/plat/arm/common/arm_def.h
index d02a405..cbac247 100644
--- a/include/plat/arm/common/arm_def.h
+++ b/include/plat/arm/common/arm_def.h
@@ -34,6 +34,7 @@
 #define ARM_PWR_LVL0		MPIDR_AFFLVL0
 #define ARM_PWR_LVL1		MPIDR_AFFLVL1
 #define ARM_PWR_LVL2		MPIDR_AFFLVL2
+#define ARM_PWR_LVL3		MPIDR_AFFLVL3
 
 /*
  *  Macros for local power states in ARM platforms encoded by State-ID field
diff --git a/include/plat/arm/css/common/css_pm.h b/include/plat/arm/css/common/css_pm.h
index eeb72de..ff75c69 100644
--- a/include/plat/arm/css/common/css_pm.h
+++ b/include/plat/arm/css/common/css_pm.h
@@ -11,9 +11,6 @@
 #include <psci.h>
 #include <stdint.h>
 
-/* System power domain at level 2, as currently implemented by CSS platforms */
-#define CSS_SYSTEM_PWR_DMN_LVL		ARM_PWR_LVL2
-
 /* Macros to read the CSS power domain state */
 #define CSS_CORE_PWR_STATE(state)	(state)->pwr_domain_state[ARM_PWR_LVL0]
 #define CSS_CLUSTER_PWR_STATE(state)	(state)->pwr_domain_state[ARM_PWR_LVL1]
diff --git a/plat/arm/board/fvp/fvp_pm.c b/plat/arm/board/fvp/fvp_pm.c
index 7b85043..78d3025 100644
--- a/plat/arm/board/fvp/fvp_pm.c
+++ b/plat/arm/board/fvp/fvp_pm.c
@@ -416,3 +416,8 @@
 	.read_mem_protect	= arm_psci_read_mem_protect,
 	.write_mem_protect	= arm_nor_psci_write_mem_protect,
 };
+
+const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops)
+{
+	return ops;
+}
diff --git a/plat/arm/board/juno/include/platform_def.h b/plat/arm/board/juno/include/platform_def.h
index 0bbe3e1..8098bc3 100644
--- a/plat/arm/board/juno/include/platform_def.h
+++ b/plat/arm/board/juno/include/platform_def.h
@@ -295,4 +295,7 @@
 #define PLAT_ARM_PRIVATE_SDEI_EVENTS	ARM_SDEI_PRIVATE_EVENTS
 #define PLAT_ARM_SHARED_SDEI_EVENTS	ARM_SDEI_SHARED_EVENTS
 
+/* System power domain level */
+#define CSS_SYSTEM_PWR_DMN_LVL		ARM_PWR_LVL2
+
 #endif /* PLATFORM_DEF_H */
diff --git a/plat/arm/board/juno/juno_pm.c b/plat/arm/board/juno/juno_pm.c
new file mode 100644
index 0000000..da2e92b
--- /dev/null
+++ b/plat/arm/board/juno/juno_pm.c
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat_arm.h>
+#include <scmi.h>
+
+const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops)
+{
+	return css_scmi_override_pm_ops(ops);
+}
diff --git a/plat/arm/board/juno/platform.mk b/plat/arm/board/juno/platform.mk
index ba1acd4..ad955f6 100644
--- a/plat/arm/board/juno/platform.mk
+++ b/plat/arm/board/juno/platform.mk
@@ -27,6 +27,7 @@
 CSS_USE_SCMI_SDS_DRIVER		:=	1
 
 PLAT_INCLUDES		:=	-Iplat/arm/board/juno/include		\
+				-Iplat/arm/css/drivers/scmi		\
 				-Iplat/arm/css/drivers/sds
 
 PLAT_BL_COMMON_SOURCES	:=	plat/arm/board/juno/${ARCH}/juno_helpers.S \
@@ -79,6 +80,7 @@
 				lib/cpus/aarch64/cortex_a57.S		\
 				lib/cpus/aarch64/cortex_a72.S		\
 				lib/utils/mem_region.c			\
+				plat/arm/board/juno/juno_pm.c		\
 				plat/arm/board/juno/juno_topology.c	\
 				plat/arm/common/arm_nor_psci_mem_protect.c \
 				${JUNO_GIC_SOURCES}			\
diff --git a/plat/arm/board/juno/sp_min/sp_min-juno.mk b/plat/arm/board/juno/sp_min/sp_min-juno.mk
index 5278109..b3471c1 100644
--- a/plat/arm/board/juno/sp_min/sp_min-juno.mk
+++ b/plat/arm/board/juno/sp_min/sp_min-juno.mk
@@ -10,6 +10,7 @@
 			lib/cpus/aarch32/cortex_a57.S		\
 			lib/cpus/aarch32/cortex_a72.S		\
 			lib/utils/mem_region.c			\
+			plat/arm/board/juno/juno_pm.c		\
 			plat/arm/board/juno/juno_topology.c	\
 			plat/arm/common/arm_nor_psci_mem_protect.c	\
 			plat/arm/soc/common/soc_css_security.c	\
diff --git a/plat/arm/board/n1sdp/include/platform_def.h b/plat/arm/board/n1sdp/include/platform_def.h
index 3e48397..fa639ca 100644
--- a/plat/arm/board/n1sdp/include/platform_def.h
+++ b/plat/arm/board/n1sdp/include/platform_def.h
@@ -32,6 +32,8 @@
 						N1SDP_MAX_CPUS_PER_CLUSTER *	\
 						N1SDP_MAX_PE_PER_CPU)
 
+/* System power domain level */
+#define CSS_SYSTEM_PWR_DMN_LVL			ARM_PWR_LVL2
 
 /*
  * PLAT_ARM_MMAP_ENTRIES depends on the number of entries in the
diff --git a/plat/arm/board/n1sdp/n1sdp_bl31_setup.c b/plat/arm/board/n1sdp/n1sdp_bl31_setup.c
index 65aad9c..cdd0b63 100644
--- a/plat/arm/board/n1sdp/n1sdp_bl31_setup.c
+++ b/plat/arm/board/n1sdp/n1sdp_bl31_setup.c
@@ -6,6 +6,7 @@
 
 #include "../../css/drivers/scmi/scmi.h"
 #include "../../css/drivers/mhu/css_mhu_doorbell.h"
+#include <plat_arm.h>
 #include <platform_def.h>
 
 static scmi_channel_plat_info_t n1sdp_scmi_plat_info = {
@@ -20,3 +21,8 @@
 {
 	return &n1sdp_scmi_plat_info;
 }
+
+const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops)
+{
+	return css_scmi_override_pm_ops(ops);
+}
diff --git a/plat/arm/board/sgi575/include/platform_def.h b/plat/arm/board/sgi575/include/platform_def.h
index c06a0a1..16e2898 100644
--- a/plat/arm/board/sgi575/include/platform_def.h
+++ b/plat/arm/board/sgi575/include/platform_def.h
@@ -20,4 +20,9 @@
 #define SGI575_DMC620_BASE0		UL(0x4e000000)
 #define SGI575_DMC620_BASE1		UL(0x4e100000)
 
+/* System power domain level */
+#define CSS_SYSTEM_PWR_DMN_LVL		ARM_PWR_LVL2
+
+#define PLAT_MAX_PWR_LVL		ARM_PWR_LVL1
+
 #endif /* PLATFORM_DEF_H */
diff --git a/plat/arm/board/sgi575/platform.mk b/plat/arm/board/sgi575/platform.mk
index dd82d29..f31a8b7 100644
--- a/plat/arm/board/sgi575/platform.mk
+++ b/plat/arm/board/sgi575/platform.mk
@@ -14,12 +14,14 @@
 
 BL1_SOURCES		+=	${SGI_CPU_SOURCES}
 
-BL2_SOURCES		+=	${SGI575_BASE}/sgi575_security.c	\
+BL2_SOURCES		+=	${SGI575_BASE}/sgi575_plat.c		\
+				${SGI575_BASE}/sgi575_security.c	\
 				drivers/arm/tzc/tzc_dmc620.c		\
 				lib/utils/mem_region.c			\
 				plat/arm/common/arm_nor_psci_mem_protect.c
 
 BL31_SOURCES		+=	${SGI_CPU_SOURCES}			\
+				${SGI575_BASE}/sgi575_plat.c		\
 				drivers/cfi/v2m/v2m_flash.c		\
 				lib/utils/mem_region.c			\
 				plat/arm/common/arm_nor_psci_mem_protect.c
diff --git a/plat/arm/board/sgi575/sgi575_plat.c b/plat/arm/board/sgi575/sgi575_plat.c
new file mode 100644
index 0000000..a8ca916
--- /dev/null
+++ b/plat/arm/board/sgi575/sgi575_plat.c
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform.h>
+
+unsigned int plat_arm_sgi_get_platform_id(void)
+{
+	return mmio_read_32(SSC_VERSION) & SSC_VERSION_PART_NUM_MASK;
+}
+
+unsigned int plat_arm_sgi_get_config_id(void)
+{
+	return (mmio_read_32(SSC_VERSION) >> SSC_VERSION_CONFIG_SHIFT)
+			& SSC_VERSION_CONFIG_MASK;
+}
diff --git a/plat/arm/board/sgiclarka/include/platform_def.h b/plat/arm/board/sgiclarka/include/platform_def.h
index ba6d043..39907e8 100644
--- a/plat/arm/board/sgiclarka/include/platform_def.h
+++ b/plat/arm/board/sgiclarka/include/platform_def.h
@@ -20,4 +20,9 @@
 #define SGICLARKA_DMC620_BASE0		UL(0x4e000000)
 #define SGICLARKA_DMC620_BASE1		UL(0x4e100000)
 
+/* System power domain level */
+#define CSS_SYSTEM_PWR_DMN_LVL		ARM_PWR_LVL2
+
+#define PLAT_MAX_PWR_LVL		ARM_PWR_LVL1
+
 #endif /* PLATFORM_DEF_H */
diff --git a/plat/arm/board/sgiclarka/platform.mk b/plat/arm/board/sgiclarka/platform.mk
index cf02219..0773be5 100644
--- a/plat/arm/board/sgiclarka/platform.mk
+++ b/plat/arm/board/sgiclarka/platform.mk
@@ -14,12 +14,14 @@
 
 BL1_SOURCES		+=	${SGI_CPU_SOURCES}
 
-BL2_SOURCES		+=	${SGICLARKA_BASE}/sgiclarka_security.c	\
+BL2_SOURCES		+=	${SGICLARKA_BASE}/sgiclarka_plat.c	\
+				${SGICLARKA_BASE}/sgiclarka_security.c	\
 				drivers/arm/tzc/tzc_dmc620.c		\
 				lib/utils/mem_region.c			\
 				plat/arm/common/arm_nor_psci_mem_protect.c
 
 BL31_SOURCES		+=	${SGI_CPU_SOURCES}			\
+				${SGICLARKA_BASE}/sgiclarka_plat.c	\
 				drivers/cfi/v2m/v2m_flash.c		\
 				lib/utils/mem_region.c			\
 				plat/arm/common/arm_nor_psci_mem_protect.c
diff --git a/plat/arm/board/sgiclarka/sgiclarka_plat.c b/plat/arm/board/sgiclarka/sgiclarka_plat.c
new file mode 100644
index 0000000..3df2da6
--- /dev/null
+++ b/plat/arm/board/sgiclarka/sgiclarka_plat.c
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform.h>
+
+unsigned int plat_arm_sgi_get_platform_id(void)
+{
+	return mmio_read_32(SID_REG_BASE + SID_SYSTEM_ID_OFFSET)
+				& SID_SYSTEM_ID_PART_NUM_MASK;
+}
+
+unsigned int plat_arm_sgi_get_config_id(void)
+{
+	return mmio_read_32(SID_REG_BASE + SID_SYSTEM_CFG_OFFSET);
+}
diff --git a/plat/arm/common/arm_pm.c b/plat/arm/common/arm_pm.c
index 6394bfb..3be1b5d 100644
--- a/plat/arm/common/arm_pm.c
+++ b/plat/arm/common/arm_pm.c
@@ -14,7 +14,6 @@
 #include <psci.h>
 
 /* Allow ARM Standard platforms to override these functions */
-#pragma weak plat_arm_psci_override_pm_ops
 #pragma weak plat_arm_program_trusted_mailbox
 
 #if !ARM_RECOM_STATE_ID_ENC
@@ -133,14 +132,6 @@
 }
 
 /******************************************************************************
- * Default definition on ARM standard platforms to override the plat_psci_ops.
- *****************************************************************************/
-const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops)
-{
-	return ops;
-}
-
-/******************************************************************************
  * Helper function to save the platform state before a system suspend. Save the
  * state of the system components which are not in the Always ON power domain.
  *****************************************************************************/
diff --git a/plat/arm/css/drivers/scmi/scmi.h b/plat/arm/css/drivers/scmi/scmi.h
index e1358bf..28dfc9a 100644
--- a/plat/arm/css/drivers/scmi/scmi.h
+++ b/plat/arm/css/drivers/scmi/scmi.h
@@ -8,6 +8,7 @@
 #define SCMI_H
 
 #include <bakery_lock.h>
+#include <psci.h>
 #include <stddef.h>
 #include <stdint.h>
 #include <spinlock.h>
@@ -162,4 +163,7 @@
 /* API to get the platform specific SCMI channel information. */
 scmi_channel_plat_info_t *plat_css_get_scmi_info();
 
+/* API to override default PSCI callbacks for platforms that support SCMI. */
+const plat_psci_ops_t *css_scmi_override_pm_ops(plat_psci_ops_t *ops);
+
 #endif /* SCMI_H */
diff --git a/plat/arm/css/drivers/scp/css_pm_scmi.c b/plat/arm/css/drivers/scp/css_pm_scmi.c
index 956f583..1397fd8 100644
--- a/plat/arm/css/drivers/scp/css_pm_scmi.c
+++ b/plat/arm/css/drivers/scp/css_pm_scmi.c
@@ -339,7 +339,7 @@
  * the SCMI driver, query capability via SCMI and modify the PSCI capability
  * based on that.
  *****************************************************************************/
-const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops)
+const plat_psci_ops_t *css_scmi_override_pm_ops(plat_psci_ops_t *ops)
 {
 	uint32_t msg_attr;
 	int ret;
diff --git a/plat/arm/css/sgi/include/sgi_base_platform_def.h b/plat/arm/css/sgi/include/sgi_base_platform_def.h
index 1395373..8705d63 100644
--- a/plat/arm/css/sgi/include/sgi_base_platform_def.h
+++ b/plat/arm/css/sgi/include/sgi_base_platform_def.h
@@ -119,8 +119,6 @@
 #define PLAT_ARM_NSRAM_BASE		0x06000000
 #define PLAT_ARM_NSRAM_SIZE		0x00080000	/* 512KB */
 
-#define PLAT_MAX_PWR_LVL		U(1)
-
 #define PLAT_ARM_G1S_IRQ_PROPS(grp)	CSS_G1S_IRQ_PROPS(grp)
 #define PLAT_ARM_G0_IRQ_PROPS(grp)	ARM_G0_IRQ_PROPS(grp)
 
diff --git a/plat/arm/css/sgi/include/sgi_variant.h b/plat/arm/css/sgi/include/sgi_variant.h
index dea580b..56dc334 100644
--- a/plat/arm/css/sgi/include/sgi_variant.h
+++ b/plat/arm/css/sgi/include/sgi_variant.h
@@ -21,4 +21,10 @@
 
 extern sgi_platform_info_t sgi_plat_info;
 
+/* returns the part number of the platform*/
+unsigned int plat_arm_sgi_get_platform_id(void);
+
+/* returns the configuration id of the platform */
+unsigned int plat_arm_sgi_get_config_id(void);
+
 #endif /* SGI_VARIANT_H */
diff --git a/plat/arm/css/sgi/sgi_bl31_setup.c b/plat/arm/css/sgi/sgi_bl31_setup.c
index ce85026..a254388 100644
--- a/plat/arm/css/sgi/sgi_bl31_setup.c
+++ b/plat/arm/css/sgi/sgi_bl31_setup.c
@@ -42,53 +42,11 @@
 		panic();
 };
 
-/*******************************************************************************
- * This function sets the sgi_platform_id and sgi_config_id
- ******************************************************************************/
-int sgi_identify_platform(unsigned long hw_config)
-{
-	void *fdt;
-	int nodeoffset;
-	const unsigned int *property;
-
-	fdt = (void *)hw_config;
-
-	/* Check the validity of the fdt */
-	assert(fdt_check_header(fdt) == 0);
-
-	nodeoffset = fdt_subnode_offset(fdt, 0, "system-id");
-	if (nodeoffset < 0) {
-		ERROR("Failed to get system-id node offset\n");
-		return -1;
-	}
-
-	property = fdt_getprop(fdt, nodeoffset, "platform-id", NULL);
-	if (property == NULL) {
-		ERROR("Failed to get platform-id property\n");
-		return -1;
-	}
-
-	sgi_plat_info.platform_id = fdt32_to_cpu(*property);
-
-	property = fdt_getprop(fdt, nodeoffset, "config-id", NULL);
-	if (property == NULL) {
-		ERROR("Failed to get config-id property\n");
-		return -1;
-	}
-
-	sgi_plat_info.config_id = fdt32_to_cpu(*property);
-
-	return 0;
-}
-
 void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
 				u_register_t arg2, u_register_t arg3)
 {
-	int ret;
-
-	ret = sgi_identify_platform(arg2);
-	if (ret == -1)
-		panic();
+	sgi_plat_info.platform_id = plat_arm_sgi_get_platform_id();
+	sgi_plat_info.config_id = plat_arm_sgi_get_config_id();
 
 	arm_bl31_early_platform_setup((void *)arg0, arg1, arg2, (void *)arg3);
 }
@@ -101,3 +59,8 @@
 	sgi_ras_intr_handler_setup();
 #endif
 }
+
+const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops)
+{
+	return css_scmi_override_pm_ops(ops);
+}
diff --git a/plat/arm/css/sgi/sgi_image_load.c b/plat/arm/css/sgi/sgi_image_load.c
index d97583e..39069ca 100644
--- a/plat/arm/css/sgi/sgi_image_load.c
+++ b/plat/arm/css/sgi/sgi_image_load.c
@@ -9,6 +9,7 @@
 #include <desc_image_load.h>
 #include <libfdt.h>
 #include <platform.h>
+#include <sgi_variant.h>
 
 /*******************************************************************************
  * This function inserts Platform information via device tree nodes as,
@@ -23,7 +24,6 @@
 	void *fdt;
 	int nodeoffset, err;
 	unsigned int platid = 0, platcfg = 0;
-	char *platform_name;
 
 	mem_params = get_bl_mem_params_node(HW_CONFIG_ID);
 	if (mem_params == NULL) {
@@ -39,38 +39,20 @@
 		return -1;
 	}
 
-	platform_name = (char *)fdt_getprop(fdt, 0, "compatible", NULL);
-
-	if (platform_name == NULL) {
-		ERROR("Invalid HW_CONFIG DTB passed\n");
-		return -1;
-	}
-
-	if (strcmp(platform_name, "arm,sgi575") == 0) {
-		platid = mmio_read_32(SSC_VERSION) & SSC_VERSION_PART_NUM_MASK;
-		platcfg = (mmio_read_32(SSC_VERSION) >> SSC_VERSION_CONFIG_SHIFT)
-				& SSC_VERSION_CONFIG_MASK;
-	} else if (strcmp(platform_name, "arm,sgi-clark") == 0) {
-		platid = mmio_read_32(SID_REG_BASE + SID_SYSTEM_ID_OFFSET)
-				& SID_SYSTEM_ID_PART_NUM_MASK;
-		platcfg = mmio_read_32(SID_REG_BASE + SID_SYSTEM_CFG_OFFSET);
-	} else {
-		WARN("Invalid platform\n");
-		return -1;
-	}
-
 	nodeoffset = fdt_subnode_offset(fdt, 0, "system-id");
 	if (nodeoffset < 0) {
 		ERROR("Failed to get system-id node offset\n");
 		return -1;
 	}
 
+	platid = plat_arm_sgi_get_platform_id();
 	err = fdt_setprop_u32(fdt, nodeoffset, "platform-id", platid);
 	if (err < 0) {
 		ERROR("Failed to set platform-id\n");
 		return -1;
 	}
 
+	platcfg = plat_arm_sgi_get_config_id();
 	err = fdt_setprop_u32(fdt, nodeoffset, "config-id", platcfg);
 	if (err < 0) {
 		ERROR("Failed to set config-id\n");
diff --git a/plat/arm/css/sgi/sgi_topology.c b/plat/arm/css/sgi/sgi_topology.c
index 3b7a57a..e524f11 100644
--- a/plat/arm/css/sgi/sgi_topology.c
+++ b/plat/arm/css/sgi/sgi_topology.c
@@ -44,3 +44,11 @@
 	0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,		\
 	16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
 };
+
+/******************************************************************************
+ * Return the number of PE's supported by the CPU.
+ *****************************************************************************/
+unsigned int plat_arm_get_cpu_pe_count(u_register_t mpidr)
+{
+	return CSS_SGI_MAX_PE_PER_CPU;
+}
diff --git a/plat/arm/css/sgm/include/sgm_base_platform_def.h b/plat/arm/css/sgm/include/sgm_base_platform_def.h
index a9795a4..2178f06 100644
--- a/plat/arm/css/sgm/include/sgm_base_platform_def.h
+++ b/plat/arm/css/sgm/include/sgm_base_platform_def.h
@@ -239,4 +239,8 @@
  */
 #define PLAT_ARM_MEM_PROT_ADDR		(V2M_FLASH0_BASE + \
 					 V2M_FLASH0_SIZE - V2M_FLASH_BLOCK_SIZE)
+
+/* System power domain level */
+#define CSS_SYSTEM_PWR_DMN_LVL		ARM_PWR_LVL2
+
 #endif /* SGM_BASE_PLATFORM_DEF_H */
diff --git a/plat/arm/css/sgm/sgm_bl31_setup.c b/plat/arm/css/sgm/sgm_bl31_setup.c
index 29c32e7..952572e 100644
--- a/plat/arm/css/sgm/sgm_bl31_setup.c
+++ b/plat/arm/css/sgm/sgm_bl31_setup.c
@@ -47,3 +47,8 @@
 
 	arm_bl31_early_platform_setup((void *)arg0, arg1, arg2, (void *)arg3);
 }
+
+const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops)
+{
+	return css_scmi_override_pm_ops(ops);
+}
diff --git a/plat/hisilicon/hikey960/hikey960_bl31_setup.c b/plat/hisilicon/hikey960/hikey960_bl31_setup.c
index c1be1f6..2261470 100644
--- a/plat/hisilicon/hikey960/hikey960_bl31_setup.c
+++ b/plat/hisilicon/hikey960/hikey960_bl31_setup.c
@@ -14,6 +14,7 @@
 #include <generic_delay_timer.h>
 #include <gicv2.h>
 #include <hi3660.h>
+#include <mmio.h>
 #include <hisi_ipc.h>
 #include <interrupt_mgmt.h>
 #include <interrupt_props.h>
@@ -143,6 +144,19 @@
 			BL31_COHERENT_RAM_LIMIT);
 }
 
+static void hikey960_edma_init(void)
+{
+	int i;
+	uint32_t non_secure;
+
+	non_secure = EDMAC_SEC_CTRL_INTR_SEC | EDMAC_SEC_CTRL_GLOBAL_SEC;
+	mmio_write_32(EDMAC_SEC_CTRL, non_secure);
+
+	for (i = 0; i < EDMAC_CHANNEL_NUMS; i++) {
+		mmio_write_32(EDMAC_AXI_CONF(i), (1 << 6) | (1 << 18));
+	}
+}
+
 void bl31_platform_setup(void)
 {
 	/* Initialize the GIC driver, cpu and distributor interfaces */
@@ -151,6 +165,8 @@
 	gicv2_pcpu_distif_init();
 	gicv2_cpuif_enable();
 
+	hikey960_edma_init();
+
 	hisi_ipc_init();
 }
 
diff --git a/plat/hisilicon/hikey960/include/hi3660.h b/plat/hisilicon/hikey960/include/hi3660.h
index 8ce531e..c9ecd32 100644
--- a/plat/hisilicon/hikey960/include/hi3660.h
+++ b/plat/hisilicon/hikey960/include/hi3660.h
@@ -366,4 +366,11 @@
 /* GPIO219: PD interrupt. pull up */
 #define IOCG_AO_043_REG			(IOCG_AO_REG_BASE + 0x030)
 
+#define EDMAC_BASE				0xfdf30000
+#define EDMAC_SEC_CTRL				(EDMAC_BASE + 0x694)
+#define EDMAC_AXI_CONF(x)			(EDMAC_BASE + 0x820 + (x << 6))
+#define EDMAC_SEC_CTRL_INTR_SEC			(1 << 1)
+#define EDMAC_SEC_CTRL_GLOBAL_SEC		(1 << 0)
+#define EDMAC_CHANNEL_NUMS				16
+
 #endif /* HI3660_H */
diff --git a/plat/marvell/a3700/common/plat_pm.c b/plat/marvell/a3700/common/plat_pm.c
index 5cebc92..dce4841 100644
--- a/plat/marvell/a3700/common/plat_pm.c
+++ b/plat/marvell/a3700/common/plat_pm.c
@@ -288,18 +288,9 @@
  */
 void a3700_pwr_domain_off(const psci_power_state_t *target_state)
 {
-	uint32_t cpu_idx = plat_my_core_pos();
-
 	/* Prevent interrupts from spuriously waking up this cpu */
 	plat_marvell_gic_cpuif_disable();
 
-	/*
-	 * Enable Core VDD OFF, core is supposed to be powered
-	 * off by PMU when WFI command is issued.
-	 */
-	mmio_setbits_32(MVEBU_PM_CPU_0_PWR_CTRL_REG + 4 * cpu_idx,
-			MVEBU_PM_CORE_PD);
-
 	/* Core can not be powered down with pending IRQ,
 	 * acknowledge all the pending IRQ
 	 */
diff --git a/plat/marvell/a8k/a80x0/board/phy-porting-layer.h b/plat/marvell/a8k/a80x0/board/phy-porting-layer.h
index 38497fb..abd85b5 100644
--- a/plat/marvell/a8k/a80x0/board/phy-porting-layer.h
+++ b/plat/marvell/a8k/a80x0/board/phy-porting-layer.h
@@ -27,7 +27,14 @@
 			  .g1_rx_selmupf = 0x2, .g1_rx_selmupi = 0x2,
 			  .valid = 0x1 }, /* Comphy2 */
 			{ 0 }, /* Comphy3 */
-			{ 0 }, /* Comphy4 */
+			{ .g1_ffe_res_sel = 0x3, .g1_ffe_cap_sel = 0xf,
+			  .align90 = 0x5f,
+			  .g1_dfe_res = 0x2, .g1_amp = 0x1c, .g1_emph = 0xe,
+			  .g1_emph_en = 0x1, .g1_tx_amp_adj = 0x1,
+			  .g1_tx_emph_en = 0x1, .g1_tx_emph = 0x0,
+			  .g1_rx_selmuff = 0x1, .g1_rx_selmufi = 0x0,
+			  .g1_rx_selmupf = 0x2, .g1_rx_selmupi = 0x2,
+			  .valid = 0x1 }, /* Comphy4 */
 			{ 0 }, /* Comphy5 */
 		},
 
@@ -44,7 +51,14 @@
 			  .g1_rx_selmupf = 0x2, .g1_rx_selmupi = 0x2,
 			  .valid = 0x1 }, /* Comphy2 */
 			{ 0 }, /* Comphy3 */
-			{ 0 }, /* Comphy4 */
+			{ .g1_ffe_res_sel = 0x3, .g1_ffe_cap_sel = 0xf,
+			  .align90 = 0x5f,
+			  .g1_dfe_res = 0x2, .g1_amp = 0x1c, .g1_emph = 0xe,
+			  .g1_emph_en = 0x1, .g1_tx_amp_adj = 0x1,
+			  .g1_tx_emph_en = 0x1, .g1_tx_emph = 0x0,
+			  .g1_rx_selmuff = 0x1, .g1_rx_selmufi = 0x0,
+			  .g1_rx_selmupf = 0x2, .g1_rx_selmupi = 0x2,
+			  .valid = 0x1 }, /* Comphy4 */
 			{ 0 }, /* Comphy5 */
 		},
 	},
diff --git a/plat/marvell/a8k/common/a8k_common.mk b/plat/marvell/a8k/common/a8k_common.mk
index 6136a1f..88d9311 100644
--- a/plat/marvell/a8k/common/a8k_common.mk
+++ b/plat/marvell/a8k/common/a8k_common.mk
@@ -13,6 +13,9 @@
 MARVELL_DRV_BASE	:= drivers/marvell
 MARVELL_COMMON_BASE	:= plat/marvell/common
 
+MARVELL_SVC_TEST		:= 0
+$(eval $(call add_define,MARVELL_SVC_TEST))
+
 ERRATA_A72_859971	:= 1
 
 # Enable MSS support for a8k family
@@ -60,14 +63,15 @@
 
 MARVELL_MOCHI_DRV	+=	$(MARVELL_DRV_BASE)/mochi/cp110_setup.c
 
-BLE_SOURCES		:=	drivers/mentor/i2c/mi2cv.c			\
-				$(PLAT_COMMON_BASE)/plat_ble_setup.c		\
-				$(MARVELL_MOCHI_DRV)			       \
-				$(PLAT_COMMON_BASE)/plat_pm.c		 	\
-				$(MARVELL_DRV_BASE)/thermal.c			\
-				$(PLAT_COMMON_BASE)/plat_thermal.c		\
-				$(BLE_PORTING_SOURCES)				\
-				$(MARVELL_DRV_BASE)/ccu.c			\
+BLE_SOURCES		:=	drivers/mentor/i2c/mi2cv.c		\
+				$(PLAT_COMMON_BASE)/plat_ble_setup.c	\
+				$(MARVELL_MOCHI_DRV)			\
+				$(PLAT_COMMON_BASE)/plat_pm.c		\
+				$(MARVELL_DRV_BASE)/ap807_clocks_init.c	\
+				$(MARVELL_DRV_BASE)/thermal.c		\
+				$(PLAT_COMMON_BASE)/plat_thermal.c	\
+				$(BLE_PORTING_SOURCES)			\
+				$(MARVELL_DRV_BASE)/ccu.c		\
 				$(MARVELL_DRV_BASE)/io_win.c
 
 BL1_SOURCES		+=	$(PLAT_COMMON_BASE)/aarch64/plat_helpers.S \
diff --git a/plat/marvell/a8k/common/mss/mss_pm_ipc.c b/plat/marvell/a8k/common/mss/mss_pm_ipc.c
index 6ff4abc..d1297b0 100644
--- a/plat/marvell/a8k/common/mss/mss_pm_ipc.c
+++ b/plat/marvell/a8k/common/mss/mss_pm_ipc.c
@@ -26,7 +26,7 @@
 
 #define MSS_MSG_INT_MASK	(0x80000000)
 #define MSS_TIMER_BASE		(MVEBU_REGS_BASE_MASK + 0x580110)
-#define MSS_TRIGGER_TIMEOUT	(1000)
+#define MSS_TRIGGER_TIMEOUT	(2000)
 
 /*****************************************************************************
  * mss_pm_ipc_msg_send
diff --git a/plat/marvell/a8k/common/plat_ble_setup.c b/plat/marvell/a8k/common/plat_ble_setup.c
index 7438f69..dbadeb7 100644
--- a/plat/marvell/a8k/common/plat_ble_setup.c
+++ b/plat/marvell/a8k/common/plat_ble_setup.c
@@ -15,14 +15,15 @@
 #include <mv_ddr_if.h>
 #include <mvebu_def.h>
 #include <plat_marvell.h>
+#include "ap807_clocks_init.h"
 
 /* Register for skip image use */
 #define SCRATCH_PAD_REG2		0xF06F00A8
 #define SCRATCH_PAD_SKIP_VAL		0x01
 #define NUM_OF_GPIO_PER_REG 32
 
-#define MMAP_SAVE_AND_CONFIG	0
-#define MMAP_RESTORE_SAVED	1
+#define MMAP_SAVE_AND_CONFIG		0
+#define MMAP_RESTORE_SAVED		1
 
 /* SAR clock settings */
 #define MVEBU_AP_GEN_MGMT_BASE		(MVEBU_RFU_BASE + 0x8000)
@@ -40,6 +41,7 @@
 #define SAR_CLOCK_FREQ_MODE(v)		(((v) & SAR_CLOCK_FREQ_MODE_MASK) >> \
 					SAR_CLOCK_FREQ_MODE_OFFSET)
 
+#define AVS_I2C_EEPROM_ADDR		0x57	/* EEPROM */
 #define AVS_EN_CTRL_REG			(MVEBU_AP_GEN_MGMT_BASE + 0x130)
 #define AVS_ENABLE_OFFSET		(0)
 #define AVS_SOFT_RESET_OFFSET		(2)
@@ -71,28 +73,25 @@
 					 (0x24 << AVS_LOW_VDD_LIMIT_OFFSET) | \
 					 (0x1 << AVS_SOFT_RESET_OFFSET) | \
 					 (0x1 << AVS_ENABLE_OFFSET))
-
+/* VDD limit is 0.82V for all A3900 devices
+ * AVS offsets are not the same as in A70x0
+ */
 #define AVS_A3900_CLK_VALUE		((0x80 << 24) | \
 					 (0x2c2 << 13) | \
 					 (0x2c2 << 3) | \
 					 (0x1 << AVS_SOFT_RESET_OFFSET) | \
 					 (0x1 << AVS_ENABLE_OFFSET))
+/* VDD is 0.88V for 2GHz clock */
+#define AVS_A3900_HIGH_CLK_VALUE	((0x80 << 24) | \
+					 (0x2f5 << 13) | \
+					 (0x2f5 << 3) | \
+					 (0x1 << AVS_SOFT_RESET_OFFSET) | \
+					 (0x1 << AVS_ENABLE_OFFSET))
 
 #define MVEBU_AP_EFUSE_SRV_CTRL_REG	(MVEBU_AP_GEN_MGMT_BASE + 0x8)
 #define EFUSE_SRV_CTRL_LD_SELECT_OFFS	6
 #define EFUSE_SRV_CTRL_LD_SEL_USER_MASK	(1 << EFUSE_SRV_CTRL_LD_SELECT_OFFS)
 
-/* Notify bootloader on DRAM setup */
-#define AP807_CPU_ARO_0_CTRL_0		(MVEBU_RFU_BASE + 0x82A8)
-#define AP807_CPU_ARO_1_CTRL_0		(MVEBU_RFU_BASE + 0x8D00)
-
-/* 0 - ARO clock is enabled, 1 - ARO clock is disabled */
-#define AP807_CPU_ARO_CLK_EN_OFFSET	0
-#define AP807_CPU_ARO_CLK_EN_MASK	(0x1 << AP807_CPU_ARO_CLK_EN_OFFSET)
-
-/* 0 - ARO is the clock source, 1 - PLL is the clock source */
-#define AP807_CPU_ARO_SEL_PLL_OFFSET	5
-#define AP807_CPU_ARO_SEL_PLL_MASK	(0x1 << AP807_CPU_ARO_SEL_PLL_OFFSET)
 
 /*
  * - Identification information in the LD-0 eFuse:
@@ -143,9 +142,16 @@
 	#define EFUSE_AP_LD0_WP_MASK		0x3FF
 #endif
 
+#define EFUSE_AP_LD0_SVC4_OFFS			42	/* LD0[112:105] */
+
-#define EFUSE_AP_LD0_SVC4_OFFS		42		/* LD0[112:105] */
+#define EFUSE_AP_LD0_CLUSTER_DOWN_OFFS		4
 
-#define EFUSE_AP_LD0_CLUSTER_DOWN_OFFS	4
+#if MARVELL_SVC_TEST
+#define MVEBU_CP_MPP_CTRL37_OFFS	20
+#define MVEBU_CP_MPP_CTRL38_OFFS	24
+#define MVEBU_CP_MPP_I2C_FUNC		2
+#define MVEBU_MPP_CTRL_MASK		0xf
+#endif
 
 /* Return the AP revision of the chip */
 static unsigned int ble_get_ap_type(void)
@@ -205,40 +211,155 @@
  * Setup Adaptive Voltage Switching - this is required for some platforms
  ****************************************************************************
  */
+#if !MARVELL_SVC_TEST
 static void ble_plat_avs_config(void)
 {
-	uint32_t reg_val, device_id;
+	uint32_t freq_mode, device_id;
+	uint32_t avs_val = 0;
 
+	freq_mode =
+		SAR_CLOCK_FREQ_MODE(mmio_read_32(MVEBU_AP_SAR_REG_BASE(
+						 FREQ_MODE_AP_SAR_REG_NUM)));
 	/* Check which SoC is running and act accordingly */
 	if (ble_get_ap_type() == CHIP_ID_AP807) {
-		VERBOSE("AVS: Setting AP807 AVS CTRL to 0x%x\n",
-			AVS_A3900_CLK_VALUE);
-		mmio_write_32(AVS_EN_CTRL_REG, AVS_A3900_CLK_VALUE);
-		return;
+		/* Increase CPU voltage for higher CPU clock */
+		if (freq_mode == CPU_2000_DDR_1200_RCLK_1200)
+			avs_val = AVS_A3900_HIGH_CLK_VALUE;
+		else
+			avs_val = AVS_A3900_CLK_VALUE;
+	} else {
+		/* Check which SoC is running and act accordingly */
+		device_id = cp110_device_id_get(MVEBU_CP_REGS_BASE(0));
+		switch (device_id) {
+		case MVEBU_80X0_DEV_ID:
+		case MVEBU_80X0_CP115_DEV_ID:
+			/* Always fix the default AVS value on A80x0 */
+			avs_val = AVS_A8K_CLK_VALUE;
+			break;
+		case MVEBU_70X0_DEV_ID:
+		case MVEBU_70X0_CP115_DEV_ID:
+			/* Fix AVS for CPU clocks lower than 1600MHz on A70x0 */
+			if ((freq_mode > CPU_1600_DDR_900_RCLK_900_2) &&
+			    (freq_mode < CPU_DDR_RCLK_INVALID))
+				avs_val = AVS_A7K_LOW_CLK_VALUE;
+			break;
+		default:
+			ERROR("Unsupported Device ID 0x%x\n", device_id);
+			return;
+		}
 	}
 
-	/* Check which SoC is running and act accordingly */
-	device_id = cp110_device_id_get(MVEBU_CP_REGS_BASE(0));
-	switch (device_id) {
-	case MVEBU_80X0_DEV_ID:
-	case MVEBU_80X0_CP115_DEV_ID:
-		/* Set the new AVS value - fix the default one on A80x0 */
-		mmio_write_32(AVS_EN_CTRL_REG, AVS_A8K_CLK_VALUE);
-		break;
-	case MVEBU_70X0_DEV_ID:
-	case MVEBU_70X0_CP115_DEV_ID:
-		/* Only fix AVS for CPU clocks lower than 1600MHz on A70x0 */
-		reg_val = mmio_read_32(MVEBU_AP_SAR_REG_BASE(
-						FREQ_MODE_AP_SAR_REG_NUM));
-		reg_val &= SAR_CLOCK_FREQ_MODE_MASK;
-		reg_val >>= SAR_CLOCK_FREQ_MODE_OFFSET;
-		if ((reg_val > CPU_1600_DDR_900_RCLK_900_2) &&
-		    (reg_val < CPU_DDR_RCLK_INVALID))
-			mmio_write_32(AVS_EN_CTRL_REG, AVS_A7K_LOW_CLK_VALUE);
-		break;
-	default:
-		ERROR("Unsupported Device ID 0x%x\n", device_id);
+	if (avs_val) {
+		VERBOSE("AVS: Setting AVS CTRL to 0x%x\n", avs_val);
+		mmio_write_32(AVS_EN_CTRL_REG, avs_val);
+	}
+}
+#endif
+/******************************************************************************
+ * Update or override current AVS work point value using data stored in EEPROM
+ * This is only required by QA/validation flows and activated by
+ * MARVELL_SVC_TEST flag.
+ *
+ * The function is expected to be called twice.
+ *
+ * First time with AVS value of 0 for testing if the EEPROM requests completely
+ * override the AVS value and bypass the eFuse test
+ *
+ * Second time - with non-zero AVS value obtained from eFuses as an input.
+ * In this case the EEPROM may contain AVS correction value (either positive
+ * or negative) that is added to the input AVS value and returned back for
+ * further processing.
+ ******************************************************************************
+ */
+static uint32_t avs_update_from_eeprom(uint32_t avs_workpoint)
+{
+	uint32_t new_wp = avs_workpoint;
+#if MARVELL_SVC_TEST
+	/* ---------------------------------------------------------------------
+	 * EEPROM  |  Data description (avs_step)
+	 * address |
+	 * ---------------------------------------------------------------------
+	 * 0x120   | AVS workpoint correction value
+	 *         | if not 0 and not 0xff, correct the AVS taken from eFuse
+	 *         | by the number of steps indicated by bit[6:0]
+	 *         | bit[7] defines correction direction.
+	 *         | If bit[7]=1, add the value from bit[6:0] to AVS workpoint,
+	 *         | othervise substruct this value from AVS workpoint.
+	 * ---------------------------------------------------------------------
+	 * 0x121   | AVS workpoint override value
+	 *         | Override the AVS workpoint with the value stored in this
+	 *         | byte. When running on AP806, the AVS workpoint is 7 bits
+	 *         | wide and override value is valid when bit[6:0] holds
+	 *         | value greater than zero and smaller than 0x33.
+	 *         | When running on AP807, the AVS workpoint is 10 bits wide.
+	 *         | Additional 2 MSB bits are supplied by EEPROM byte 0x122.
+	 *         | AVS override value is valid when byte @ 0x121 and bit[1:0]
+	 *         | of byte @ 0x122 combined have non-zero value.
+	 * ---------------------------------------------------------------------
+	 * 0x122   | Extended AVS workpoint override value
+	 *         | Valid only for AP807 platforms and must be less than 0x4
+	 * ---------------------------------------------------------------------
+	 */
+	static uint8_t  avs_step[3] = {0};
+	uintptr_t reg;
+	uint32_t val;
+	unsigned int ap_type = ble_get_ap_type();
+
+	/* Always happens on second call to this function */
+	if (avs_workpoint != 0) {
+		/* Get correction steps from the EEPROM */
+		if ((avs_step[0] != 0) && (avs_step[0] != 0xff)) {
+			NOTICE("AVS request to step %s by 0x%x from old 0x%x\n",
+				avs_step[0] & 0x80 ? "DOWN" : "UP",
+				avs_step[0] & 0x7f, new_wp);
+			if (avs_step[0] & 0x80)
+				new_wp -= avs_step[0] & 0x7f;
+			else
+				new_wp += avs_step[0] & 0x7f;
+		}
+
+		return new_wp;
+	}
+
+	/* AVS values are located in EEPROM
+	 * at CP0 i2c bus #0, device 0x57 offset 0x120
+	 * The SDA and SCK pins of CP0 i2c-0: MPP[38:37], i2c function 0x2.
+	 */
+	reg = MVEBU_CP_MPP_REGS(0, 4);
+	val = mmio_read_32(reg);
+	val &= ~((MVEBU_MPP_CTRL_MASK << MVEBU_CP_MPP_CTRL37_OFFS) |
+		 (MVEBU_MPP_CTRL_MASK << MVEBU_CP_MPP_CTRL38_OFFS));
+	val |= (MVEBU_CP_MPP_I2C_FUNC << MVEBU_CP_MPP_CTRL37_OFFS) |
+		(MVEBU_CP_MPP_I2C_FUNC << MVEBU_CP_MPP_CTRL38_OFFS);
+	mmio_write_32(reg, val);
+
+	/* Init CP0 i2c-0 */
+	i2c_init((void *)(MVEBU_CP0_I2C_BASE));
+
+	/* Read EEPROM only once at the fist call! */
+	i2c_read(AVS_I2C_EEPROM_ADDR, 0x120, 2, avs_step, 3);
+	NOTICE("== SVC test build ==\n");
+	NOTICE("EEPROM holds values 0x%x, 0x%x and 0x%x\n",
+		avs_step[0], avs_step[1], avs_step[2]);
+
+	/* Override the AVS value? */
+	if ((ap_type != CHIP_ID_AP807) && (avs_step[1] < 0x33)) {
+		/* AP806 - AVS is 7 bits */
+		new_wp = avs_step[1];
+
+	} else if (ap_type == CHIP_ID_AP807 && (avs_step[2] < 0x4)) {
+		/* AP807 - AVS is 10 bits */
+		new_wp = avs_step[2];
+		new_wp <<= 8;
+		new_wp |= avs_step[1];
 	}
+
+	if (new_wp == 0)
+		NOTICE("Ignore BAD AVS Override value in EEPROM!\n");
+	else
+		NOTICE("Override AVS by EEPROM value 0x%x\n", new_wp);
+#endif /* MARVELL_SVC_TEST */
+	return new_wp;
 }
 
 /****************************************************************************
@@ -262,6 +383,11 @@
 	unsigned int ap_type;
 
 	/* Set access to LD0 */
+	avs_workpoint = avs_update_from_eeprom(0);
+	if (avs_workpoint)
+		goto set_aws_wp;
+
+	/* Set access to LD0 */
 	reg_val = mmio_read_32(MVEBU_AP_EFUSE_SRV_CTRL_REG);
 	reg_val &= ~EFUSE_SRV_CTRL_LD_SELECT_OFFS;
 	mmio_write_32(MVEBU_AP_EFUSE_SRV_CTRL_REG, reg_val);
@@ -279,7 +405,12 @@
 	sw_ver = (efuse >> EFUSE_AP_LD0_SWREV_OFFS) & EFUSE_AP_LD0_SWREV_MASK;
 	if (sw_ver < 1) {
 		NOTICE("SVC: SW Revision 0x%x. SVC is not supported\n", sw_ver);
+#if MARVELL_SVC_TEST
+		NOTICE("SVC_TEST: AVS bypassed\n");
+
+#else
 		ble_plat_avs_config();
+#endif
 		return;
 	}
 
@@ -447,6 +578,10 @@
 	if (ap_type != CHIP_ID_AP807)
 		avs_workpoint &= 0x7F;
 
+	/* Update WP from EEPROM if needed */
+	avs_workpoint = avs_update_from_eeprom(avs_workpoint);
+
+set_aws_wp:
 	reg_val  = mmio_read_32(AVS_EN_CTRL_REG);
 	NOTICE("SVC: AVS work point changed from 0x%x to 0x%x\n",
 		(reg_val & AVS_VDD_LOW_LIMIT_MASK) >> AVS_LOW_VDD_LIMIT_OFFSET,
@@ -543,35 +678,11 @@
 }
 #endif
 
-/* Switch to ARO from PLL in ap807 */
-static void aro_to_pll(void)
-{
-	unsigned int reg;
-
-	/* switch from ARO to PLL */
-	reg = mmio_read_32(AP807_CPU_ARO_0_CTRL_0);
-	reg |= AP807_CPU_ARO_SEL_PLL_MASK;
-	mmio_write_32(AP807_CPU_ARO_0_CTRL_0, reg);
-
-	reg = mmio_read_32(AP807_CPU_ARO_1_CTRL_0);
-	reg |= AP807_CPU_ARO_SEL_PLL_MASK;
-	mmio_write_32(AP807_CPU_ARO_1_CTRL_0, reg);
-
-	mdelay(1000);
-
-	/* disable ARO clk driver */
-	reg = mmio_read_32(AP807_CPU_ARO_0_CTRL_0);
-	reg |= (AP807_CPU_ARO_CLK_EN_MASK);
-	mmio_write_32(AP807_CPU_ARO_0_CTRL_0, reg);
-
-	reg = mmio_read_32(AP807_CPU_ARO_1_CTRL_0);
-	reg |= (AP807_CPU_ARO_CLK_EN_MASK);
-	mmio_write_32(AP807_CPU_ARO_1_CTRL_0, reg);
-}
 
 int ble_plat_setup(int *skip)
 {
 	int ret;
+	unsigned int freq_mode;
 
 	/* Power down unused CPUs */
 	plat_marvell_early_cpu_powerdown();
@@ -598,9 +709,14 @@
 	/* Setup AVS */
 	ble_plat_svc_config();
 
+	/* read clk option from sampled-at-reset register */
+	freq_mode =
+		SAR_CLOCK_FREQ_MODE(mmio_read_32(MVEBU_AP_SAR_REG_BASE(
+						 FREQ_MODE_AP_SAR_REG_NUM)));
+
 	/* work with PLL clock driver in AP807 */
 	if (ble_get_ap_type() == CHIP_ID_AP807)
-		aro_to_pll();
+		ap807_clocks_init(freq_mode);
 
 	/* Do required AP setups for BLE stage */
 	ap_ble_init();
diff --git a/plat/marvell/a8k/common/plat_pm.c b/plat/marvell/a8k/common/plat_pm.c
index 1b68d07..2854416 100644
--- a/plat/marvell/a8k/common/plat_pm.c
+++ b/plat/marvell/a8k/common/plat_pm.c
@@ -79,7 +79,7 @@
 	#define PWRC_CPUN_CR_PWR_DN_RQ_OFFSET		1
 	#define PWRC_CPUN_CR_LDO_BYPASS_RDY_OFFSET	0
 #else
-#define PWRC_CPUN_CR_PWR_DN_RQ_OFFSET		0
+	#define PWRC_CPUN_CR_PWR_DN_RQ_OFFSET		0
 	#define PWRC_CPUN_CR_LDO_BYPASS_RDY_OFFSET	31
 #endif
 
@@ -106,7 +106,7 @@
 #define AP807_PWRC_LDO_CR0_OFFSET		16
 #define AP807_PWRC_LDO_CR0_MASK			\
 			(0xff << AP807_PWRC_LDO_CR0_OFFSET)
-#define AP807_PWRC_LDO_CR0_VAL			0xfd
+#define AP807_PWRC_LDO_CR0_VAL			0xfc
 
 /*
  * Power down CPU:
diff --git a/plat/marvell/common/mrvl_sip_svc.c b/plat/marvell/common/mrvl_sip_svc.c
index 8bc633b..bc4b621 100644
--- a/plat/marvell/common/mrvl_sip_svc.c
+++ b/plat/marvell/common/mrvl_sip_svc.c
@@ -87,7 +87,7 @@
 		SMC_RET1(handle, ret);
 	case MV_SIP_COMPHY_POWER_OFF:
 		/* x1:  comphy_base, x2: comphy_index */
-		ret = mvebu_cp110_comphy_power_off(x1, x2);
+		ret = mvebu_cp110_comphy_power_off(x1, x2, x3);
 		SMC_RET1(handle, ret);
 	case MV_SIP_COMPHY_PLL_LOCK:
 		/* x1:  comphy_base, x2: comphy_index */
diff --git a/plat/marvell/version.mk b/plat/marvell/version.mk
index 16b0a16..e072e12 100644
--- a/plat/marvell/version.mk
+++ b/plat/marvell/version.mk
@@ -1 +1 @@
-SUBVERSION = devel-18.09.1
+SUBVERSION = devel-18.12.0