summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Jones <ajones@ventanamicro.com>2023-02-27 13:31:02 +0300
committerAnup Patel <anup@brainfault.org>2023-02-27 17:13:52 +0300
commit73623a0acac7f62646757cdd5a03b325eba3e0c9 (patch)
tree3665667dbfecdfaf68789e8aaa8508b9e3d83255
parent8a40306371b7e5dbe20da946edd0ddd9693bfa85 (diff)
downloadopensbi-73623a0acac7f62646757cdd5a03b325eba3e0c9.tar.xz
lib: sbi: Add system suspend skeleton
Add the SUSP extension probe and ecall support, but for now the system suspend function is just a stub. Signed-off-by: Andrew Jones <ajones@ventanamicro.com> Reviewed-by: Anup Patel <anup@brainfault.org>
-rw-r--r--include/sbi/sbi_ecall_interface.h8
-rw-r--r--include/sbi/sbi_system.h26
-rw-r--r--lib/sbi/Kconfig4
-rw-r--r--lib/sbi/objects.mk3
-rw-r--r--lib/sbi/sbi_ecall_susp.c48
-rw-r--r--lib/sbi/sbi_init.c4
-rw-r--r--lib/sbi/sbi_system.c26
7 files changed, 119 insertions, 0 deletions
diff --git a/include/sbi/sbi_ecall_interface.h b/include/sbi/sbi_ecall_interface.h
index 9d6f474..4c378c3 100644
--- a/include/sbi/sbi_ecall_interface.h
+++ b/include/sbi/sbi_ecall_interface.h
@@ -30,6 +30,7 @@
#define SBI_EXT_SRST 0x53525354
#define SBI_EXT_PMU 0x504D55
#define SBI_EXT_DBCN 0x4442434E
+#define SBI_EXT_SUSP 0x53555350
/* SBI function IDs for BASE extension*/
#define SBI_EXT_BASE_GET_SPEC_VERSION 0x0
@@ -236,6 +237,13 @@ enum sbi_pmu_ctr_type {
#define SBI_EXT_DBCN_CONSOLE_READ 0x1
#define SBI_EXT_DBCN_CONSOLE_WRITE_BYTE 0x2
+/* SBI function IDs for SUSP extension */
+#define SBI_EXT_SUSP_SUSPEND 0x0
+
+#define SBI_SUSP_SLEEP_TYPE_SUSPEND 0x0
+#define SBI_SUSP_SLEEP_TYPE_LAST SBI_SUSP_SLEEP_TYPE_SUSPEND
+#define SBI_SUSP_PLATFORM_SLEEP_START 0x80000000
+
/* SBI base specification related macros */
#define SBI_SPEC_VERSION_MAJOR_OFFSET 24
#define SBI_SPEC_VERSION_MAJOR_MASK 0x7f
diff --git a/include/sbi/sbi_system.h b/include/sbi/sbi_system.h
index 84c2813..11d3d6f 100644
--- a/include/sbi/sbi_system.h
+++ b/include/sbi/sbi_system.h
@@ -43,4 +43,30 @@ bool sbi_system_reset_supported(u32 reset_type, u32 reset_reason);
void __noreturn sbi_system_reset(u32 reset_type, u32 reset_reason);
+/** System suspend device */
+struct sbi_system_suspend_device {
+ /** Name of the system suspend device */
+ char name[32];
+
+ /* Check whether sleep type is supported by the device */
+ int (*system_suspend_check)(u32 sleep_type);
+
+ /**
+ * Suspend the system
+ *
+ * @sleep_type: The sleep type identifier passed to the SBI call.
+ * @mmode_resume_addr:
+ * This is the same as sbi_scratch.warmboot_addr. Some platforms
+ * may not be able to return from system_suspend(), so they will
+ * jump directly to this address instead. Platforms which can
+ * return from system_suspend() may ignore this parameter.
+ */
+ int (*system_suspend)(u32 sleep_type, unsigned long mmode_resume_addr);
+};
+
+const struct sbi_system_suspend_device *sbi_system_suspend_get_device(void);
+void sbi_system_suspend_set_device(struct sbi_system_suspend_device *dev);
+bool sbi_system_suspend_supported(u32 sleep_type);
+int sbi_system_suspend(u32 sleep_type, ulong resume_addr, ulong opaque);
+
#endif
diff --git a/lib/sbi/Kconfig b/lib/sbi/Kconfig
index ef6728b..7eb3273 100644
--- a/lib/sbi/Kconfig
+++ b/lib/sbi/Kconfig
@@ -22,6 +22,10 @@ config SBI_ECALL_SRST
bool "System Reset extension"
default y
+config SBI_ECALL_SUSP
+ bool "System Suspend extension"
+ default y
+
config SBI_ECALL_PMU
bool "Performance Monitoring Unit extension"
default y
diff --git a/lib/sbi/objects.mk b/lib/sbi/objects.mk
index 319f38d..770238b 100644
--- a/lib/sbi/objects.mk
+++ b/lib/sbi/objects.mk
@@ -34,6 +34,9 @@ libsbi-objs-$(CONFIG_SBI_ECALL_HSM) += sbi_ecall_hsm.o
carray-sbi_ecall_exts-$(CONFIG_SBI_ECALL_SRST) += ecall_srst
libsbi-objs-$(CONFIG_SBI_ECALL_SRST) += sbi_ecall_srst.o
+carray-sbi_ecall_exts-$(CONFIG_SBI_ECALL_SUSP) += ecall_susp
+libsbi-objs-$(CONFIG_SBI_ECALL_SUSP) += sbi_ecall_susp.o
+
carray-sbi_ecall_exts-$(CONFIG_SBI_ECALL_PMU) += ecall_pmu
libsbi-objs-$(CONFIG_SBI_ECALL_PMU) += sbi_ecall_pmu.o
diff --git a/lib/sbi/sbi_ecall_susp.c b/lib/sbi/sbi_ecall_susp.c
new file mode 100644
index 0000000..f20126c
--- /dev/null
+++ b/lib/sbi/sbi_ecall_susp.c
@@ -0,0 +1,48 @@
+// SPDX-License-Identifier: BSD-2-Clause
+#include <sbi/sbi_ecall.h>
+#include <sbi/sbi_ecall_interface.h>
+#include <sbi/sbi_error.h>
+#include <sbi/sbi_trap.h>
+#include <sbi/sbi_system.h>
+
+static int sbi_ecall_susp_handler(unsigned long extid, unsigned long funcid,
+ const struct sbi_trap_regs *regs,
+ unsigned long *out_val,
+ struct sbi_trap_info *out_trap)
+{
+ int ret = SBI_ENOTSUPP;
+
+ if (funcid == SBI_EXT_SUSP_SUSPEND)
+ ret = sbi_system_suspend(regs->a0, regs->a1, regs->a2);
+
+ if (ret >= 0) {
+ *out_val = ret;
+ ret = 0;
+ }
+
+ return ret;
+}
+
+static int sbi_ecall_susp_probe(unsigned long extid, unsigned long *out_val)
+{
+ u32 type, count = 0;
+
+ /*
+ * At least one suspend type should be supported by the
+ * platform for the SBI SUSP extension to be usable.
+ */
+ for (type = 0; type <= SBI_SUSP_SLEEP_TYPE_LAST; type++) {
+ if (sbi_system_suspend_supported(type))
+ count++;
+ }
+
+ *out_val = count ? 1 : 0;
+ return 0;
+}
+
+struct sbi_ecall_extension ecall_susp = {
+ .extid_start = SBI_EXT_SUSP,
+ .extid_end = SBI_EXT_SUSP,
+ .handle = sbi_ecall_susp_handler,
+ .probe = sbi_ecall_susp_probe,
+};
diff --git a/lib/sbi/sbi_init.c b/lib/sbi/sbi_init.c
index e353c33..bc60a42 100644
--- a/lib/sbi/sbi_init.c
+++ b/lib/sbi/sbi_init.c
@@ -69,6 +69,7 @@ static void sbi_boot_print_general(struct sbi_scratch *scratch)
const struct sbi_timer_device *tdev;
const struct sbi_console_device *cdev;
const struct sbi_system_reset_device *srdev;
+ const struct sbi_system_suspend_device *susp_dev;
const struct sbi_platform *plat = sbi_platform_ptr(scratch);
if (scratch->options & SBI_SCRATCH_NO_BOOT_PRINTS)
@@ -103,6 +104,9 @@ static void sbi_boot_print_general(struct sbi_scratch *scratch)
srdev = sbi_system_reset_get_device(SBI_SRST_RESET_TYPE_SHUTDOWN, 0);
sbi_printf("Platform Shutdown Device : %s\n",
(srdev) ? srdev->name : "---");
+ susp_dev = sbi_system_suspend_get_device();
+ sbi_printf("Platform Suspend Device : %s\n",
+ (susp_dev) ? susp_dev->name : "---");
/* Firmware details */
sbi_printf("Firmware Base : 0x%lx\n", scratch->fw_start);
diff --git a/lib/sbi/sbi_system.c b/lib/sbi/sbi_system.c
index f37c811..5c123a6 100644
--- a/lib/sbi/sbi_system.c
+++ b/lib/sbi/sbi_system.c
@@ -92,3 +92,29 @@ void __noreturn sbi_system_reset(u32 reset_type, u32 reset_reason)
/* If platform specific reset did not work then do sbi_exit() */
sbi_exit(scratch);
}
+
+static const struct sbi_system_suspend_device *suspend_dev = NULL;
+
+const struct sbi_system_suspend_device *sbi_system_suspend_get_device(void)
+{
+ return suspend_dev;
+}
+
+void sbi_system_suspend_set_device(struct sbi_system_suspend_device *dev)
+{
+ if (!dev || suspend_dev)
+ return;
+
+ suspend_dev = dev;
+}
+
+bool sbi_system_suspend_supported(u32 sleep_type)
+{
+ return suspend_dev && suspend_dev->system_suspend_check &&
+ suspend_dev->system_suspend_check(sleep_type);
+}
+
+int sbi_system_suspend(u32 sleep_type, ulong resume_addr, ulong opaque)
+{
+ return 0;
+}