meson: gxl: Fix reset and power off

Before CPU enters standby state (wfi), the AP needs to signal the SCP
through PSCI mailbox.

Also at boot time the AP has to wait for the SCP to be ready before
sending the first scpi commands or it can crash.

Change-Id: Iacc99f5bec745ad71922c5ea07ca5b87088133b6
Signed-off-by: Remi Pommarel <repk@triplefau.lt>
diff --git a/plat/meson/gxl/gxl_bl31_setup.c b/plat/meson/gxl/gxl_bl31_setup.c
index f8ce660..b1da794 100644
--- a/plat/meson/gxl/gxl_bl31_setup.c
+++ b/plat/meson/gxl/gxl_bl31_setup.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -10,6 +10,7 @@
 #include <common/interrupt_props.h>
 #include <plat/common/platform.h>
 #include <platform_def.h>
+#include <lib/mmio.h>
 #include <lib/xlat_tables/xlat_mmu_helpers.h>
 
 #include "gxl_private.h"
@@ -100,12 +101,19 @@
 	enable_mmu_el3(0);
 }
 
+static inline bool gxl_scp_ready(void)
+{
+	return GXBB_AO_RTI_SCP_IS_READY(mmio_read_32(GXBB_AO_RTI_SCP_STAT));
+}
+
 static inline void gxl_scp_boot(void)
 {
 	scpi_upload_scp_fw(bl30_image_info.image_base,
 			bl30_image_info.image_size, 0);
 	scpi_upload_scp_fw(bl301_image_info.image_base,
 			bl301_image_info.image_size, 1);
+	while (!gxl_scp_ready())
+		;
 }
 
 /*******************************************************************************
diff --git a/plat/meson/gxl/gxl_def.h b/plat/meson/gxl/gxl_def.h
index ada2656..089fa8d 100644
--- a/plat/meson/gxl/gxl_def.h
+++ b/plat/meson/gxl/gxl_def.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -91,6 +91,12 @@
 #define GXBB_SYS_CPU_CFG7			UL(0xC8834664)
 
 #define GXBB_AO_RTI_STATUS_REG3			UL(0xDA10001C)
+#define GXBB_AO_RTI_SCP_STAT			UL(0xDA10023C)
+#define GXBB_AO_RTI_SCP_READY_OFF		U(0x14)
+#define GXBB_A0_RTI_SCP_READY_MASK		U(3)
+#define GXBB_AO_RTI_SCP_IS_READY(v)		\
+	((((v) >> GXBB_AO_RTI_SCP_READY_OFF) & \
+	  GXBB_A0_RTI_SCP_READY_MASK) == GXBB_A0_RTI_SCP_READY_MASK)
 
 #define GXBB_HIU_MAILBOX_SET_0			UL(0xDA83C404)
 #define GXBB_HIU_MAILBOX_STAT_0			UL(0xDA83C408)
diff --git a/plat/meson/gxl/gxl_pm.c b/plat/meson/gxl/gxl_pm.c
index d9b69ef..5136c89 100644
--- a/plat/meson/gxl/gxl_pm.c
+++ b/plat/meson/gxl/gxl_pm.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -27,20 +27,29 @@
 static uintptr_t gxbb_sec_entrypoint;
 static volatile uint32_t gxbb_cpu0_go;
 
-static void gxbb_program_mailbox(u_register_t mpidr, uint64_t value)
+static void gxl_pm_set_reset_addr(u_register_t mpidr, uint64_t value)
 {
 	unsigned int core = plat_gxbb_calc_core_pos(mpidr);
 	uintptr_t cpu_mailbox_addr = GXBB_PSCI_MAILBOX_BASE + (core << 4);
 
 	mmio_write_64(cpu_mailbox_addr, value);
-	flush_dcache_range(cpu_mailbox_addr, sizeof(uint64_t));
+}
+
+static void gxl_pm_reset(u_register_t mpidr)
+{
+	unsigned int core = plat_gxbb_calc_core_pos(mpidr);
+	uintptr_t cpu_mailbox_addr = GXBB_PSCI_MAILBOX_BASE + (core << 4) + 8;
+
+	mmio_write_32(cpu_mailbox_addr, 0);
 }
 
 static void __dead2 gxbb_system_reset(void)
 {
 	INFO("BL31: PSCI_SYSTEM_RESET\n");
 
+	u_register_t mpidr = read_mpidr_el1();
 	uint32_t status = mmio_read_32(GXBB_AO_RTI_STATUS_REG3);
+	int ret;
 
 	NOTICE("BL31: Reboot reason: 0x%x\n", status);
 
@@ -50,13 +59,15 @@
 
 	mmio_write_32(GXBB_AO_RTI_STATUS_REG3, status);
 
-	int ret = scpi_sys_power_state(SCPI_SYSTEM_REBOOT);
+	ret = scpi_sys_power_state(SCPI_SYSTEM_REBOOT);
 
 	if (ret != 0) {
-		ERROR("BL31: PSCI_SYSTEM_RESET: SCP error: %u\n", ret);
+		ERROR("BL31: PSCI_SYSTEM_RESET: SCP error: %i\n", ret);
 		panic();
 	}
 
+	gxl_pm_reset(mpidr);
+
 	wfi();
 
 	ERROR("BL31: PSCI_SYSTEM_RESET: Operation not handled\n");
@@ -67,14 +78,18 @@
 {
 	INFO("BL31: PSCI_SYSTEM_OFF\n");
 
-	unsigned int ret = scpi_sys_power_state(SCPI_SYSTEM_SHUTDOWN);
+	u_register_t mpidr = read_mpidr_el1();
+	int ret;
+
+	ret = scpi_sys_power_state(SCPI_SYSTEM_SHUTDOWN);
 
 	if (ret != 0) {
-		ERROR("BL31: PSCI_SYSTEM_OFF: SCP error %u\n", ret);
+		ERROR("BL31: PSCI_SYSTEM_OFF: SCP error %i\n", ret);
 		panic();
 	}
 
-	gxbb_program_mailbox(read_mpidr_el1(), 0);
+	gxl_pm_set_reset_addr(mpidr, 0);
+	gxl_pm_reset(mpidr);
 
 	wfi();
 
@@ -101,7 +116,7 @@
 		return PSCI_E_SUCCESS;
 	}
 
-	gxbb_program_mailbox(mpidr, gxbb_sec_entrypoint);
+	gxl_pm_set_reset_addr(mpidr, gxbb_sec_entrypoint);
 	scpi_set_css_power_state(mpidr,
 				 SCPI_POWER_ON, SCPI_POWER_ON, SCPI_POWER_ON);
 	dmbsy();
@@ -133,10 +148,6 @@
 {
 	u_register_t mpidr = read_mpidr_el1();
 	unsigned int core = plat_gxbb_calc_core_pos(mpidr);
-	uintptr_t addr = GXBB_PSCI_MAILBOX_BASE + 8 + (core << 4);
-
-	mmio_write_32(addr, 0xFFFFFFFF);
-	flush_dcache_range(addr, sizeof(uint32_t));
 
 	gicv2_cpuif_disable();