Merge "amlogic/axg: Add documentation page to the index" into integration
diff --git a/Makefile b/Makefile
index 39e8a00..03f9fc6 100644
--- a/Makefile
+++ b/Makefile
@@ -779,6 +779,7 @@
 $(eval $(call assert_boolean,GICV2_G0_FOR_EL3))
 $(eval $(call assert_boolean,HANDLE_EA_EL3_FIRST))
 $(eval $(call assert_boolean,HW_ASSISTED_COHERENCY))
+$(eval $(call assert_boolean,INVERTED_MEMMAP))
 $(eval $(call assert_boolean,MEASURED_BOOT))
 $(eval $(call assert_boolean,NS_TIMER_SWITCH))
 $(eval $(call assert_boolean,OVERRIDE_LIBC))
@@ -1120,7 +1121,7 @@
 
 # Call print_memory_map tool
 memmap: all
-	${Q}${PYTHON} $(PRINT_MEMORY_MAP) $(BUILD_PLAT)
+	${Q}${PYTHON} ${PRINT_MEMORY_MAP} ${BUILD_PLAT} ${INVERTED_MEMMAP}
 
 doc:
 	@echo "  BUILD DOCUMENTATION"
diff --git a/docs/getting_started/build-options.rst b/docs/getting_started/build-options.rst
index 7ee34c9..da5dcbf 100644
--- a/docs/getting_started/build-options.rst
+++ b/docs/getting_started/build-options.rst
@@ -340,6 +340,11 @@
    translation library (xlat tables v2) must be used; version 1 of translation
    library is not supported.
 
+-  ``INVERTED_MEMMAP``: memmap tool print by default lower addresses at the
+   bottom, higher addresses at the top. This buid flag can be set to '1' to
+   invert this behavior. Lower addresses will be printed at the top and higher
+   addresses at the bottom.
+
 -  ``JUNO_AARCH32_EL3_RUNTIME``: This build flag enables you to execute EL3
    runtime software in AArch32 mode, which is required to run AArch32 on Juno.
    By default this flag is set to '0'. Enabling this flag builds BL1 and BL2 in
