Juno: Implement PSCI SYSTEM_OFF and SYSTEM_RESET APIs
This patch adds the Juno platform specific handlers for PSCI
SYSTEM_OFF and SYSTEM_RESET operations.
Change-Id: Ie389adead533ec2314af44d721b4d0f306147c7d
diff --git a/plat/juno/plat_pm.c b/plat/juno/plat_pm.c
index 27a1227..74ce89f 100644
--- a/plat/juno/plat_pm.c
+++ b/plat/juno/plat_pm.c
@@ -30,6 +30,7 @@
#include <assert.h>
#include <arch_helpers.h>
+#include <debug.h>
#include <cci400.h>
#include <errno.h>
#include <platform.h>
@@ -239,6 +240,41 @@
}
/*******************************************************************************
+ * Juno handlers to shutdown/reboot the system
+ ******************************************************************************/
+static void __dead2 juno_system_off(void)
+{
+ uint32_t response;
+
+ /* Send the power down request to the SCP */
+ response = scpi_sys_power_state(scpi_system_shutdown);
+
+ if (response != SCP_OK) {
+ ERROR("Juno System Off: SCP error %u.\n", response);
+ panic();
+ }
+ wfi();
+ ERROR("Juno System Off: operation not handled.\n");
+ panic();
+}
+
+static void __dead2 juno_system_reset(void)
+{
+ uint32_t response;
+
+ /* Send the system reset request to the SCP */
+ response = scpi_sys_power_state(scpi_system_reboot);
+
+ if (response != SCP_OK) {
+ ERROR("Juno System Reset: SCP error %u.\n", response);
+ panic();
+ }
+ wfi();
+ ERROR("Juno System Reset: operation not handled.\n");
+ panic();
+}
+
+/*******************************************************************************
* Export the platform handlers to enable psci to invoke them
******************************************************************************/
static const plat_pm_ops_t juno_ops = {
@@ -246,7 +282,9 @@
.affinst_on_finish = juno_affinst_on_finish,
.affinst_off = juno_affinst_off,
.affinst_suspend = juno_affinst_suspend,
- .affinst_suspend_finish = juno_affinst_suspend_finish
+ .affinst_suspend_finish = juno_affinst_suspend_finish,
+ .system_off = juno_system_off,
+ .system_reset = juno_system_reset
};
/*******************************************************************************
diff --git a/plat/juno/scpi.c b/plat/juno/scpi.c
index c1677aa..950c00b 100644
--- a/plat/juno/scpi.c
+++ b/plat/juno/scpi.c
@@ -124,3 +124,17 @@
state |= css_state << 16;
scpi_secure_send32(SCPI_CMD_SET_CSS_POWER_STATE, state);
}
+
+uint32_t scpi_sys_power_state(scpi_system_state_t system_state)
+{
+ uint32_t *response;
+ size_t size;
+ uint8_t state = system_state & 0xff;
+
+ /* Send the command */
+ *(__typeof__(state) *)scpi_secure_message_start() = state;
+ scpi_secure_message_send(SCPI_CMD_SYS_POWER_STATE, sizeof(state));
+ scpi_secure_message_receive((void *)&response, &size);
+ scpi_secure_message_end();
+ return *response;
+}
diff --git a/plat/juno/scpi.h b/plat/juno/scpi.h
index 1112980..8a5ef65 100644
--- a/plat/juno/scpi.h
+++ b/plat/juno/scpi.h
@@ -59,6 +59,7 @@
typedef enum {
SCPI_CMD_SCP_READY = 0x01,
SCPI_CMD_SET_CSS_POWER_STATE = 0x04,
+ SCPI_CMD_SYS_POWER_STATE = 0x08
} scpi_command_t;
typedef enum {
@@ -67,8 +68,15 @@
scpi_power_off = 3,
} scpi_power_state_t;
+typedef enum {
+ scpi_system_shutdown = 0,
+ scpi_system_reboot = 1,
+ scpi_system_reset = 2
+} scpi_system_state_t;
+
extern int scpi_wait_ready(void);
extern void scpi_set_css_power_state(unsigned mpidr, scpi_power_state_t cpu_state,
scpi_power_state_t cluster_state, scpi_power_state_t css_state);
+uint32_t scpi_sys_power_state(scpi_system_state_t system_state);
#endif /* __SCPI_H__ */