From 149f7d9868cf1139311f13fbd3c064b18bc64734 Mon Sep 17 00:00:00 2001 From: kettenis Date: Sat, 9 Jul 2022 19:27:56 +0000 Subject: [PATCH] Add support for calling the CPU_OFF and SYSTEM_SUSPEND functions. Add a function to check whether SYSTEM_SUSPEND is supported by the PSCI firmware. ok patrick@ --- sys/dev/fdt/psci.c | 47 ++++++++++++++++++++++++++++++++++++++++++- sys/dev/fdt/pscivar.h | 6 +++++- 2 files changed, 51 insertions(+), 2 deletions(-) diff --git a/sys/dev/fdt/psci.c b/sys/dev/fdt/psci.c index df9b0df1655..a7ebb8d905a 100644 --- a/sys/dev/fdt/psci.c +++ b/sys/dev/fdt/psci.c @@ -1,4 +1,4 @@ -/* $OpenBSD: psci.c,v 1.10 2021/10/24 17:52:26 mpi Exp $ */ +/* $OpenBSD: psci.c,v 1.11 2022/07/09 19:27:56 kettenis Exp $ */ /* * Copyright (c) 2016 Jonathan Gray @@ -36,6 +36,7 @@ extern void (*powerdownfn)(void); #define SMCCC_ARCH_WORKAROUND_1 0x80008000 #define PSCI_VERSION 0x84000000 +#define CPU_OFF 0x84000002 #ifdef __LP64__ #define CPU_ON 0xc4000003 #else @@ -44,6 +45,11 @@ extern void (*powerdownfn)(void); #define SYSTEM_OFF 0x84000008 #define SYSTEM_RESET 0x84000009 #define PSCI_FEATURES 0x8400000a +#ifdef __LP64__ +#define SYSTEM_SUSPEND 0xc400000e +#else +#define SYSTEM_SUSPEND 0x8400000e +#endif struct psci_softc { struct device sc_dev; @@ -52,7 +58,9 @@ struct psci_softc { uint32_t sc_psci_version; uint32_t sc_system_off; uint32_t sc_system_reset; + uint32_t sc_system_suspend; uint32_t sc_cpu_on; + uint32_t sc_cpu_off; uint32_t sc_smccc_version; }; @@ -117,12 +125,14 @@ psci_attach(struct device *parent, struct device *self, void *aux) sc->sc_system_off = SYSTEM_OFF; sc->sc_system_reset = SYSTEM_RESET; sc->sc_cpu_on = CPU_ON; + sc->sc_cpu_off = CPU_OFF; } else if (OF_is_compatible(faa->fa_node, "arm,psci")) { sc->sc_system_off = OF_getpropint(faa->fa_node, "system_off", 0); sc->sc_system_reset = OF_getpropint(faa->fa_node, "system_reset", 0); sc->sc_cpu_on = OF_getpropint(faa->fa_node, "cpu_on", 0); + sc->sc_cpu_off = OF_getpropint(faa->fa_node, "cpu_off", 0); } psci_sc = sc; @@ -136,6 +146,10 @@ psci_attach(struct device *parent, struct device *self, void *aux) printf(", SMCCC %d.%d", sc->sc_smccc_version >> 16, sc->sc_smccc_version & 0xffff); } + if (psci_features(SYSTEM_SUSPEND) == PSCI_SUCCESS) { + sc->sc_system_suspend = SYSTEM_SUSPEND; + printf(", SYSTEM_SUSPEND"); + } } printf("\n"); @@ -240,6 +254,29 @@ psci_version(void) return 0; } +int32_t +psci_system_suspend(register_t entry_point_address, register_t context_id) +{ + struct psci_softc *sc = psci_sc; + + if (sc && sc->sc_callfn && sc->sc_system_suspend != 0) + return (*sc->sc_callfn)(sc->sc_system_suspend, + entry_point_address, context_id, 0); + + return PSCI_NOT_SUPPORTED; +} + +int32_t +psci_cpu_off(void) +{ + struct psci_softc *sc = psci_sc; + + if (sc && sc->sc_callfn && sc->sc_cpu_off != 0) + return (*sc->sc_callfn)(sc->sc_cpu_off, 0, 0, 0); + + return PSCI_NOT_SUPPORTED; +} + int32_t psci_cpu_on(register_t target_cpu, register_t entry_point_address, register_t context_id) @@ -263,3 +300,11 @@ psci_features(uint32_t psci_func_id) return PSCI_NOT_SUPPORTED; } + +int +psci_can_suspend(void) +{ + struct psci_softc *sc = psci_sc; + + return (sc && sc->sc_system_suspend != 0); +} diff --git a/sys/dev/fdt/pscivar.h b/sys/dev/fdt/pscivar.h index 717ca142e8e..54ff2b1fd88 100644 --- a/sys/dev/fdt/pscivar.h +++ b/sys/dev/fdt/pscivar.h @@ -6,7 +6,11 @@ #define PSCI_SUCCESS 0 #define PSCI_NOT_SUPPORTED -1 -int32_t psci_cpu_on(register_t, register_t, register_t); +int psci_can_suspend(void); + +int32_t psci_system_suspend(register_t, register_t); +int32_t psci_cpu_on(register_t, register_t, register_t); +int32_t psci_cpu_off(void); void psci_flush_bp(void); #endif /* _SYS_DEV_FDT_PSCIVAR_H_ */ -- 2.20.1