allwinner: psci: Improve system shutdown/reset sequence
- When the SCPI shutdown/reset command returns success, the SCP is
still waiting for the CPU to enter WFI. Do that.
- Peform board-level poweroff before CPU poweroff. If there is a PMIC
available, it will turn everything off including the CPUs, so doing
CPU poweroff first is a waste of cycles.
- During poweroff, attempt to turn off the local CPU using the ARISC.
This should use slightly less power than just an infinite WFI.
- Drop the WFI in the reset failure path. The panic will hang anyway.
Change-Id: I897efecb3fe4e77a56041b97dd273156ec51ef8e
Signed-off-by: Samuel Holland <samuel@sholland.org>
diff --git a/plat/allwinner/common/sunxi_pm.c b/plat/allwinner/common/sunxi_pm.c
index e6e9133..4e1a028 100644
--- a/plat/allwinner/common/sunxi_pm.c
+++ b/plat/allwinner/common/sunxi_pm.c
@@ -125,19 +125,20 @@
/* 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);
- }
+ if (ret == SCP_OK) {
+ wfi();
+ }
- /* Turn off all secondary CPUs */
- sunxi_cpu_power_off_others();
+ ERROR("PSCI: SCPI %s failed: %d\n", "shutdown", ret);
+ }
+ /* Attempt to power down the board (may not return) */
sunxi_power_down();
- udelay(1000);
- ERROR("PSCI: Cannot turn off system, halting\n");
- wfi();
- panic();
+ /* Turn off all CPUs */
+ sunxi_cpu_power_off_others();
+ sunxi_cpu_power_off_self();
+ psci_power_down_wfi();
}
static void __dead2 sunxi_system_reset(void)
@@ -148,8 +149,11 @@
/* 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);
+ if (ret == SCP_OK) {
+ wfi();
+ }
+
+ ERROR("PSCI: SCPI %s failed: %d\n", "reboot", ret);
}
/* Reset the whole system when the watchdog times out */
@@ -160,7 +164,6 @@
mdelay(1000);
ERROR("PSCI: System reset failed\n");
- wfi();
panic();
}