diff --git a/drivers/allwinner/sunxi_msgbox.c b/drivers/allwinner/sunxi_msgbox.c
new file mode 100644
index 0000000..cc4a6ff
--- /dev/null
+++ b/drivers/allwinner/sunxi_msgbox.c
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <stdbool.h>
+
+#include <drivers/delay_timer.h>
+#include <lib/bakery_lock.h>
+#include <lib/mmio.h>
+#include <lib/utils_def.h>
+
+#include <sunxi_mmap.h>
+
+#define REMOTE_IRQ_EN_REG	0x0040
+#define REMOTE_IRQ_STAT_REG	0x0050
+#define LOCAL_IRQ_EN_REG	0x0060
+#define LOCAL_IRQ_STAT_REG	0x0070
+
+#define RX_IRQ(n)		BIT(0 + 2 * (n))
+#define TX_IRQ(n)		BIT(1 + 2 * (n))
+
+#define FIFO_STAT_REG(n)	(0x0100 + 0x4 * (n))
+#define FIFO_STAT_MASK		GENMASK(0, 0)
+
+#define MSG_STAT_REG(n)		(0x0140 + 0x4 * (n))
+#define MSG_STAT_MASK		GENMASK(2, 0)
+
+#define MSG_DATA_REG(n)		(0x0180 + 0x4 * (n))
+
+#define RX_CHAN			1
+#define TX_CHAN			0
+
+#define MHU_MAX_SLOT_ID		31
+
+#define MHU_TIMEOUT_DELAY	10
+#define MHU_TIMEOUT_ITERS	10000
+
+static DEFINE_BAKERY_LOCK(mhu_secure_message_lock);
+
+static bool sunxi_msgbox_last_tx_done(unsigned int chan)
+{
+	uint32_t stat = mmio_read_32(SUNXI_MSGBOX_BASE + REMOTE_IRQ_STAT_REG);
+
+	return (stat & RX_IRQ(chan)) == 0U;
+}
+
+static bool sunxi_msgbox_peek_data(unsigned int chan)
+{
+	uint32_t stat = mmio_read_32(SUNXI_MSGBOX_BASE + MSG_STAT_REG(chan));
+
+	return (stat & MSG_STAT_MASK) != 0U;
+}
+
+void mhu_secure_message_start(unsigned int slot_id __unused)
+{
+	uint32_t timeout = MHU_TIMEOUT_ITERS;
+
+	bakery_lock_get(&mhu_secure_message_lock);
+
+	/* Wait for all previous messages to be acknowledged. */
+	while (!sunxi_msgbox_last_tx_done(TX_CHAN) && --timeout)
+		udelay(MHU_TIMEOUT_DELAY);
+}
+
+void mhu_secure_message_send(unsigned int slot_id)
+{
+	mmio_write_32(SUNXI_MSGBOX_BASE + MSG_DATA_REG(TX_CHAN), BIT(slot_id));
+}
+
+uint32_t mhu_secure_message_wait(void)
+{
+	uint32_t timeout = MHU_TIMEOUT_ITERS;
+	uint32_t msg = 0;
+
+	/* Wait for a message from the SCP. */
+	while (!sunxi_msgbox_peek_data(RX_CHAN) && --timeout)
+		udelay(MHU_TIMEOUT_DELAY);
+
+	/* Return the most recent message in the FIFO. */
+	while (sunxi_msgbox_peek_data(RX_CHAN))
+		msg = mmio_read_32(SUNXI_MSGBOX_BASE + MSG_DATA_REG(RX_CHAN));
+
+	return msg;
+}
+
+void mhu_secure_message_end(unsigned int slot_id)
+{
+	/* Acknowledge a response by clearing the IRQ status. */
+	mmio_write_32(SUNXI_MSGBOX_BASE + LOCAL_IRQ_STAT_REG, RX_IRQ(RX_CHAN));
+
+	bakery_lock_release(&mhu_secure_message_lock);
+}
diff --git a/plat/allwinner/common/allwinner-common.mk b/plat/allwinner/common/allwinner-common.mk
index 98bcf3e..e60ebc6 100644
--- a/plat/allwinner/common/allwinner-common.mk
+++ b/plat/allwinner/common/allwinner-common.mk
@@ -20,6 +20,8 @@
 				${AW_PLAT}/common/sunxi_common.c
 
 BL31_SOURCES		+=	drivers/allwinner/axp/common.c		\
+				drivers/allwinner/sunxi_msgbox.c	\
+				drivers/arm/css/scpi/css_scpi.c		\
 				drivers/arm/gic/common/gic_common.c	\
 				drivers/arm/gic/v2/gicv2_helpers.c	\
 				drivers/arm/gic/v2/gicv2_main.c		\
diff --git a/plat/allwinner/common/include/platform_def.h b/plat/allwinner/common/include/platform_def.h
index 6f22744..975cc48 100644
--- a/plat/allwinner/common/include/platform_def.h
+++ b/plat/allwinner/common/include/platform_def.h
@@ -14,7 +14,12 @@
 #include <sunxi_mmap.h>
 
 #define BL31_BASE			(SUNXI_SRAM_A2_BASE + 0x4000)
-#define BL31_LIMIT			(SUNXI_SRAM_A2_BASE + SUNXI_SRAM_A2_SIZE)
+#define BL31_LIMIT			(SUNXI_SRAM_A2_BASE + \
+					 SUNXI_SRAM_A2_SIZE - SUNXI_SCP_SIZE)
+
+/* The SCP firmware is allocated the last 16KiB of SRAM A2. */
+#define SUNXI_SCP_BASE			BL31_LIMIT
+#define SUNXI_SCP_SIZE			0x4000
 
 /* Overwrite U-Boot SPL, but reserve the first page for the SPL header. */
 #define BL31_NOBITS_BASE		(SUNXI_SRAM_A1_BASE + 0x1000)
