-/* $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 <jsg@openbsd.org>
#define SMCCC_ARCH_WORKAROUND_1 0x80008000
#define PSCI_VERSION 0x84000000
+#define CPU_OFF 0x84000002
#ifdef __LP64__
#define CPU_ON 0xc4000003
#else
#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;
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;
};
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;
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");
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)
return PSCI_NOT_SUPPORTED;
}
+
+int
+psci_can_suspend(void)
+{
+ struct psci_softc *sc = psci_sc;
+
+ return (sc && sc->sc_system_suspend != 0);
+}
#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_ */