diff --git a/plat/juno/plat_pm.c b/plat/juno/plat_pm.c index 27a12278d39513f428c0de006ad6575af644ef03..74ce89fdfe5bbd41ad6d78ef49a7a41f4636eb92 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> @@ -238,6 +239,41 @@ static int32_t juno_affinst_suspend_finish(uint64_t mpidr, return juno_affinst_on_finish(mpidr, afflvl, state); } +/******************************************************************************* + * 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 ******************************************************************************/ @@ -246,7 +282,9 @@ static const plat_pm_ops_t juno_ops = { .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 c1677aae31d748dd6928a4f16c01ca3861caa31a..950c00bb7c9823decb4c5fb9b209b2a155c1acad 100644 --- a/plat/juno/scpi.c +++ b/plat/juno/scpi.c @@ -124,3 +124,17 @@ void scpi_set_css_power_state(unsigned mpidr, scpi_power_state_t cpu_state, 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 11129805bd6ba1c1a64289353e47237b6cd65eeb..8a5ef65496959eb929d2bd9a0cac74c1c3718590 100644 --- a/plat/juno/scpi.h +++ b/plat/juno/scpi.h @@ -59,6 +59,7 @@ typedef uint32_t scpi_status_t; 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 @@ typedef enum { 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__ */