@@ -35,6 +40,9 @@
 #define MAX_MMAP_REGIONS		(3 + PLATFORM_MMAP_REGIONS)
 #define MAX_XLAT_TABLES			1
 
+#define PLAT_CSS_SCP_COM_SHARED_MEM_BASE \
+	(SUNXI_SRAM_A2_BASE + SUNXI_SRAM_A2_SIZE - 0x200)
+
 #define PLAT_MAX_PWR_LVL_STATES		U(2)
 #define PLAT_MAX_RET_STATE		U(1)
 #define PLAT_MAX_OFF_STATE		U(2)
@@ -51,7 +59,7 @@
 #define PLATFORM_CORE_COUNT		(PLATFORM_CLUSTER_COUNT * \
 					 PLATFORM_MAX_CPUS_PER_CLUSTER)
 #define PLATFORM_MAX_CPUS_PER_CLUSTER	U(4)
-#define PLATFORM_MMAP_REGIONS		4
+#define PLATFORM_MMAP_REGIONS		5
 #define PLATFORM_STACK_SIZE		(0x1000 / PLATFORM_CORE_COUNT)
 
 #ifndef SPD_none
diff --git a/plat/allwinner/common/sunxi_common.c b/plat/allwinner/common/sunxi_common.c
index 45e4154..0ca18ad 100644
--- a/plat/allwinner/common/sunxi_common.c
+++ b/plat/allwinner/common/sunxi_common.c
@@ -21,6 +21,8 @@
 static const mmap_region_t sunxi_mmap[PLATFORM_MMAP_REGIONS + 1] = {
 	MAP_REGION_FLAT(SUNXI_SRAM_BASE, SUNXI_SRAM_SIZE,
 			MT_RW_DATA | MT_SECURE),
+	MAP_REGION_FLAT(SUNXI_SCP_BASE, SUNXI_SCP_SIZE,
+			MT_DEVICE | MT_RW | MT_SECURE | MT_EXECUTE_NEVER),
 	MAP_REGION_FLAT(SUNXI_DEV_BASE, SUNXI_DEV_SIZE,
 			MT_DEVICE | MT_RW | MT_SECURE | MT_EXECUTE_NEVER),
 	MAP_REGION(SUNXI_DRAM_BASE, SUNXI_DRAM_VIRT_BASE, SUNXI_DRAM_SEC_SIZE,
diff --git a/plat/allwinner/common/sunxi_pm.c b/plat/allwinner/common/sunxi_pm.c
index 9b074d2..e0fa5b3 100644
--- a/plat/allwinner/common/sunxi_pm.c
+++ b/plat/allwinner/common/sunxi_pm.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -10,6 +10,7 @@
 
 #include <arch_helpers.h>
 #include <common/debug.h>
+#include <drivers/arm/css/css_scpi.h>
 #include <drivers/arm/gicv2.h>
 #include <drivers/delay_timer.h>
 #include <lib/mmio.h>
@@ -17,6 +18,7 @@
 #include <plat/common/platform.h>
 
 #include <sunxi_cpucfg.h>
+#include <sunxi_def.h>
 #include <sunxi_mmap.h>
 #include <sunxi_private.h>
 
@@ -24,25 +26,88 @@
 #define SUNXI_WDOG0_CFG_REG		(SUNXI_R_WDOG_BASE + 0x0014)
 #define SUNXI_WDOG0_MODE_REG		(SUNXI_R_WDOG_BASE + 0x0018)
 
-#define mpidr_is_valid(mpidr) ( \
-	MPIDR_AFFLVL3_VAL(mpidr) == 0 && \
-	MPIDR_AFFLVL2_VAL(mpidr) == 0 && \
-	MPIDR_AFFLVL1_VAL(mpidr) < PLATFORM_CLUSTER_COUNT && \
-	MPIDR_AFFLVL0_VAL(mpidr) < PLATFORM_MAX_CPUS_PER_CLUSTER)
+#define CPU_PWR_LVL			MPIDR_AFFLVL0
+#define CLUSTER_PWR_LVL			MPIDR_AFFLVL1
+#define SYSTEM_PWR_LVL			MPIDR_AFFLVL2
+
+#define CPU_PWR_STATE(state) \
+	((state)->pwr_domain_state[CPU_PWR_LVL])
+#define CLUSTER_PWR_STATE(state) \
+	((state)->pwr_domain_state[CLUSTER_PWR_LVL])
+#define SYSTEM_PWR_STATE(state) \
+	((state)->pwr_domain_state[SYSTEM_PWR_LVL])
+
+#define mpidr_is_valid(mpidr) (plat_core_pos_by_mpidr(mpidr) >= 0)
+
+/*
+ * The addresses for the SCP exception vectors are defined in the or1k
+ * architecture specification.
+ */
+#define OR1K_VEC_FIRST			0x01
+#define OR1K_VEC_LAST			0x0e
+#define OR1K_VEC_ADDR(n)		(0x100 * (n))
+
+/*
+ * This magic value is the little-endian representation of the or1k
+ * instruction "l.mfspr r2, r0, 0x12", which is guaranteed to be the
+ * first instruction in the SCP firmware.
+ */
+#define SCP_FIRMWARE_MAGIC		0xb4400012
+
+static bool scpi_available;
+
+static inline scpi_power_state_t scpi_map_state(plat_local_state_t psci_state)
+{
+	if (is_local_state_run(psci_state))
+		return scpi_power_on;
+	if (is_local_state_retn(psci_state))
+		return scpi_power_retention;
+	return scpi_power_off;
+}
+
+static void sunxi_cpu_standby(plat_local_state_t cpu_state)
+{
+	u_register_t scr = read_scr_el3();
+
+	assert(is_local_state_retn(cpu_state));
+
+	write_scr_el3(scr | SCR_IRQ_BIT);
+	wfi();
+	write_scr_el3(scr);
+}
 
 static int sunxi_pwr_domain_on(u_register_t mpidr)
 {
 	if (mpidr_is_valid(mpidr) == 0)
 		return PSCI_E_INTERN_FAIL;
 
-	sunxi_cpu_on(mpidr);
+	if (scpi_available) {
+		scpi_set_css_power_state(mpidr,
+					 scpi_power_on,
+					 scpi_power_on,
+					 scpi_power_on);
+	} else {
+		sunxi_cpu_on(mpidr);
+	}
 
 	return PSCI_E_SUCCESS;
 }
 
 static void sunxi_pwr_domain_off(const psci_power_state_t *target_state)
 {
-	gicv2_cpuif_disable();
+	plat_local_state_t cpu_pwr_state     = CPU_PWR_STATE(target_state);
+	plat_local_state_t cluster_pwr_state = CLUSTER_PWR_STATE(target_state);
+	plat_local_state_t system_pwr_state  = SYSTEM_PWR_STATE(target_state);
+
+	if (is_local_state_off(cpu_pwr_state))
+		gicv2_cpuif_disable();
+
+	if (scpi_available) {
+		scpi_set_css_power_state(read_mpidr(),
+					 scpi_map_state(cpu_pwr_state),
+					 scpi_map_state(cluster_pwr_state),
+					 scpi_map_state(system_pwr_state));
+	}
 }
 
 static void __dead2 sunxi_pwr_down_wfi(const psci_power_state_t *target_state)
@@ -55,12 +120,26 @@
 
 static void sunxi_pwr_domain_on_finish(const psci_power_state_t *target_state)
 {
-	gicv2_pcpu_distif_init();
-	gicv2_cpuif_enable();
+	if (is_local_state_off(SYSTEM_PWR_STATE(target_state)))
+		gicv2_distif_init();
+	if (is_local_state_off(CPU_PWR_STATE(target_state))) {
+		gicv2_pcpu_distif_init();
+		gicv2_cpuif_enable();
+	}
 }
 
 static void __dead2 sunxi_system_off(void)
 {
+	gicv2_cpuif_disable();
+
+	if (scpi_available) {
+		/* Send the power down request to the SCP */
+		uint32_t ret = scpi_sys_power_state(scpi_system_shutdown);
+
+		if (ret != SCP_OK)
+			ERROR("PSCI: SCPI %s failed: %d\n", "shutdown", ret);
+	}
+
 	/* Turn off all secondary CPUs */
 	sunxi_disable_secondary_cpus(read_mpidr());
 
@@ -74,6 +153,16 @@
 
 static void __dead2 sunxi_system_reset(void)
 {
+	gicv2_cpuif_disable();
+
+	if (scpi_available) {
+		/* Send the system reset request to the SCP */
+		uint32_t ret = scpi_sys_power_state(scpi_system_reboot);
+
+		if (ret != SCP_OK)
+			ERROR("PSCI: SCPI %s failed: %d\n", "reboot", ret);
+	}
+
 	/* Reset the whole system when the watchdog times out */
 	mmio_write_32(SUNXI_WDOG0_CFG_REG, 1);
 	/* Enable the watchdog with the shortest timeout (0.5 seconds) */
@@ -86,6 +175,40 @@
 	panic();
 }
 
+static int sunxi_validate_power_state(unsigned int power_state,
+				      psci_power_state_t *req_state)
+{
+	unsigned int power_level = psci_get_pstate_pwrlvl(power_state);
+	unsigned int type = psci_get_pstate_type(power_state);
+
+	assert(req_state != NULL);
+
+	if (power_level > PLAT_MAX_PWR_LVL)
+		return PSCI_E_INVALID_PARAMS;
+
+	if (type == PSTATE_TYPE_STANDBY) {
+		/* Only one retention power state is supported. */
+		if (psci_get_pstate_id(power_state) > 0)
+			return PSCI_E_INVALID_PARAMS;
+		/* The SoC cannot be suspended without losing state */
+		if (power_level == SYSTEM_PWR_LVL)
+			return PSCI_E_INVALID_PARAMS;
+		for (unsigned int i = 0; i <= power_level; ++i)
+			req_state->pwr_domain_state[i] = PLAT_MAX_RET_STATE;
+	} else {
+		/* Only one off power state is supported. */
+		if (psci_get_pstate_id(power_state) > 0)
+			return PSCI_E_INVALID_PARAMS;
+		for (unsigned int i = 0; i <= power_level; ++i)
+			req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE;
+	}
+	/* Higher power domain levels should all remain running */
+	for (unsigned int i = power_level + 1; i <= PLAT_MAX_PWR_LVL; ++i)
+		req_state->pwr_domain_state[i] = PSCI_LOCAL_STATE_RUN;
+
+	return PSCI_E_SUCCESS;
+}
+
 static int sunxi_validate_ns_entrypoint(uintptr_t ns_entrypoint)
 {
 	/* The non-secure entry point must be in DRAM */
@@ -95,13 +218,45 @@
 	return PSCI_E_INVALID_ADDRESS;
 }
 
+static void sunxi_get_sys_suspend_power_state(psci_power_state_t *req_state)
+{
+	assert(req_state);
+
+	for (unsigned int i = 0; i <= PLAT_MAX_PWR_LVL; ++i)
+		req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE;
+}
+
+static int sunxi_get_node_hw_state(u_register_t mpidr,
+				   unsigned int power_level)
+{
+	unsigned int cluster_state, cpu_state;
+	unsigned int cpu = MPIDR_AFFLVL0_VAL(mpidr);
+
+	/* SoC power level (always on if PSCI works). */
+	if (power_level == SYSTEM_PWR_LVL)
+		return HW_ON;
+	if (scpi_get_css_power_state(mpidr, &cpu_state, &cluster_state))
+		return PSCI_E_NOT_SUPPORTED;
+	/* Cluster power level (full power state available). */
+	if (power_level == CLUSTER_PWR_LVL) {
+		if (cluster_state == scpi_power_on)
+			return HW_ON;
+		if (cluster_state == scpi_power_retention)
+			return HW_STANDBY;
+		return HW_OFF;
+	}
+	/* CPU power level (one bit boolean for on or off). */
+	return ((cpu_state & BIT(cpu)) != 0) ? HW_ON : HW_OFF;
+}
+
 static plat_psci_ops_t sunxi_psci_ops = {
+	.cpu_standby			= sunxi_cpu_standby,
 	.pwr_domain_on			= sunxi_pwr_domain_on,
 	.pwr_domain_off			= sunxi_pwr_domain_off,
-	.pwr_domain_pwr_down_wfi	= sunxi_pwr_down_wfi,
 	.pwr_domain_on_finish		= sunxi_pwr_domain_on_finish,
 	.system_off			= sunxi_system_off,
 	.system_reset			= sunxi_system_reset,
+	.validate_power_state		= sunxi_validate_power_state,
 	.validate_ns_entrypoint		= sunxi_validate_ns_entrypoint,
 };
 
@@ -110,13 +265,44 @@
 {
 	assert(psci_ops);
 
-	for (int cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu += 1) {
+	/* Program all CPU entry points. */
+	for (unsigned int cpu = 0; cpu < PLATFORM_CORE_COUNT; ++cpu) {
 		mmio_write_32(SUNXI_CPUCFG_RVBAR_LO_REG(cpu),
 			      sec_entrypoint & 0xffffffff);
 		mmio_write_32(SUNXI_CPUCFG_RVBAR_HI_REG(cpu),
 			      sec_entrypoint >> 32);
 	}
 
+	/* Check for a valid SCP firmware, and boot the SCP if found. */
+	if (mmio_read_32(SUNXI_SCP_BASE) == SCP_FIRMWARE_MAGIC) {
+		/* Program SCP exception vectors to the firmware entrypoint. */
+		for (unsigned int i = OR1K_VEC_FIRST; i <= OR1K_VEC_LAST; ++i) {
+			uint32_t vector = SUNXI_SRAM_A2_BASE + OR1K_VEC_ADDR(i);
+			uint32_t offset = SUNXI_SCP_BASE - vector;
+
+			mmio_write_32(vector, offset >> 2);
+			clean_dcache_range(vector, sizeof(uint32_t));
+		}
+		/* Take the SCP out of reset. */
+		mmio_setbits_32(SUNXI_R_CPUCFG_BASE, BIT(0));
+		/* Wait for the SCP firmware to boot. */
+		if (scpi_wait_ready() == 0)
+			scpi_available = true;
+	}
+
+	NOTICE("PSCI: System suspend is %s\n",
+	       scpi_available ? "available via SCPI" : "unavailable");
+	if (scpi_available) {
+		/* Suspend is only available via SCPI. */
+		sunxi_psci_ops.pwr_domain_suspend = sunxi_pwr_domain_off;
+		sunxi_psci_ops.pwr_domain_suspend_finish = sunxi_pwr_domain_on_finish;
+		sunxi_psci_ops.get_sys_suspend_power_state = sunxi_get_sys_suspend_power_state;
+		sunxi_psci_ops.get_node_hw_state = sunxi_get_node_hw_state;
+	} else {
+		/* This is only needed when SCPI is unavailable. */
+		sunxi_psci_ops.pwr_domain_pwr_down_wfi = sunxi_pwr_down_wfi;
+	}
+
 	*psci_ops = &sunxi_psci_ops;
 
 	return 0;
diff --git a/plat/arm/board/fvp/fvp_def.h b/plat/arm/board/fvp/fvp_def.h
index 347ba2e..909b687 100644
--- a/plat/arm/board/fvp/fvp_def.h
+++ b/plat/arm/board/fvp/fvp_def.h
@@ -52,8 +52,10 @@
 #define DEVICE1_BASE			UL(0x2e000000)
 #define DEVICE1_SIZE			UL(0x1A00000)
 #else
-#define DEVICE1_BASE			UL(0x2f000000)
-#define DEVICE1_SIZE			UL(0x200000)
+/* GICv2 and GICv3 mapping: GICD + CORE_COUNT * 128KB */
+#define DEVICE1_BASE			BASE_GICD_BASE
+#define DEVICE1_SIZE			((BASE_GICR_BASE - BASE_GICD_BASE) + \
+					 (PLATFORM_CORE_COUNT * 0x20000))
 #define NSRAM_BASE			UL(0x2e000000)
 #define NSRAM_SIZE			UL(0x10000)
 #endif
@@ -110,7 +112,7 @@
 #define FVP_SP810_CTRL_TIM3_OV		BIT_32(22)
 
 /*******************************************************************************
- * GIC-400 & interrupt handling related constants
+ * GIC & interrupt handling related constants
  ******************************************************************************/
 /* VE compatible GIC memory map */
 #define VE_GICD_BASE			UL(0x2c001000)
@@ -128,7 +130,6 @@
 #define FVP_IRQ_TZ_WDOG			56
 #define FVP_IRQ_SEC_SYS_TIMER		57
 
-
 /*******************************************************************************
  * TrustZone address space controller related constants
  ******************************************************************************/
diff --git a/plat/imx/imx8m/include/imx_rdc.h b/plat/imx/imx8m/include/imx_rdc.h
index 6be8550..e25b0e6 100644
--- a/plat/imx/imx8m/include/imx_rdc.h
+++ b/plat/imx/imx8m/include/imx_rdc.h
@@ -13,9 +13,9 @@
 
 #define MDAn(x)		(IMX_RDC_BASE + 0x200 + (x) * 4)
 #define PDAPn(x)	(IMX_RDC_BASE + 0x400 + (x) * 4)
-#define MRSAn(x)	(IMX_RDC_BASE + 0x800 + (x) * 4)
-#define MREAn(x)	(IMX_RDC_BASE + 0x804 + (x) * 4)
-#define MRCn(x)		(IMX_RDC_BASE + 0x808 + (x) * 4)
+#define MRSAn(x)	(IMX_RDC_BASE + 0x800 + (x) * 0x10)
+#define MREAn(x)	(IMX_RDC_BASE + 0x804 + (x) * 0x10)
+#define MRCn(x)		(IMX_RDC_BASE + 0x808 + (x) * 0x10)
 
 #define LCK		BIT(31)
 #define SREQ		BIT(30)
diff --git a/plat/socionext/uniphier/uniphier_soc_info.c b/plat/socionext/uniphier/uniphier_soc_info.c
index 377532d..0e7a2d1 100644
--- a/plat/socionext/uniphier/uniphier_soc_info.c
+++ b/plat/socionext/uniphier/uniphier_soc_info.c
@@ -4,18 +4,25 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
+#include <common/bl_common.h>
 #include <lib/mmio.h>
 
 #include "uniphier.h"
 
-#define UNIPHIER_REVISION		0x5f800000
+#define UNIPHIER_REVISION		0x5f800000UL
+#define UNIPHIER_REVISION_NEW		0x1f800000UL
 
 static unsigned int uniphier_get_revision_field(unsigned int mask,
 						unsigned int shift)
 {
-	uint32_t revision = mmio_read_32(UNIPHIER_REVISION);
+	uintptr_t reg;
+
+	if (BL_CODE_BASE >= 0x80000000UL)
+		reg = UNIPHIER_REVISION;
+	else
+		reg = UNIPHIER_REVISION_NEW;
 
-	return (revision >> shift) & mask;
+	return (mmio_read_32(reg) >> shift) & mask;
 }
 
 unsigned int uniphier_get_soc_type(void)
diff --git a/tools/memory/print_memory_map.py b/tools/memory/print_memory_map.py
index 35cccd3..8a84018 100755
--- a/tools/memory/print_memory_map.py
+++ b/tools/memory/print_memory_map.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python3
 #
-# Copyright (c) 2019, Arm Limited. All rights reserved.
+# Copyright (c) 2019-2020, Arm Limited. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -22,6 +22,7 @@
                 '__DATA_START__', '__DATA_END__',
                 '__STACKS_START__', '__STACKS_END__',
                 '__BSS_END',
+                '__COHERENT_RAM_START__', '__COHERENT_RAM_END__',
                ]
 
 # Regex to extract address from map file
@@ -31,8 +32,11 @@
 address_list = []
 
 # Get the directory from command line or use a default one
+inverted_print = True
 if len(sys.argv) >= 2:
     build_dir = sys.argv[1]
+    if len(sys.argv) >= 3:
+        inverted_print = sys.argv[2] == '0'
 else:
     build_dir = 'build/fvp/debug'
 
@@ -43,7 +47,10 @@
         with open (file_path, 'rt') as mapfile:
             for line in mapfile:
                 for symbol in blx_symbols:
-                    if line.find(symbol) > 0 and line.find("ASSERT") < 0:
+                    # Regex to find symbol definition
+                    line_pattern = re.compile(r"\b0x\w*\s*" + symbol + "\s= .")
+                    match = line_pattern.search(line)
+                    if match:
                         # Extract address from line
                         match = address_pattern.search(line)
                         if match:
@@ -52,17 +59,21 @@
 # Sort by address
 address_list.sort(key=operator.itemgetter(0))
 
+# Invert list for lower address at bottom
+if inverted_print:
+    address_list = reversed(address_list)
+
 # Generate memory view
-print('{:-^87}'.format('Memory Map from: ' + build_dir))
-for address in reversed(address_list):
+print('{:-^93}'.format('Memory Map from: ' + build_dir))
+for address in address_list:
     if "bl1" in address[2]:
-        print(address[0], '+{:-^20}+ |{:^20}| |{:^20}|'.format(address[1], '', ''))
+        print(address[0], '+{:-^22}+ |{:^22}| |{:^22}|'.format(address[1], '', ''))
     elif "bl2" in address[2]:
-        print(address[0], '|{:^20}| +{:-^20}+ |{:^20}|'.format('', address[1], ''))
+        print(address[0], '|{:^22}| +{:-^22}+ |{:^22}|'.format('', address[1], ''))
     elif "bl31" in address[2]:
-        print(address[0], '|{:^20}| |{:^20}| +{:-^20}+'.format('', '', address[1]))
+        print(address[0], '|{:^22}| |{:^22}| +{:-^22}+'.format('', '', address[1]))
     else:
-        print(address[0], '|{:^20}| |{:^20}| +{:-^20}+'.format('', '', address[1]))
+        print(address[0], '|{:^22}| |{:^22}| +{:-^22}+'.format('', '', address[1]))
 
-print('{:^20}{:_^20}   {:_^20}   {:_^20}'.format('', '', '', ''))
-print('{:^20}{:^20}   {:^20}   {:^20}'.format('address', 'bl1', 'bl2', 'bl31'))
+print('{:^20}{:_^22}   {:_^22}   {:_^22}'.format('', '', '', ''))
+print('{:^20}{:^22}   {:^22}   {:^22}'.format('address', 'bl1', 'bl2', 'bl31'))