@@ -561,6 +561,14 @@ END(efi_xen_start)
#endif /* CONFIG_ARM_EFI */
+#ifdef CONFIG_SYSTEM_SUSPEND
+
+FUNC(hyp_resume)
+ b .
+END(hyp_resume)
+
+#endif /* CONFIG_SYSTEM_SUSPEND */
+
/*
* Local variables:
* mode: ASM
@@ -20,6 +20,7 @@ extern uint32_t psci_ver;
int psci_init(void);
int call_psci_cpu_on(int cpu);
+int call_psci_system_suspend(void);
void call_psci_cpu_off(void);
void call_psci_system_off(void);
void call_psci_system_reset(void);
@@ -4,6 +4,7 @@
#define __ASM_ARM_SUSPEND_H__
int32_t domain_suspend(register_t epoint, register_t cid);
+void hyp_resume(void);
#endif
@@ -17,6 +17,7 @@
#include <asm/cpufeature.h>
#include <asm/psci.h>
#include <asm/acpi.h>
+#include <asm/suspend.h>
/*
* While a 64-bit OS can make calls with SMC32 calling conventions, for
@@ -60,6 +61,24 @@ void call_psci_cpu_off(void)
}
}
+int call_psci_system_suspend(void)
+{
+#ifdef CONFIG_SYSTEM_SUSPEND
+ struct arm_smccc_res res;
+
+ if ( psci_ver < PSCI_VERSION(1, 0) )
+ return PSCI_NOT_SUPPORTED;
+
+ /* 2nd argument (context ID) is not used */
+ arm_smccc_smc(PSCI_1_0_FN64_SYSTEM_SUSPEND, __pa(hyp_resume), &res);
+
+ return PSCI_RET(res);
+#else
+ /* not supported */
+ return PSCI_NOT_SUPPORTED;
+#endif
+}
+
void call_psci_system_off(void)
{
if ( psci_ver > PSCI_VERSION(0, 1) )
@@ -170,6 +170,10 @@ static long system_suspend(void *data)
*/
update_boot_mapping(true);
+ status = call_psci_system_suspend();
+ if ( status )
+ dprintk(XENLOG_ERR, "PSCI system suspend failed, err=%d\n", status);
+
system_state = SYS_STATE_resume;
update_boot_mapping(false);